Salome HOME
Updated copyright comment
[modules/yacs.git] / src / genericgui / GuiEditor.cxx
1 // Copyright (C) 2006-2024  CEA, EDF
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 <Python.h>
21 #include "GuiEditor.hxx"
22 #include "RuntimeSALOME.hxx"
23 #include "Proc.hxx"
24 #include "Node.hxx"
25 #include "ForEachLoop.hxx"
26 #include "Catalog.hxx"
27 #include "Container.hxx"
28 #include "ComponentInstance.hxx"
29 #include "guiObservers.hxx"
30 #include "QtGuiContext.hxx"
31 #include "TypeCode.hxx"
32 #include "Scene.hxx"
33 #include "SceneComposedNodeItem.hxx"
34 #include "SceneLinkItem.hxx"
35 #include "Catalog.hxx"
36 #include "ItemMimeData.hxx"
37 #include "Message.hxx"
38 #include "Resource.hxx"
39 #include "FormUndoRedo.hxx"
40 #include <QMessageBox>
41
42 #include <string>
43 #include <sstream>
44 #include <iostream>
45
46 //#define _DEVDEBUG_
47 #include "YacsTrace.hxx"
48
49 using namespace std;
50 using namespace YACS::ENGINE;
51 using namespace YACS::HMI;
52
53 GuiEditor::GuiEditor()
54 {
55   // approximative conversion from latin1 to US ascii (removing accentuation)
56   DEBTRACE("GuiEditor::GuiEditor");
57   _table    = "________________"  ; //   0 -  15
58   _table   += "________________"  ; //  16 -  31
59   _table   += " !\"#$%&'()*+,-./" ; //  32 -  47
60   _table   += "0123456789:;<=>?"  ; //  48 -  63
61   _table   += "@ABCDEFGHIJKLMNO"  ; //  64 -  79
62   _table   += "PQRSTUVWXYZ[\\]^_" ; //  80 -  95
63   _table   += "`abcdefghijklmno"  ; //  96 - 111
64   _table   += "pqrstuvwxyz{|}~_"  ; // 112 - 127
65   _table   += "________________"  ; // 128 - 143
66   _table   += "________________"  ; // 144 - 159
67   _table   += "_icLoY|-_ca-__r-" ;  // 160 - 175
68   _table   += "-_23'u_..10\"___?" ;  // 176 - 191
69   _table   += "AAAAAAACEEEEIIII"  ; // 192 - 207
70   _table   += "DNOOOOOx0UUUUYPB"  ; // 208 - 223
71   _table   += "aaaaaaaceeeeiiii"  ; // 224 - 239
72   _table   += "onooooo-0uuuuypy"  ; // 240 - 255
73   //_table[167] = char(167); // '§'
74   //_table[176] = char(176); // '°'
75   DEBTRACE(_table.size() << " " << _table);
76 }
77
78 GuiEditor::~GuiEditor()
79 {
80   DEBTRACE("GuiEditor::~GuiEditor");
81 }
82
83 void GuiEditor::CreateNodeFromCatalog(const ItemMimeData* myData, SubjectComposedNode *cnode,bool createNewComponentInstance)
84 {
85   DEBTRACE("GuiEditor::CreateNodeFromCatalog");
86   int nb = myData->getDataSize();
87   DEBTRACE(nb);
88   for (int i=0; i<nb; i++)
89     {
90       Catalog* catalog = myData->getCatalog(i);
91       string compoName =  myData->getCompo(i);
92       string service = myData->getType(i);
93       DEBTRACE(compoName << "/" << service);
94       _createNode(catalog, cnode, service, compoName,createNewComponentInstance);
95     }
96 }
97
98 SubjectNode* GuiEditor::CreateNode(std::string typeNode)
99 {
100   DEBTRACE("GuiEditor::CreateNode " << typeNode);
101   YACS::ENGINE::Catalog *catalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog();
102
103   Subject *sub = QtGuiContext::getQtCurrent()->getSelectedSubject();
104   if (!sub)
105     {
106       DEBTRACE("GuiEditor::CreateNode : invalid selection!");
107       return 0;
108     }
109   DEBTRACE(sub->getName());
110
111   YACS::HMI::SubjectComposedNode *cnode = dynamic_cast< YACS::HMI::SubjectComposedNode*>(sub);
112   if (!cnode)
113     {
114       DEBTRACE("GuiEditor::CreateNode : no ComposedNode selected!");
115       return 0;
116     }
117
118   return _createNode(catalog, cnode, typeNode, "", Resource::COMPONENT_INSTANCE_NEW); 
119 }
120
121 SubjectNode* GuiEditor::_createNode(YACS::ENGINE::Catalog* catalog,
122                                     SubjectComposedNode *cnode,
123                                     std::string service,
124                                     std::string compoName,
125                                     bool createNewComponentInstance)
126 {
127   SubjectNode* aNewNode = 0;
128
129   // --- find a name not used
130
131   string name = service;
132   if (name == "PresetNode")
133     name = "DataIn";
134   Node *node =cnode->getNode();
135   ComposedNode *father = dynamic_cast<ComposedNode*>(node);
136   YASSERT(father);
137   list<Node*> children = father->edGetDirectDescendants();
138   bool nameInUse = true;
139   std::stringstream tryname;
140   while (nameInUse)
141     {
142       nameInUse = false;
143       long newid = GuiContext::getCurrent()->getNewId();
144       tryname.str("");
145       tryname << name << newid;
146       if (newid > 100000) break; 
147       for (list<Node*>::iterator it = children.begin(); it != children.end(); ++it)
148         {
149           if ((*it)->getName() == tryname.str())
150             nameInUse = true;
151         }
152     }
153   name = tryname.str();
154
155   int swCase = 0;
156   SubjectSwitch *aSwitch = dynamic_cast<SubjectSwitch*>(cnode);
157   if (aSwitch)
158     {
159       map<int, SubjectNode*> bodyMap = aSwitch->getBodyMap();
160       if (bodyMap.empty()) swCase = 1;
161       else
162         {
163           map<int, SubjectNode*>::reverse_iterator rit = bodyMap.rbegin();
164           swCase = (*rit).first + 1;
165         }
166       aNewNode = aSwitch->addNode(catalog, compoName, service, name, createNewComponentInstance, swCase);
167       if (!aNewNode)
168         Message mess;
169     }
170   else if (cnode && (dynamic_cast<SubjectBloc*>(cnode) == 0) && cnode->getChild() != 0)
171     {
172       // loop with a body : can't add a node
173       QMessageBox msgBox;
174       std::string msg;
175       msg="This loop has already a body. It is not possible to add directly another node\n";
176       msg=msg+"Do you want to put the existing node in a bloc and add the new node in this bloc ?\n";
177       msgBox.setText(msg.c_str());
178       msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No );
179       msgBox.setDefaultButton(QMessageBox::No);
180       int ret = msgBox.exec();
181       if(ret == QMessageBox::Yes)
182         {
183           // User wants to put body node in bloc
184           if (cnode->getChild()->putInComposedNode("Bloc1","Bloc"))
185             {
186               //the bloc has been successfully created. Add the new node
187               SubjectBloc* newbloc = dynamic_cast<SubjectBloc*>(cnode->getChild());
188               aNewNode = newbloc->addNode(catalog, compoName, service, name, createNewComponentInstance);
189               if (!aNewNode)
190                 Message mess;
191             }
192           else
193             Message mess;
194         }
195     }
196   else if (cnode)
197     aNewNode = cnode->addNode(catalog, compoName, service, name, createNewComponentInstance);
198     if (!aNewNode)
199       Message mess;
200   return aNewNode;
201 }
202
203 void GuiEditor::AddTypeFromCatalog(const ItemMimeData* myData)
204 {
205   DEBTRACE("GuiEditor::AddTypeFromCatalog");
206   SubjectProc* sProc = QtGuiContext::getQtCurrent()->getSubjectProc();
207   int nb = myData->getDataSize();
208   DEBTRACE(nb);
209   for (int i=0; i<nb; i++)
210     {
211       Catalog* catalog = myData->getCatalog(i);
212       DEBTRACE("catalog " << catalog);
213       string aType = myData->getType(i);
214       DEBTRACE(aType);
215       sProc->addDataType(catalog, aType);
216     }
217 }
218
219 void GuiEditor::CreateBloc()
220 {
221   DEBTRACE("GuiEditor::CreateBloc");
222   CreateNode("Bloc");
223 }
224
225 void GuiEditor::CreateForLoop()
226 {
227   DEBTRACE("GuiEditor::CreateForLoop");
228   CreateNode("ForLoop");
229 }
230
231 void GuiEditor::CreateForEachLoop(std::string type)
232 {
233   DEBTRACE("GuiEditor::CreateForEachLoop");
234   // The ForEachLoop node for datatype type must exist in builtin catalog
235   // So  create it in builtin catalog if it does not exist and datatype is loaded in the current Proc
236   YACS::ENGINE::Catalog *catalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog();
237   Proc* proc = GuiContext::getCurrent()->getProc();
238   std::string typeName="ForEachLoop_"+type;
239   if (!catalog->_composednodeMap.count(typeName))
240     {
241       if(proc->typeMap.count(type))
242         {
243           catalog->_composednodeMap[typeName]=new ForEachLoop(typeName,proc->typeMap[type]);
244         }
245     }
246   CreateNode(typeName);
247 }
248
249 void GuiEditor::CreateWhileLoop()
250 {
251   DEBTRACE("GuiEditor::CreateWhileLoop");
252   CreateNode("WhileLoop");
253 }
254
255 void GuiEditor::CreateSwitch()
256 {
257   DEBTRACE("GuiEditor::CreateSwitch");
258   CreateNode("Switch");
259 }
260
261 void GuiEditor::CreateOptimizerLoop()
262 {
263   DEBTRACE("GuiEditor::CreateOptimizerLoop");
264   CreateNode("OptimizerLoop");
265 }
266
267 void GuiEditor::CreateContainer()
268 {
269   DEBTRACE("GuiEditor::CreateContainer");
270   SubjectProc *sproc = QtGuiContext::getQtCurrent()->getSubjectProc();
271   YASSERT(sproc);
272   SubjectContainerBase *scont = 0;
273   while (!scont)
274     {
275       std::stringstream name;
276       long newid = GuiContext::getCurrent()->getNewId();
277       if (newid > 100000) break; 
278       name.str("");
279       name << "container" << newid;
280       scont = sproc->addContainer(name.str());
281     }
282 }
283
284 void GuiEditor::CreateHPContainer()
285 {
286   DEBTRACE("GuiEditor::CreateHPContainer");
287   SubjectProc *sproc = QtGuiContext::getQtCurrent()->getSubjectProc();
288   YASSERT(sproc);
289   SubjectContainerBase *scont = 0;
290   while (!scont)
291     {
292       std::stringstream name;
293       long newid = GuiContext::getCurrent()->getNewId();
294       if (newid > 100000) break;
295       name.str("");
296       name << "container" << newid;
297       scont = sproc->addHPContainer(name.str());
298     }
299 }
300
301 void GuiEditor::CreateComponentInstance()
302 {
303   DEBTRACE("GuiEditor::CreateComponentInstance");
304   SubjectProc *sproc = QtGuiContext::getQtCurrent()->getSubjectProc();
305   YASSERT(sproc);
306   Subject *sub = QtGuiContext::getQtCurrent()->getSelectedSubject();
307   SubjectComponent *sco = dynamic_cast<SubjectComponent*>(sub);
308   if (!sco)
309     {
310       DEBTRACE("GuiEditor::CreateComponentInstance: " << "selection is not a component");
311       return;
312     }
313   string compoName = sco->getComponent()->getCompoName();
314   string containerName = sco->getComponent()->getContainer()->getName();
315   sproc->addComponent(compoName, containerName);
316 }
317
318
319 SubjectDataPort* GuiEditor::CreateInputPort(SubjectElementaryNode* seNode, 
320                                             std::string name,
321                                             YACS::ENGINE::Catalog *catalog,
322                                             std::string type,
323                                             SubjectDataPort* before)
324 {
325   DEBTRACE("GuiEditor::CreateInputPort");
326   SubjectDataPort *sdp = 0;
327   if (name.empty())
328     {
329       std::stringstream aName;
330       long newid = 0;
331       while (newid < 100000)
332         {
333           newid = GuiContext::getCurrent()->getNewId();
334           aName.str("");
335           aName << "i" << newid;
336           try
337             {
338               seNode->getNode()->getInputPort(aName.str());
339             }
340           catch(Exception& ex)
341             {
342               break;
343             }
344         }
345       sdp = seNode->addInputPort(catalog,type, aName.str());
346     }
347   else
348     sdp = seNode->addInputPort(catalog,type, name);
349   if (!sdp)
350     Message mess;
351   return sdp;
352 }
353
354 SubjectDataPort*  GuiEditor::CreateOutputPort(SubjectElementaryNode* seNode, 
355                                               std::string name,
356                                               YACS::ENGINE::Catalog *catalog,
357                                               std::string type,
358                                               SubjectDataPort* before)
359 {
360   DEBTRACE("GuiEditor::CreateOutputPort");
361   SubjectDataPort *sdp = 0;
362   if (name.empty())
363     {
364       std::stringstream aName;
365       long newid = 0;
366       while (newid < 100000)
367         {
368           newid = GuiContext::getCurrent()->getNewId();
369           aName.str("");
370           aName << "o" << newid;
371           try
372             {
373               seNode->getNode()->getOutputPort(aName.str());
374             }
375           catch(Exception& ex)
376             {
377               break;
378             }
379         }
380       sdp = seNode->addOutputPort(catalog,type, aName.str());
381     }
382   else
383     sdp = seNode->addOutputPort(catalog,type, name);
384   if (!sdp)
385     Message mess;
386   return sdp;
387 }
388
389 /*!
390  * Subject shrink or expand, command from popup menu: needs a valid selection
391  */
392 void GuiEditor::shrinkExpand(Qt::KeyboardModifiers kbModifiers) {
393   DEBTRACE("GuiEditor::shrinkExpand");
394
395   Subject* sub = QtGuiContext::getQtCurrent()->getSelectedSubject();
396   if (!sub) {
397     DEBTRACE("GuiEditor::shrinkExpand : invalid selection!");
398     return;
399   };
400
401   if (! QtGuiContext::getQtCurrent()->_mapOfSceneItem.count(sub)) {
402     DEBTRACE("GuiEditor::shrinkExpand: no scene item corresponding to this subject");
403     return;
404   };
405
406   SceneItem* item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[sub];
407   SceneNodeItem *sni = dynamic_cast<SceneNodeItem*>(item);
408   if (!sni) {
409     DEBTRACE("GuiEditor::shrinkExpand: no scene node item corresponding to this subject");
410     return;
411   };
412
413   ShrinkMode aShrinkMode = CurrentNode;
414   if (kbModifiers == Qt::ControlModifier) {
415     aShrinkMode = ElementaryNodes;
416   } else if (kbModifiers == (Qt::ShiftModifier|Qt::ControlModifier)) {
417     aShrinkMode = ChildrenNodes;
418   }
419
420   sni->reorganizeShrinkExpand(aShrinkMode);
421   sni->showOutScopeLinks();
422   sni->updateLinks();
423 }
424
425 /*!
426  * Subject destruction, command from popup menu: needs a valid selection
427  */
428 void GuiEditor::DeleteSubject()
429 {
430   DEBTRACE("GuiEditor::DeleteSubject");
431   if (!QtGuiContext::getQtCurrent()->isEdition()) return;
432   QModelIndexList selList
433     = QtGuiContext::getQtCurrent()->getSelectionModel()->selectedIndexes();
434   if (selList.isEmpty())
435     return;
436
437   QModelIndex selected = selList.front();
438   if (!selected.isValid())
439     return;
440
441   SchemaItem *selItem = static_cast<SchemaItem*>(selected.internalPointer());
442   if (!selItem) return;
443   Subject *subToRemove = selItem->getSubject();
444   Subject *subParent = subToRemove->getParent();
445   DeleteSubject(subParent, subToRemove);
446 }
447
448 /*!
449  * Subject destruction, command from button in port table view or via selection
450  */
451 void GuiEditor::DeleteSubject(Subject* parent,
452                               Subject* toRemove)
453 {
454   DEBTRACE("GuiEditor::DeleteSubject "<<parent->getName()<<" "<<toRemove->getName());
455   if (!QtGuiContext::getQtCurrent()->isEdition()) return;
456   toRemove->askRegisterUndoDestroy();
457   if(!parent->destroy(toRemove))
458     Message mess;
459   // Empty the clipboard in order to avoid the copy of a destroyed object.
460   QtGuiContext::getQtCurrent()->setSubjectToCopy(NULL);
461 }
462
463 void GuiEditor::CutSubject()
464 {
465   DEBTRACE("GuiEditor::CutSubject");
466   if (!QtGuiContext::getQtCurrent()->isEdition()) return;
467   Subject *sub = QtGuiContext::getQtCurrent()->getSelectedSubject();
468   if (!sub)
469     {
470       Message mess("GuiEditor::Cut : invalid selection!");
471       return;
472     }
473   DEBTRACE(sub->getName());
474   QtGuiContext::getQtCurrent()->setSubjectToCut(sub);
475 }
476
477 void GuiEditor::CopySubject()
478 {
479   DEBTRACE("GuiEditor::CopySubject");
480   if (!QtGuiContext::getQtCurrent()->isEdition()) return;
481   Subject *sub = QtGuiContext::getQtCurrent()->getSelectedSubject();
482   if (!sub)
483     {
484       Message mess("GuiEditor::Copy : invalid selection!");
485       return;
486     }
487   DEBTRACE(sub->getName());
488   QtGuiContext::getQtCurrent()->setSubjectToCopy(sub);
489 }
490
491 void GuiEditor::PasteSubject()
492 {
493   DEBTRACE("GuiEditor::PasteSubject");
494   if (!QtGuiContext::getQtCurrent()->isEdition()) return;
495   Subject *newParent = QtGuiContext::getQtCurrent()->getSelectedSubject();
496   if (!newParent)
497     {
498       Message mess("GuiEditor::Paste : invalid selection!");
499       return;
500     }
501   bool isCut = false;
502   Subject *sub = QtGuiContext::getQtCurrent()->getSubjectToPaste(isCut);
503   if (!sub)
504     {
505       Message mess("Nothing to paste");
506       return;
507     }
508   if (SubjectNode *snode = dynamic_cast<SubjectNode*>(sub))
509     {
510       if (isCut)
511         {
512           DEBTRACE("cut");
513           if (!snode->reparent(newParent))
514             Message mess;
515         }
516       else
517         {
518           DEBTRACE("copy");
519           if (!snode->copy(newParent))
520             Message mess;
521         }
522       return;
523     }
524   Message mess("Paste not possible for this kind of object");
525 }
526
527 void GuiEditor::PutSubjectInBloc()
528 {
529   Subject *sub = QtGuiContext::getQtCurrent()->getSelectedSubject();
530   if (!sub)
531     {
532       Message mess("GuiEditor::PutSubjectInBloc : invalid selection!");
533       return;
534     }
535   if (SubjectNode *snode = dynamic_cast<SubjectNode*>(sub))
536     {
537       //Build the set of children node names
538       Node* node=snode->getNode();
539       ComposedNode* father=node->getFather();
540       std::list<Node*> children = father->edGetDirectDescendants();
541       std::set<std::string> names;
542       for (std::list<Node*>::iterator it = children.begin(); it != children.end(); ++it)
543         names.insert((*it)->getName());
544
545       std::stringstream tryname;
546       long newid=0;
547       while (newid < 100000)
548         {
549           tryname.str("");
550           tryname << "Bloc" << newid;
551           if(names.find(tryname.str()) == names.end())break;
552           newid++;
553         }
554       
555       if (!snode->putInComposedNode(tryname.str(),"Bloc"))
556         Message mess;
557
558       return;
559     }
560   Message mess("Put in Bloc not possible for this kind of object");
561 }
562
563 void GuiEditor::PutGraphInNode(std::string typeNode)
564 {
565   // put graph in Bloc node before
566   std::string blocname = PutGraphInBloc();
567   // put the built bloc into target node type
568   Proc* proc = GuiContext::getCurrent()->getProc();
569   Node* bloc = proc->getChildByShortName(blocname);
570   SubjectNode * sbloc = GuiContext::getCurrent()->_mapOfSubjectNode[bloc];
571   // create a target node
572   SubjectNode * snode = CreateNode(typeNode);
573   // put the built bloc into target node
574   sbloc->putInComposedNode(snode->getName(), typeNode);
575   // select a target node
576   YACS::HMI::SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
577   QtGuiContext::getQtCurrent()->setSelectedSubject(subproc);
578   arrangeNodes(false);
579 }
580
581 std::string GuiEditor::PutGraphInBloc()
582 {
583   Proc* proc = GuiContext::getCurrent()->getProc();
584   std::list<Node *> children = proc->edGetDirectDescendants();
585
586   //get the set of children node names
587   std::set<std::string> names;
588   for (std::list<Node*>::iterator it = children.begin(); it != children.end(); ++it)
589     names.insert((*it)->getName());
590
591   //get the next numbered name
592   std::stringstream tryname;
593   long newid = GuiContext::getCurrent()->getNewId();
594   while (newid < 100000)
595     {
596       tryname.str("");
597       tryname << "Bloc" << newid;
598       if(names.find(tryname.str()) == names.end())break;
599       newid++;
600     }
601   std::string blocname = tryname.str();
602
603   //put one by one the child nodes of Proc node into a new Bloc node
604   std::map< std::string, std::pair<QPointF, QPointF> > aMapOfNodePosition;
605   SceneItem *item = 0;
606   SceneNodeItem *inode = 0;
607   SubjectNode * snode = 0;
608   for (std::list<Node*>::iterator it = children.begin(); it != children.end(); ++it)
609     {
610       snode = GuiContext::getCurrent()->_mapOfSubjectNode[(*it)];
611       snode->saveLinks();
612       item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[snode];
613       YASSERT(item);
614       inode = dynamic_cast<SceneNodeItem*>(item);
615       YASSERT(inode);
616       // save current node position to restore it after reparenting
617       aMapOfNodePosition[snode->getName()] = std::make_pair(inode->pos(), QPointF(inode->getExpandedX(), inode->getExpandedY()));
618       // put in Bloc node
619       snode->putInComposedNode(blocname, "Bloc", false);
620     }
621   for (std::list<Node*>::iterator it = children.begin(); it != children.end(); ++it)
622     {
623       snode = 0;
624       snode = GuiContext::getCurrent()->_mapOfSubjectNode[(*it)];
625       snode->restoreLinks();
626       item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[snode];
627       YASSERT(item);
628       inode = dynamic_cast<SceneNodeItem*>(item);
629       YASSERT(inode);
630       // restore node position
631       inode->setPos(aMapOfNodePosition[snode->getName()].first);
632       // update node position for shrink/expand operation
633       inode->setExpandedPos(aMapOfNodePosition[snode->getName()].second);
634       // notify node about position changing
635       inode->checkGeometryChange();
636     }
637   Node* bloc = proc->getChildByShortName(blocname);
638   SubjectNode* sbloc = GuiContext::getCurrent()->_mapOfSubjectNode[bloc];
639   item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[sbloc];
640   YASSERT(item);
641   // notify bloc about child position changing
642   item->checkGeometryChange();
643   // select a target bloc
644   YACS::HMI::SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
645   QtGuiContext::getQtCurrent()->setSelectedSubject(subproc);
646   return blocname;
647 }
648
649 void GuiEditor::rebuildLinks()
650 {
651 // --- only global link redraw for now...
652   DEBTRACE("GuiEditor::rebuildLinks");
653   YACS::HMI::SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
654   SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[subproc];
655   SceneComposedNodeItem *proc = dynamic_cast<SceneComposedNodeItem*>(item);
656   proc->rebuildLinks();
657 }
658
659 void GuiEditor::arrangeNodes(bool isRecursive)
660 {
661   Subject *sub = QtGuiContext::getQtCurrent()->getSelectedSubject();
662   if (!sub)
663     {
664       DEBTRACE("GuiEditor::arrangeNodes : invalid selection!");
665       return;
666     }
667   DEBTRACE(sub->getName());
668
669   if (! QtGuiContext::getQtCurrent()->_mapOfSceneItem.count(sub))
670     {
671       DEBTRACE("no scene item corresponding to this subject");
672       return;
673     }
674   SceneItem* item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[sub];
675   SceneComposedNodeItem *sci = dynamic_cast<SceneComposedNodeItem*>(item);
676   if (! sci)
677     {
678       DEBTRACE("no scene composed node item corresponding to this subject");
679       return;
680     }
681   sci->arrangeNodes(isRecursive);
682 //   if (Scene::_autoComputeLinks && !QtGuiContext::getQtCurrent()->isLoading())
683 //     {
684 //       YACS::HMI::SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
685 //       SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[subproc];
686 //       SceneComposedNodeItem *proc = dynamic_cast<SceneComposedNodeItem*>(item);
687 //       proc->rebuildLinks();
688 //     }
689 }
690
691 void GuiEditor::arrangeProc()
692 {
693   YACS::HMI::SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
694   SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[subproc];
695   SceneComposedNodeItem *proc = dynamic_cast<SceneComposedNodeItem*>(item);
696   proc->arrangeNodes(true);
697 }
698
699 void GuiEditor::showUndo(QWidget *parent)
700 {
701   FormUndoRedo *undo = new FormUndoRedo(parent);
702   undo->tabWidget->setCurrentWidget(undo->undoTab);
703   undo->exec();
704 }
705
706 void GuiEditor::showRedo(QWidget *parent)
707 {
708   FormUndoRedo *redo = new FormUndoRedo(parent);
709   redo->tabWidget->setCurrentWidget(redo->redoTab);
710   redo->exec();
711 }
712
713 /*! Replace accentuated characters from latin1 to US ascii equivalent without accent.
714 *   I did not found anything to do that in Qt...
715 */
716 QString GuiEditor::asciiFilter(const QString & name)
717 {
718   DEBTRACE(name.toStdString());
719   string aName = name.toLatin1().data();
720   DEBTRACE(aName);
721   for (int i=0; i < aName.size(); i++)
722     {
723       int v = (unsigned char)(aName[i]);
724       DEBTRACE(v << " " << _table[v]);
725       aName[i] = _table[v];
726     }
727   DEBTRACE(aName);
728   return aName.c_str();
729 }