VPTissue Reference Manual
PTreePanels.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2016 Universiteit Antwerpen
3  *
4  * Licensed under the EUPL, Version 1.1 or as soon they will be approved by
5  * the European Commission - subsequent versions of the EUPL (the "Licence");
6  * You may not use this work except in compliance with the Licence.
7  * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl5
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the Licence is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the Licence for the specific language governing
13  * permissions and limitations under the Licence.
14  */
20 #include "../editor/PTreePanels.h"
21 
22 #include "bio/Node.h"
23 #include "bio/Wall.h"
24 #include "bio/Cell.h"
25 #include "util/misc/Exception.h"
26 
27 #include <boost/lexical_cast.hpp>
28 #include <boost/property_tree/ptree.hpp>
29 #include <QAction>
30 #include <QDockWidget>
31 #include <QMessageBox>
32 
33 using namespace boost::property_tree;
34 using namespace SimShell;
35 using namespace SimShell::Gui;
36 
37 namespace SimPT_Editor {
38 
39 PTreePanels::PTreePanels(QWidget* parent)
40  : m_attribute_panel(new Gui::PTreeContainer("Attribute panel", parent)),
41  m_attribute_panel_toggled(true),
42  m_geometric_panel(new Gui::PTreeContainer("Geometric panel", parent)),
43  m_geometric_panel_toggled(true),
44  m_parameters_panel(new Gui::PTreeContainer("Parameters panel", parent)),
45  m_parameters_panel_toggled(true)
46 {
47  connect(m_attribute_panel->GetDock()->toggleViewAction(), SIGNAL(toggled(bool)),
48  this, SLOT(ToggleAttributePanel(bool)));
49  connect(m_geometric_panel->GetDock()->toggleViewAction(), SIGNAL(toggled(bool)),
50  this, SLOT(ToggleGeometricPanel(bool)));
51  connect(m_parameters_panel->GetDock()->toggleViewAction(), SIGNAL(toggled(bool)),
52  this, SLOT(ToggleParametersPanel(bool)));
53 
54  connect(m_attribute_panel, SIGNAL(Applied(const boost::property_tree::ptree&)),
55  this, SLOT(ApplyAttributePanel(const boost::property_tree::ptree&)));
56  connect(m_geometric_panel, SIGNAL(Applied(const boost::property_tree::ptree&)),
57  this, SLOT(ApplyGeometricPanel(const boost::property_tree::ptree&)));
58  connect(m_parameters_panel, SIGNAL(Applied(const boost::property_tree::ptree&)),
59  this, SLOT(ApplyParametersPanel(const boost::property_tree::ptree&)));
60 
61  m_geometric_panel->SetOnlyEditData(true);
62  m_attribute_panel->SetOnlyEditData(true);
63 }
64 
66 
67 void PTreePanels::ApplyAttributePanel(const ptree& pt)
68 {
69  try {
70  m_tissue->ChangeAttributes(pt);
71  }
72  catch (SimPT_Sim::Util::Exception& e) {
73  QMessageBox messageBox(m_attribute_panel->GetDock());
74  messageBox.critical(m_attribute_panel->GetDock(),
75  "Attribute parsing error", "This value isn't allowed for this attribute.");
76  UpdateAttributePanel();
77  }
78 }
79 
80 void PTreePanels::ApplyGeometricPanel(const ptree& pt)
81 {
82  try {
83  if (m_tissue->SelectedNodes().size() == 1) {
84  if (!m_tissue->MoveNode(m_tissue->SelectedNodes().front(),
85  pt.get<double>("x"), pt.get<double>("y"))) {
86  UpdateGeometricPanel();
87  } else if (m_tissue->SelectedNodes().front()->IsAtBoundary() != pt.get<bool>("boundary")) {
88  UpdateGeometricPanel();
89  }
90  } else {
91  UpdateGeometricPanel();
92  }
93  }
94  catch (ptree_bad_data& e) {
95  QMessageBox messageBox(m_geometric_panel->GetDock());
96  messageBox.critical(m_geometric_panel->GetDock(),
97  "Geometry parsing error", "This value isn't allowed for this property.");
98  UpdateGeometricPanel();
99  }
100 }
101 
102 void PTreePanels::ApplyParametersPanel(const ptree& pt)
103 {
104  m_tissue->SetParameters(pt);
105 }
106 
108 {
109  return m_attribute_panel;
110 }
111 
112 void PTreePanels::Initialize(std::shared_ptr<EditControlLogic> tissue)
113 {
114  m_tissue = tissue;
115  connect(m_tissue.get(), SIGNAL(SelectionChanged()), this, SLOT(UpdatePanels()));
116  connect(m_tissue.get(), SIGNAL(StoppedMoving()), this, SLOT(UpdateGeometricPanel()));
117 }
118 
120 {
121  return m_geometric_panel;
122 }
123 
124 ptree PTreePanels::MergeJoin(ptree pt1, ptree pt2)
125 {
126  ptree pt;
127  if (pt1.data() != pt2.data()) {
128  pt = ptree("?");
129  } else {
130  pt = ptree(pt1.data());
131  }
132 
133  if (pt1.size() == 0) {
134  return pt;
135  } else {
136  ptree::const_iterator it1 = pt1.begin();
137  ptree::const_iterator it2 = pt2.begin();
138  while (it1 != pt1.end() && it2 != pt2.end()) {
139  if (it1->first == it2->first) {
140  pt.add_child(it1->first, MergeJoin(it1->second, it2->second));
141  ++it1;
142  ++it2;
143  }
144  else if (it1->first < it2->first) {
145  pt.add_child(it1->first, SetDataToUnknown(it1->second));
146  ++it1;
147  }
148  else { //it1->first > it2->first
149  pt.add_child(it2->first, SetDataToUnknown(it2->second));
150  ++it2;
151  }
152  }
153  for (ptree::const_iterator it = it1; it != pt1.end(); ++it) {
154  pt.add_child(it->first, SetDataToUnknown(it->second));
155  }
156  for (ptree::const_iterator it = it2; it != pt2.end(); ++it) {
157  pt.add_child(it->first, SetDataToUnknown(it->second));
158  }
159 
160  return pt;
161  }
162 }
163 
165 {
166  return m_parameters_panel;
167 }
168 
169 ptree PTreePanels::SetDataToUnknown(const ptree& pt)
170 {
171  ptree new_pt("?");
172  for (const auto& v : pt) {
173  new_pt.add_child(v.first, SetDataToUnknown(v.second));
174  }
175  return new_pt;
176 }
177 
178 void PTreePanels::ToggleAttributePanel(bool toggled)
179 {
180  m_attribute_panel_toggled = toggled;
181  UpdateAttributePanel();
182 }
183 
184 void PTreePanels::ToggleGeometricPanel(bool toggled)
185 {
186  m_geometric_panel_toggled = toggled;
187  UpdateGeometricPanel();
188 }
189 
190 void PTreePanels::ToggleParametersPanel(bool toggled)
191 {
192  m_parameters_panel_toggled = toggled;
193  UpdateParametersPanel();
194 }
195 
196 void PTreePanels::UpdateAttributePanel()
197 {
198  if (!m_attribute_panel_toggled) {
199  return;
200  }
201 
202  std::string title = "Attribute panel";
203  if (m_tissue->SelectedNodes().size() > 0) {
204  auto nodes = m_tissue->SelectedNodes();
205  ptree pt = nodes.front()->ToPtree();
206  for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) {
207  pt = MergeJoin(pt, (*it)->ToPtree());
208  }
209  pt.erase("id");
210  pt.erase("x");
211  pt.erase("y");
212  pt.erase("boundary");
213  m_attribute_panel->Open(pt.get_child("attributes"));
214 
215  if (nodes.size() == 1) {
216  title += " - node "
217  + boost::lexical_cast<std::string>(nodes.front()->GetIndex());
218  } else {
219  title += " - nodes";
220  }
221  } else if (!m_tissue->SelectedWalls().empty()) {
222  auto walls = m_tissue->SelectedWalls();
223  ptree pt = walls.front()->WallAttributes::ToPtree();
224  for (auto it = std::next(walls.begin()); it != walls.end(); ++it) {
225  pt = MergeJoin(pt, (*it)->WallAttributes::ToPtree());
226  }
227  m_attribute_panel->Open(pt);
228 
229  if (walls.size() == 1) {
230  title += " - wall "
231  + boost::lexical_cast<std::string>(walls.front()->GetIndex());
232  } else {
233  title += " - walls";
234  }
235  } else if (m_tissue->SelectedCells().size() > 0) {
236  auto cells = m_tissue->SelectedCells();
237  ptree pt = cells.front()->CellAttributes::ToPtree();
238  //pt.sort();
239  for (auto it = std::next(cells.begin()); it != cells.end(); ++it) {
240  pt = MergeJoin(pt, (*it)->CellAttributes::ToPtree());
241  }
242  m_attribute_panel->Open(pt);
243 
244  if (cells.size() == 1) {
245  title += " - cell "
246  + boost::lexical_cast<std::string>(cells.front()->GetIndex());
247  } else {
248  title += " - cells";
249  }
250  } else {
251  m_attribute_panel->Open(m_tissue->ToPTree().get_child("mesh"));
252  }
253 
254  m_attribute_panel->GetDock()->setWindowTitle(QString::fromStdString(title));
255 }
256 
257 void PTreePanels::UpdateGeometricPanel()
258 {
259  if (!m_geometric_panel_toggled) {
260  return;
261  }
262 
263  std::string title = "Geometric panel";
264  if (m_tissue->SelectedNodes().size() > 0) {
265  auto nodes = m_tissue->SelectedNodes();
266 
267  ptree pt;
268  pt.add("x", (*nodes.front())[0]);
269  pt.add("y", (*nodes.front())[1]);
270  pt.add("boundary", nodes.front()->IsAtBoundary());
271  for (auto it = std::next(nodes.begin()); it != nodes.end(); ++it) {
272  ptree node_pt = (*it)->ToPtree();
273  if (pt.get<std::string>("x") != "?") {
274  if (pt.get<double>("x") != node_pt.get<double>("x")) {
275  pt.put("x", "?");
276  }
277  }
278  if (pt.get<std::string>("y") != "?") {
279  if (pt.get<double>("y") != node_pt.get<double>("y")) {
280  pt.put("y", "?");
281  }
282  }
283  if (pt.get<std::string>("boundary") != "?") {
284  if (pt.get<bool>("boundary") != node_pt.get<bool>("boundary")) {
285  pt.put("boundary", "?");
286  }
287  }
288  }
289  m_geometric_panel->Open(pt);
290 
291  if (nodes.size() == 1) {
292  title += " - node " + boost::lexical_cast<std::string>(nodes.front()->GetIndex());
293  } else {
294  title += " - nodes";
295  }
296  } else if (m_tissue->SelectedWalls().size() > 0) {
297  auto walls = m_tissue->SelectedWalls();
298 
299  ptree pt = walls.front()->ToPtree();
300  //pt.sort();
301  for (auto it = std::next(walls.begin()); it != walls.end(); ++it) {
302  pt = MergeJoin(pt, (*it)->ToPtree());
303  }
304  pt.erase("id");
305  pt.erase("attributes");
306  m_geometric_panel->Open(pt);
307 
308  if (walls.size() == 1) {
309  title += " - wall " + boost::lexical_cast<std::string>(walls.front()->GetIndex());
310  }
311  else {
312  title += " - walls";
313  }
314  } else if (m_tissue->SelectedCells().size() > 0) {
315  auto cells = m_tissue->SelectedCells();
316 
317  ptree pt = cells.front()->GeometryToPtree();
318  for (auto it = std::next(cells.begin()); it != cells.end(); ++it) {
319  pt = MergeJoin(pt, (*it)->GeometryToPtree());
320  }
321  pt.erase("id");
322  m_geometric_panel->Open(pt);
323 
324  if (cells.size() == 1) {
325  title += " - cell " + boost::lexical_cast<std::string>(cells.front()->GetIndex());
326  }
327  else {
328  title += " - cells";
329  }
330  } else {
331  m_geometric_panel->Open(m_tissue->ToPTree().get_child("mesh"));
332  }
333 
334  m_geometric_panel->GetDock()->setWindowTitle(QString::fromStdString(title));
335 }
336 
337 void PTreePanels::UpdateParametersPanel()
338 {
339  m_parameters_panel->Open(m_tissue->GetParameters());
340 }
341 
342 void PTreePanels::UpdatePanels()
343 {
344  UpdateAttributePanel();
345  UpdateGeometricPanel();
346 }
347 
348 } // namespace
void SetOnlyEditData(bool)
If true, the user can't insert, move, delete or edit keys.
Namespace for SimPT tissue editor package.
Definition: Cell.h:32
Gui::PTreeContainer * ParametersPanel() const
Get the parameters panel.
Namespace for graphical interface classes.
bool Open(boost::property_tree::ptree const &pt, QString const &edit_path="")
Open ptree with given edit path.
Extremely simple Exception root class.
Definition: Exception.h:28
Interface for Cell.
QDockWidget * GetDock() const
Get the associated dock widget, containing the ptree editor.
Interface for Node.
void Initialize(std::shared_ptr< EditControlLogic > tissue)
Initializes the panels with a given tissue.
see the online Qt documentation
virtual ~PTreePanels()
Destructor.
Definition: PTreePanels.cpp:65
CircularIterator< T > next(CircularIterator< T > i)
Helper yields the position the iterator would have if moved forward (in circular fashion) by 1 positi...
Header file for Exception class.
Gui::PTreeContainer * AttributePanel() const
Get the attribute panel.
Namespace for generic graphical shell for simulators.
Definition: SimSession.h:32
Gui::PTreeContainer * GeometricPanel() const
Get the geometric panel.
For a given ptree, constructs PTreeMenu, QDockWidget, PTreeEditorWindow.
Interface for Wall.