CustusX  2023.01.05-dev+develop.0da12
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) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 #include "cxTreeRepository.h"
12 #include "cxPatientModelService.h"
13 #include "cxDefinitions.h"
14 #include "cxData.h"
15 #include "cxTreeNode.h"
16 #include "cxDataTreeNode.h"
17 #include "cxSpaceTreeNode.h"
18 #include "cxGroupTreeNode.h"
19 #include "cxTopTreeNode.h"
20 #include "cxToolTreeNode.h"
21 #include "cxLogger.h"
22 #include "cxTrackingService.h"
23 #include "cxActiveData.h"
24 #include "cxVisServices.h"
25 #include "cxShowDataTreeNode.h"
26 #include "cxViewServiceTreeNode.h"
27 #include "cxViewGroupTreeNode.h"
28 #include "cxViewService.h"
29 #include "cxStringListProperty.h"
30 #include "cxStringProperty.h"
31 
32 namespace cx
33 {
34 
35 boost::shared_ptr<QWidget> WidgetTypeRepository::findMetricWidget(DataPtr data)
36 {
37  for (unsigned i=0; i<mWidgets.size(); ++i)
38  {
39  boost::shared_ptr<SingleMetricWidget> w = boost::dynamic_pointer_cast<SingleMetricWidget>(mWidgets[i]);
40  if(w && w->getData() && data && w->getData()->getUid() == data->getUid())
41  return w;
42  }
43  return boost::shared_ptr<QWidget>();
44 }
45 
46 void WidgetTypeRepository::add(boost::shared_ptr<QWidget> widget)
47 {
48  mWidgets.push_back(widget);
49 }
50 
51 //---------------------------------------------------------
52 //---------------------------------------------------------
53 //---------------------------------------------------------
54 
56 {
57  TreeRepositoryPtr retval(new TreeRepository(options, services));
58  retval->mSelf = retval;
59  retval->insertTopNode();
60  return retval;
61 }
62 
63 TreeRepository::TreeRepository(XmlOptionFile options, VisServicesPtr services) :
64  mInvalid(true),
65  mServices(services),
66  mOptions(options)
67 {
68  this->createVisibilityProperty();
69  this->createModeProperty();
70 
71  mWidgetTypeRepository.reset(new WidgetTypeRepository());
72 
73  this->startListen();
74 }
75 
76 void TreeRepository::createVisibilityProperty()
77 {
78  QStringList allNodeTypes = QStringList() << "data" << "metric" << "image" << "model" << "tool" << "view";
79  mVisibilityProperty = StringListProperty::initialize("visible_node_types",
80  "Visibility",
81  "Select visible node types",
82  allNodeTypes,
83  allNodeTypes,
84  mOptions.getElement());
85  connect(mVisibilityProperty.get(), &StringListProperty::changed, this, &TreeRepository::invalidate);
86 }
87 
88 void TreeRepository::createModeProperty()
89 {
90  QStringList allModes = QStringList() << "spaces" << "flat";
91 
92  mModeProperty = StringProperty::initialize("mode",
93  "mode",
94  "Node display mode",
95  allModes.front(),
96  allModes,
97  mOptions.getElement());
98  connect(mModeProperty.get(), &Property::changed, this, &TreeRepository::loaded);
99 }
100 
102 {
103  this->stopListen();
104 }
105 
107 {
108 // CX_LOG_CHANNEL_DEBUG("CA") << "TreeRepository::update(), invalid=" << mInvalid;
109  if (mInvalid)
110  this->rebuild();
111  mInvalid = true;
112 }
113 
115 {
116 // CX_LOG_CHANNEL_DEBUG("CA") << "TreeRepository::invalidate()";
117  mInvalid = true;
118  emit invalidated();
119 }
120 
121 void TreeRepository::startListen()
122 {
123  connect(this->getServices()->patient().get(), &PatientModelService::patientChanged, this, &TreeRepository::loaded);
124  connect(this->getServices()->patient().get(), &PatientModelService::dataAddedOrRemoved, this, &TreeRepository::invalidate);
125  connect(this->getServices()->tracking().get(), &TrackingService::stateChanged, this, &TreeRepository::loaded);
126  connect(this->getServices()->patient()->getActiveData().get(), &ActiveData::activeDataChanged, this, &TreeRepository::onChanged);
127 }
128 
129 void TreeRepository::stopListen()
130 {
131  disconnect(this->getServices()->patient().get(), &PatientModelService::patientChanged, this, &TreeRepository::loaded);
132  disconnect(this->getServices()->patient().get(), &PatientModelService::dataAddedOrRemoved, this, &TreeRepository::invalidate);
133  disconnect(this->getServices()->tracking().get(), &TrackingService::stateChanged, this, &TreeRepository::loaded);
134  disconnect(this->getServices()->patient()->getActiveData().get(), &ActiveData::activeDataChanged, this, &TreeRepository::onChanged);
135 }
136 
137 std::vector<TreeNodePtr> TreeRepository::getNodes()
138 {
139  return mNodes;
140 }
141 
143 {
144  for (unsigned i=0; i<mNodes.size(); ++i)
145  {
146  if (mNodes[i]->getUid()==uid)
147  return mNodes[i];
148  }
149  return TreeNodePtr();
150 }
151 
153 {
154  std::vector<TreeNodePtr> all = this->getNodes();
155  for (unsigned i=0; i<all.size(); ++i)
156  if (all[i]->getUid() == "node::invisible_top")
157  return all[i];
158  CX_LOG_CHANNEL_DEBUG("CA") << "invalid tree - did not find top node";
159  return TreeNodePtr();
160 }
161 
163 {
164  return mServices;
165 }
166 
168 {
169  return mWidgetTypeRepository;
170 }
171 
172 QString TreeRepository::getMode() const
173 {
174  return mModeProperty->getValue();
175 }
176 
178 {
179  return mVisibilityProperty->getValue();
180 }
181 
183 {
184  return mVisibilityProperty->getValueRange();
185 }
186 
187 void TreeRepository::insertTopNode()
188 {
189  // TreeNodePtr topnode(new TopTreeNode(mSelf));
190 // mNodes.push_back(topnode);
191  this->appendNode(new TopTreeNode(mSelf));
192 // CX_LOG_CHANNEL_DEBUG("CA") << " - built topnode";
193 }
194 
195 void TreeRepository::rebuild()
196 {
197 // CX_LOG_CHANNEL_DEBUG("CA") << " reuild tree...";
198  for (unsigned i=0; i<mNodes.size(); ++i)
199  disconnect(mNodes[i].get(), &TreeNode::changed, this, &TreeRepository::onChanged);
200  mNodes.clear();
201 
202  this->insertTopNode();
203 
204  QStringList groups = QStringList() << "tool" << "data" << "space" << "view";
205  for (unsigned i=0; i<groups.size(); ++i)
206  this->insertGroupNode(groups[i]);
207 
208  this->insertSpaceNode(CoordinateSystem(csREF));
209 
210  std::map<QString, DataPtr> source = this->getServices()->patient()->getDatas();
211  for (std::map<QString, DataPtr>::const_iterator iter = source.begin(); iter != source.end(); ++iter)
212  {
213  this->insertDataNode(iter->second);
214  }
215  for (std::map<QString, DataPtr>::const_iterator iter = source.begin(); iter != source.end(); ++iter)
216  {
217  QString space = iter->second->getParentSpace();
218  if (space.isEmpty())
219  continue;
220  if (source.count(space))
221  continue;
222  this->insertSpaceNode(CoordinateSystem(csDATA, space));
223  }
224 
225  this->insertSpaceNode(CoordinateSystem(csPATIENTREF));
226 
227  std::map<QString, ToolPtr> tools = this->getServices()->tracking()->getTools();
228  for (std::map<QString, ToolPtr>::const_iterator iter = tools.begin(); iter != tools.end(); ++iter)
229  {
230  this->insertToolNode(iter->second);
231  }
232 
233  for (unsigned i=0; i<this->getServices()->view()->groupCount(); ++i)
234  {
235  this->appendNode(new ViewGroupTreeNode(mSelf, i));
236  }
237 
238 // for (unsigned i=0; i<mNodes.size(); ++i)
239 // CX_LOG_CHANNEL_DEBUG("CA") << " node: " << mNodes[i]->getUid();
240 }
241 
242 void TreeRepository::insertGroupNode(QString groupname)
243 {
244  if (this->getNodeForGroup(groupname))
245  return;
246  if (groupname=="view")
247  this->appendNode(new ViewServiceTreeNode(mSelf));
248  else
249  this->appendNode(new GroupTreeNode(mSelf, groupname));
250 }
251 
253 {
254  return this->getNode(QString("group_%1").arg(groupname));
255 }
256 
257 void TreeRepository::insertToolNode(ToolPtr tool)
258 {
259  if (this->getNode(tool->getUid()))
260  return;
261  this->appendNode(new ToolTreeNode(mSelf, tool));
262 }
263 
264 void TreeRepository::insertDataNode(DataPtr data)
265 {
266  if (this->getNode(data->getUid()))
267  return;
268 
269  this->appendNode(new DataTreeNode(mSelf, data));
270 
271  this->appendNode(new ShowVolumeDataTreeNode(mSelf, data));
272  this->appendNode(new ShowSlice2DDataTreeNode(mSelf, data));
273  this->appendNode(new ShowSlice3DDataTreeNode(mSelf, data));
274 }
275 
276 void TreeRepository::appendNode(TreeNode* rawNode)
277 {
278  TreeNodePtr bnode(rawNode);
279  TreeNodePtr node(new CachedTreeNode(bnode));
280 
281  if (!this->getNode(node->getUid()))
282  {
283  // TODO need a more detailed change policy: invalidate only when parent/childe
284  // structure is changed.
285 // connect(node.get(), &TreeNode::changed, this, &TreeRepository::invalidated);
286  connect(node.get(), &TreeNode::changed, this, &TreeRepository::onChanged);
287  mNodes.push_back(node);
288  }
289 }
290 
291 void TreeRepository::onChanged()
292 {
293  TreeNode* node = dynamic_cast<TreeNode*>(sender());
294 // CX_LOG_CHANNEL_DEBUG("CA") << " TreeRepository::onChanged() node=" << ((node)?node->getName():"-");
295  emit changed(node);
296 }
297 
298 void TreeRepository::insertSpaceNode(CoordinateSystem space)
299 {
300  if (this->getNode(space.toString()) || this->getNode(space.mRefObject))
301  return;
302  this->appendNode(new SpaceTreeNode(mSelf, space));
303 }
304 
305 
306 } // 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:40
csREF
the data reference space (r) using LPS (left-posterior-superior) coordinates.
Definition: cxDefinitions.h:90
csDATA
a datas space (d)
Definition: cxDefinitions.h:90
static StringListPropertyPtr initialize(const QString &uid, QString name, QString help, QStringList value, QStringList range, QDomNode root=QDomNode())
csPATIENTREF
the patient/tool reference space (pr)
Definition: cxDefinitions.h:90
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:107
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