Version: 8.3.0
SceneBlocItem.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2016 CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 
20 #include "SceneBlocItem.hxx"
21 #include "Scene.hxx"
22 #include "Menus.hxx"
23 #include "QtGuiContext.hxx"
24 #include "guiObservers.hxx"
25 #include "ComposedNode.hxx"
26 #include "Proc.hxx"
27 #include "OutputPort.hxx"
28 #include "OutGate.hxx"
29 #include "InputPort.hxx"
30 #include "InGate.hxx"
31 
32 #include <sstream>
33 
34 #include <gvc.h>
35 
36 #include "Resource.hxx"
37 
38 //#define _DEVDEBUG_
39 #include "YacsTrace.hxx"
40 
41 using namespace std;
42 using namespace YACS::ENGINE;
43 using namespace YACS::HMI;
44 
48 #define DPI 72.
49 
50 SceneBlocItem::SceneBlocItem(QGraphicsScene *scene, SceneItem *parent,
51  QString label, Subject *subject)
52  : SceneComposedNodeItem(scene, parent, label, subject)
53 {
54  DEBTRACE("SceneBlocItem::SceneBlocItem " <<label.toStdString());
55  _format = "%1"; // --- format to convert a float without locale: ex. 9.81
56 }
57 
59 {
60 }
61 
63 
67 {
68 #ifdef _DEVDEBUG_
69  DEBTRACE("SceneBlocItem::arrangeChildNodes");
70  clock_t start_t, end_t;
71  start_t = clock();
72 #endif //_DEVDEBUG_
73  GVC_t* aGvc = 0;
74 
75 
76  SubjectComposedNode *scnode = dynamic_cast<SubjectComposedNode*>(getSubject());
77  YASSERT(scnode);
78  ComposedNode *cnode = dynamic_cast<ComposedNode*>(scnode->getNode());
79  YASSERT(cnode);
80 
81  // ---- Create a graphviz context
82 
83  if(!aGvc)
84  {
85  DEBTRACE(setlocale(LC_ALL,NULL));
86  //Graphviz is sensitive to locale : set the mimimal one ("C")for numeric
87  setlocale(LC_NUMERIC, "C");
88  //aginit();
89  aGvc = gvContext();
90  }
91 
92  // ---- Create a graph
93 
94  _graph = agopen((char*)( cnode->getName().c_str()), Agdirected, NULL);
95 
96  // ---- Initialize and set attributes for the graph
97 
98  agattr(_graph, AGRAPH, const_cast<char*>("compound"), const_cast<char*>("true"));
99  agattr(_graph, AGRAPH, const_cast<char*>("rankdir"), const_cast<char*>("LR"));
100  agattr(_graph, AGRAPH, const_cast<char*>("dpi"), const_cast<char*>("72"));
101  agattr(_graph, AGRAPH, const_cast<char*>("label"), const_cast<char*>("myLabel"));
102  agattr(_graph, AGRAPH, const_cast<char*>("labelloc"), const_cast<char*>("top"));
103  agattr(_graph, AGRAPH, const_cast<char*>("fontsize"), const_cast<char*>("24"));
104  agattr(_graph, AGRAPH, const_cast<char*>("splines"), const_cast<char*>(""));
105 
106  // --- Initialize attributes for nodes
107 
108  agattr(_graph, AGNODE, const_cast<char*>("height"), const_cast<char*>("" ));
109  agattr(_graph, AGNODE, const_cast<char*>("width"), const_cast<char*>("" ));
110  agattr(_graph, AGNODE, const_cast<char*>("shape"), const_cast<char*>("" ));
111  agattr(_graph, AGNODE, const_cast<char*>("fixedsize"), const_cast<char*>("false" ));
112 
113  // ---- Bind graph to graphviz context - must be done before layout
114  // ---- Compute a layout
115 
116  try
117  {
118  getNodesInfo(cnode);
119  // createGraphvizNodes(cnode);
120  DEBTRACE("end of graphviz input");
121 #ifdef _DEVDEBUG_
122  agwrite(_graph, stderr);
123 #endif
124  //DEBTRACE("external render for test");
125  //gvRenderFilename(aGvc, _mainGraph, "dot", "graph1.dot");
126  DEBTRACE("compute layout");
127  gvLayout(aGvc, _graph, "dot");
128  DEBTRACE("external render for test");
129 #ifdef _DEVDEBUG_
130  gvRenderFilename(aGvc, _graph, "dot", "graph2.dot");
131 #endif
132  }
133  catch (std::exception &e)
134  {
135  DEBTRACE("Exception Graphviz layout: " << e.what());
136  return;
137  }
138  catch (...)
139  {
140  DEBTRACE("Unknown Exception Graphviz layout ");
141  return;
142  }
143 #ifdef _DEVDEBUG_
144  {
145  end_t = clock();
146  double passe = (end_t -start_t);
147  passe = passe/CLOCKS_PER_SEC;
148  DEBTRACE("graphviz : " << passe);
149  start_t = end_t;
150  }
151 #endif //_DEVDEBUG_
152  DEBTRACE("start of display");
153  // ---- layout Canvas nodes recursively
154 
155  arrangeCanvasNodes(cnode);
156 
157  DEBTRACE("clean up graphviz");
158  // ---- Delete layout
159 
160  gvFreeLayout(aGvc, _graph);
161 
162  // ---- Free graph structures
163 
164  agclose(_graph) ;
165 
166  // ---- Free context and return number of errors
167 
168  gvFreeContext( aGvc );
169 
170  // --- update scene
171 #ifdef _DEVDEBUG_
172  {
173  end_t = clock();
174  double passe = (end_t -start_t);
175  passe = passe/CLOCKS_PER_SEC;
176  DEBTRACE("display : " << passe);
177  start_t = end_t;
178  }
179 #endif //_DEVDEBUG_
180 }
181 
183 {
184  Proc *proc = GuiContext::getCurrent()->getProc();
185 
186  // --- Create Nodes = direct descendants in the bloc
187 
188  list<Node*> children = cnode->edGetDirectDescendants();
189  for (list<Node*>::iterator it = children.begin(); it != children.end(); ++it)
190  {
191  Agnode_t* aNode = agnode(_graph, (char*)(proc->getChildName(*it).c_str()), 1);
192  DEBTRACE("Add node in graph: " << agnameof(aNode));
193 
196  double nh = sci->getHeight();
197  double nw = sci->getWidth();
198  double lh = nh/DPI;
199  double lw = nw/DPI;
200 
201  QString height, width;
202  height = QString(_format.c_str()).arg(lh, 0, 'g', 3);
203  width = QString(_format.c_str()).arg(lw, 0, 'g', 3);
204 
205  DEBTRACE(agnameof(aNode) << " (" << nh << "," << nw << ") = (" << height.toStdString() << " ; " << width.toStdString() <<")");
206  agset(aNode, const_cast<char*>("height"), height.toLatin1().data());
207  agset(aNode, const_cast<char*>("width"), width.toLatin1().data());
208  agset(aNode, const_cast<char*>("shape"), const_cast<char*>("box") );
209  agset(aNode, const_cast<char*>("fixedsize"), const_cast<char*>("true") );
210  }
211 
212  // --- Create edges (i.e. links)
213 
214  Agnode_t* aNode;
215  for (aNode = agfstnode(_graph); aNode; aNode = agnxtnode(_graph, aNode))
216  {
217  string aNodeName = agnameof(aNode);
218  DEBTRACE("--- tail node " << aNodeName);
219  Agnode_t* aTailNode = aNode;
220  Node* outNode = proc->getChildByName(string(agnameof(aTailNode)));
221  if (outNode->getFather() != cnode)
222  {
223  DEBTRACE(" =========== problem here ! =============================");
224  continue; // Create edges only with outgoing nodes directly in bloc
225  }
226 
227  // --- control link from node, keep only link staying inside the bloc
228 
229  {
230  OutGate *outGate = outNode->getOutGate();
231  list<InGate*> setOfInGate = outGate->edSetInGate();
232  list<InGate*>::const_iterator itin = setOfInGate.begin();
233  for (; itin != setOfInGate.end(); ++itin)
234  {
235  Node *inNode = (*itin)->getNode();
236  string inName = proc->getChildName(inNode);
237  DEBTRACE("--- control link from tail node: --- "<<inName);
238  // --- isInMyDescendance(this) return this
239  // isInMyDescendance(inNode) return direct child if inNode is a direct child or grandchild
240  if (Node *inDCNode = cnode->isInMyDescendance(inNode))
241  {
242  DEBTRACE("--- edge inside the bloc " << inDCNode->getName());
243  string inDCName = proc->getChildName(inDCNode);
244  Agnode_t* aHeadNode = agnode(_graph, (char*)(inDCName.c_str()), 1);
245  Agedge_t* anEdge = agedge(_graph, aTailNode, aHeadNode, NULL, 1);
246  DEBTRACE("--- control link from tail node: --- " << agnameof(aNode) << " --> " << inDCName);
247  }
248  }
249  }
250 
251  // --- datalink from node, keep only link staying inside the bloc
252 
253  {
254  list<OutPort*> outPortList = outNode->getSetOfOutPort();
255  list<OutPort*>::const_iterator itou = outPortList.begin();
256  for (; itou != outPortList.end(); ++itou)
257  {
258  set<InPort*> inPortList = (*itou)->edSetInPort();
259  set<InPort*>::const_iterator itin = inPortList.begin();
260  for (; itin != inPortList.end(); ++itin)
261  {
262  Node *inNode = (*itin)->getNode();
263  string inName = proc->getChildName(inNode);
264  DEBTRACE("------ data link from tail node: ---- ");
265  if (Node *inDCNode = cnode->isInMyDescendance(inNode))
266  {
267  DEBTRACE("--- edge inside the bloc " << inDCNode->getName());
268  string inDCName = proc->getChildName(inDCNode);
269  Agnode_t* aHeadNode = agnode(_graph, (char*)(inDCName.c_str()), 1);
270  Agedge_t* anEdge = agedge(_graph, aTailNode, aHeadNode, NULL, 1);
271  DEBTRACE("------ data link from tail node: ---- " << agnameof(aNode) << " --> " << inDCName);
272  }
273  }
274  }
275  }
276  }
277 }
278 
279 
281 {
282  DEBTRACE("SceneBlocItem::arrangeCanvasNodes");
283  Proc *proc = GuiContext::getCurrent()->getProc();
284 
287  SceneComposedNodeItem *sceneCompo = dynamic_cast<SceneComposedNodeItem*>(sci);
288  YASSERT(sceneCompo);
289  qreal yHead = sceneCompo->getHeaderBottom() + Resource::Space_Margin;
290  qreal xOffset = Resource::Space_Margin;
291 
292  list<Node*> children = cnode->edGetDirectDescendants();
293  for (list<Node*>::iterator it = children.begin(); it != children.end(); ++it)
294  {
295  Agnode_t* aNode = agnode(_graph, (char*)(proc->getChildName(*it).c_str()), 1);
296  DEBTRACE("Get node in graph: " << agnameof(aNode));
299 
300  qreal xCenter = ND_coord(aNode).x;
301  qreal yCenter = ND_coord(aNode).y;
302  qreal halfWidth = sci->boundingRect().width()/2.;
303  qreal halfHeight = sci->boundingRect().height()/2.;
304 
305  sci->setPos(xOffset + xCenter -halfWidth, yHead + yCenter -halfHeight);
306  SceneNodeItem *scni = dynamic_cast<SceneNodeItem*>(sci);
307  if (scni) scni->setExpandedPos(QPointF(xOffset + xCenter -halfWidth, yHead + yCenter -halfHeight));
308  }
309  sceneCompo->checkGeometryChange();
311  {
314  SceneComposedNodeItem *proc = dynamic_cast<SceneComposedNodeItem*>(item);
315  proc->rebuildLinks();
316  }
317 
318 }