Salome HOME
Update copyright information
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_Service.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SUPERV SUPERVGUI : GUI for Supervisor component
23 //  File   : SUPERVGUI_Service.cxx
24 //  Author : Francis KLOSS
25 //  Module : SUPERV
26 //
27 #include "SUPERVGUI_Service.h"
28 #include "SUPERVGUI_Main.h"
29 #include "SUPERVGUI_Library.h"
30 #include "SUPERVGUI.h"
31
32 #include "CAM_Application.h"
33 #include "SUIT_Desktop.h"
34 #include "SUIT_FileDlg.h"
35 #include "SUIT_Session.h"
36 #include "SUIT_Tools.h"
37
38 #include "SALOME_NamingService.hxx"
39 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
40 #include <qlabel.h>
41 #include <qlayout.h>
42 #include <qhbox.h>
43 #include <qtextstream.h>
44 #include <qregexp.h>
45
46 static const char * ComponentIcon[] = {
47 "20 20 2 1",
48 "       c None",
49 ".      c #000000",
50 "                    ",
51 "                    ",
52 "                    ",
53 " .................. ",
54 " .                . ",
55 " .                . ",
56 " .                . ",
57 " .                . ",
58 " .                . ",
59 " .                . ",
60 " .                . ",
61 " .                . ",
62 " .................. ",
63 "    .     .     .   ",
64 "    .     .     .   ",
65 "   ...   ...   ...  ",
66 "  .. .. .. .. .. .. ",
67 "  .   . .   . .   . ",
68 "  .. .. .. .. .. .. ",
69 "   ...   ...   ...  "};
70
71
72 static const char * InterfaceIcon[] = {
73 "20 20 2 1",
74 "       c None",
75 ".      c #000000",
76 "                    ",
77 "                    ",
78 "                    ",
79 "                    ",
80 "                    ",
81 "            ..      ",
82 "          ......    ",
83 "         ..    ..   ",
84 "         .      .   ",
85 "..........      ..  ",
86 "         .      .   ",
87 "         ..    ..   ",
88 "          ......    ",
89 "            ..      ",
90 "                    ",
91 "                    ",
92 "                    ",
93 "                    ",
94 "                    ",
95 "                    "};
96
97
98
99
100 SUPERVGUI_Service::SUPERVGUI_Service(SALOME_NamingService* ns):
101     QDialog(SUIT_Session::session()->activeApplication()->desktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
102     naming(ns), myMFile(0)
103 {
104   setSizeGripEnabled( true );
105   setCaption(tr("TIT_SERVICES"));
106
107   QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 4);
108
109   myTabPane = new QTabWidget(this);
110   connect(myTabPane, SIGNAL(currentChanged(QWidget *)), this, SLOT(tabChanged(QWidget *)));
111
112   // Create Tab for Corba services
113   QWidget* aCorbaPane = new QWidget(myTabPane);
114   QVBoxLayout* aBaseLayoutV= new QVBoxLayout(aCorbaPane, 0, 4);
115   aBaseLayoutV->setMargin(5);
116   aBaseLayoutV->setSpacing(10);
117
118   QHBoxLayout* aBaseLayout = new QHBoxLayout(aCorbaPane); //!!
119   aBaseLayout->setMargin(5);
120   aBaseLayout->setSpacing(10);
121  
122   components = new QListView(aCorbaPane);
123   components->addColumn(tr("COL_COMPONENTS"));
124   components->addColumn(tr("COL_PORTTYPE"));
125   components->addColumn(tr("COL_PORTWAY"));
126   components->setColumnAlignment(1, AlignLeft);
127   components->setColumnAlignment(2, AlignLeft);
128   components->setColumnAlignment(3, AlignLeft);
129   components->setSelectionMode(QListView::Extended);
130   components->setRootIsDecorated(true);
131
132 //  aBaseLayout->addWidget(components);
133   aBaseLayoutV->addWidget(components); //!!
134
135   //QHGroupBox* aAddBox = new QHGroupBox(tr("TIT_ADDNODE"), aCorbaPane); //!!
136   //aAddBox->setInsideSpacing(20); //!!
137
138 //NRI   QPushButton* aComputeCBtn = new QPushButton(tr("TIT_ADDCNODE"), aCorbaPane); //!!
139 //NRI   connect(aComputeCBtn, SIGNAL(clicked()), this, SLOT(addComputeNode())); //!!
140 //NRI   aComputeCBtn->setDefault(false); 
141
142   QPushButton* aComputeBtnDef = new QPushButton(tr("TIT_ADDFNODE"), aCorbaPane);
143   connect(aComputeBtnDef, SIGNAL(clicked()), this, SLOT(addFactoryNodeDef()));
144   aComputeBtnDef->setDefault(true); 
145
146   QPushButton* aComputeBtnCust = new QPushButton(tr("TIT_ADDFNODE_CUST"), aCorbaPane);
147   connect(aComputeBtnCust, SIGNAL(clicked()), this, SLOT(addFactoryNodeCust()));
148   aComputeBtnCust->setDefault(true); 
149
150   aBaseLayout->addWidget(aComputeBtnDef);
151   aBaseLayout->addWidget(aComputeBtnCust);
152   //NRI  aBaseLayout->addWidget(aComputeCBtn); //!!
153
154   aBaseLayoutV->insertLayout(-1, aBaseLayout);
155   myTabPane->addTab(aCorbaPane, tr("MODULES_PANE"));
156
157
158   // Create Tab for Python services
159   QWidget* aPythonPane = new QWidget(myTabPane);
160   QVBoxLayout* aPythonLayout = new QVBoxLayout(aPythonPane, 0, 4);
161   aPythonLayout->setMargin(5);
162   aPythonLayout->setSpacing(10);
163
164   // Type pane
165   QHGroupBox* aAddBox2 = new QHGroupBox(tr("TIT_ADDNODE"), aPythonPane);
166   aAddBox2->setInsideSpacing(20);
167
168   /*QLabel* aTypeLbl = */new QLabel(tr("LBL_NODETYPE"), aAddBox2);
169
170   myTypeCombo = new QComboBox(aAddBox2);
171   myTypeCombo->insertItem( tr( "INLINE_COMP" ) );
172   myTypeCombo->insertItem( tr( "INLINE_SWTC" ) );
173   myTypeCombo->insertItem( tr( "INLINE_LOOP" ) );
174   myTypeCombo->insertItem( tr( "INLINE_GOTO") );
175   connect(myTypeCombo, SIGNAL(activated(int)), this, SLOT(typeNodeSelected(int)));
176
177   aPythonLayout->addWidget(aAddBox2);
178
179   // Edit pane
180   myStackWidget = new QWidgetStack(aPythonPane);
181
182   // other pane
183   myScriptPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
184   myOtherId = myStackWidget->addWidget(myScriptPane);
185
186   // loop pane
187   QTabWidget* aLoopTabPane = new QTabWidget(myStackWidget);
188   myInitPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY ); 
189   aLoopTabPane->addTab(myInitPane, "Init");
190
191   myMorePane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
192   aLoopTabPane->addTab(myMorePane, "More");
193
194   myNextPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
195   aLoopTabPane->addTab(myNextPane, "Next");
196   myLoopId = myStackWidget->addWidget(aLoopTabPane);
197
198   myStackWidget->raiseWidget(myOtherId);
199
200   aPythonLayout->addWidget(myStackWidget, 1);
201
202   // Create button
203   QPushButton* aCreateBtn = new QPushButton(tr("TIT_ADDNODE"), aPythonPane);
204   connect(aCreateBtn, SIGNAL(clicked()), this, SLOT(addInlineNode()));
205   aPythonLayout->addWidget(aCreateBtn);
206
207   myTabPane->addTab(aPythonPane, tr("INLINE_PANE"));
208
209   // Create Tab for Macro node only if environmental variable ENABLE_MACRO_NODE is set
210   if ( getenv( "ENABLE_MACRO_NODE" ) != NULL ) {
211     QWidget* aMacroPane = new QWidget(myTabPane);
212     QVBoxLayout* aMacroLayout = new QVBoxLayout(aMacroPane, 0, 4);
213     aMacroLayout->setMargin(5);
214     aMacroLayout->setSpacing(10);
215     
216     QHBoxLayout* aLoadLayout = new QHBoxLayout(aMacroPane); //!!
217     aLoadLayout->addStretch();
218     
219     QPushButton* aLoadBtn = new QPushButton(tr("BUT_LOAD"), aMacroPane);
220     connect(aLoadBtn, SIGNAL(clicked()), this, SLOT(loadGraph()));
221
222     aLoadLayout->addWidget(aLoadBtn);
223
224     aMacroLayout->addLayout(aLoadLayout);
225  
226     myMacroPane = new QListView(aMacroPane);
227     myMacroPane->addColumn(tr("COL_COMPONENTS"));
228     myMacroPane->addColumn(tr("COL_PORTTYPE"));
229     myMacroPane->addColumn(tr("COL_PORTWAY"));
230     myMacroPane->setColumnAlignment(1, AlignLeft);
231     myMacroPane->setColumnAlignment(2, AlignLeft);
232     myMacroPane->setColumnAlignment(3, AlignLeft);
233     myMacroPane->setSelectionMode(QListView::Extended);
234     myMacroPane->setRootIsDecorated(true);
235     aMacroLayout->addWidget(myMacroPane); //!!
236     
237     QPushButton* aAddBtn = new QPushButton(tr("TIT_ADDFNODE"), aMacroPane);
238     connect(aAddBtn, SIGNAL(clicked()), this, SLOT(addMacroNode()));
239     aAddBtn->setDefault(true); 
240     
241     aMacroLayout->addWidget(aAddBtn);
242
243     myTabPane->addTab(aMacroPane, tr("MACRO_PANE"));
244   }
245   
246   aMainLayout->addWidget(myTabPane);
247
248   // Close button
249   QHBox* aBtnBox = new QHBox(this);
250   QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnBox->layout()); 
251   aBtnLayout->addStretch();
252
253   QPushButton* aCloseBtn = new QPushButton(tr("BUT_CLOSE"), aBtnBox);
254   connect(aCloseBtn, SIGNAL(clicked()), this, SLOT(reject()));
255   
256   aMainLayout->addWidget(aBtnBox);
257
258   initialise();
259   myX = 0;
260   myY = 0;
261   myIsInline = false;
262 }
263
264
265 char* getDataStreamParameterName(const char * aType)
266 {
267   QString type (aType);
268
269   if (aType == "int") // 1
270     return "integer";
271   if (aType == "float") // 2
272     return "float";
273   if (aType == "double") // 3
274     return "double";
275   if (aType == "string") // 4
276     return "string";
277   if (aType == "bool") // 6 ??
278     return "boolean";
279
280   return "unknown";
281 }
282
283 void SUPERVGUI_Service::initialise() {
284   CORBA::Object_ptr obj  = naming->Resolve("/Kernel/ModulCatalog");
285   SALOME_ModuleCatalog::ModuleCatalog_var *aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
286   *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
287   if (CORBA::is_nil(*aModuleCatalog)) {
288     setCaption("Error in Connexion to omniNames with '/Kernel/ModulCatalog'");
289     return;
290   }
291   
292   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
293
294   SALOME_ModuleCatalog::ListOfComponents_var lComponents = (*aModuleCatalog)->GetComponentList();
295   long nbComp = lComponents->length();
296   for (int i=0; i<nbComp; i++) {
297     SALOME_ModuleCatalog::Acomponent_ptr C = (*aModuleCatalog)->GetComponent((char *)lComponents[i]);
298     QListViewItem* myComponentItem = new QListViewItem(components, (char*)C->componentusername());
299     myComponentItem->setSelectable(false);
300     QString aIconName = C->component_icone();
301     if (!aIconName.isEmpty()) {
302       QString resFilePath = aResMgr->path(aResMgr->resSection(), C->componentname(), aIconName) ;
303       if ( resFilePath ) {
304         QPixmap aIcone(resFilePath);
305         QIconSet aIconSet(aIcone);
306         myComponentItem->setPixmap(0, aIconSet.pixmap(QIconSet::Small, QIconSet::Normal));
307       } else {
308         myComponentItem->setPixmap(0, ComponentIcon);
309       }
310     } else {
311       myComponentItem->setPixmap(0, ComponentIcon);
312     }
313     SALOME_ModuleCatalog::ListOfInterfaces* lInterfaces = C->GetInterfaceList();
314     long nbInterf = lInterfaces->length();
315     for (int j=0; j<nbInterf; j++) {
316       SALOME_ModuleCatalog::DefinitionInterface* Interface = C->GetInterface((char*)(*lInterfaces)[j]);
317       QListViewItem* myInterfaceItem = new QListViewItem(myComponentItem, (char*)Interface->interfacename);
318       myInterfaceItem->setSelectable(false);
319       myInterfaceItem->setPixmap(0, InterfaceIcon);
320       
321       long nbServices = Interface->interfaceservicelist.length();
322       for (int k=0; k<nbServices; k++) {
323         SALOME_ModuleCatalog::Service* Service = &(Interface->interfaceservicelist[k]);
324         QListViewItem* myServiceItem = new QListViewItem(myInterfaceItem, (char*)Service->ServiceName);
325         myServiceItem->setSelectable(true);
326         //components->ensureItemVisible(myServiceItem);
327         
328         long nbPortsOut = Service->ServiceoutParameter.length();
329         for (int m=0; m<nbPortsOut; m++) {
330           SALOME_ModuleCatalog::ServicesParameter* PortOut = &(Service->ServiceoutParameter[m]);
331           QListViewItem* myPortOutItem = 
332             new QListViewItem(myServiceItem, (char*)PortOut->Parametername, (char*)PortOut->Parametertype, "Out");
333           myPortOutItem->setSelectable(false);
334         }
335
336         long nbStreamPortsOut = Service->ServiceoutDataStreamParameter.length();
337         for (int m=0; m<nbStreamPortsOut; m++) {
338           SALOME_ModuleCatalog::ServicesDataStreamParameter* PortOut =
339             &(Service->ServiceoutDataStreamParameter[m]);
340           QListViewItem* myPortOutItem = 
341             new QListViewItem(myServiceItem, (char*)PortOut->Parametername, 
342                               getDataStreamParameterName(PortOut->Parametertype), "DataStream Out");
343           myPortOutItem->setSelectable(false);
344         }
345         
346         long nbPortsIn = Service->ServiceinParameter.length();
347         for (int l=0; l<nbPortsIn; l++) {
348           SALOME_ModuleCatalog::ServicesParameter* PortIn = &(Service->ServiceinParameter[l]);
349           QListViewItem* myPortInItem = 
350             new QListViewItem(myServiceItem, (char*)PortIn->Parametername, (char*)PortIn->Parametertype, "In");
351           myPortInItem->setSelectable(false);
352         }
353
354         long nbStreamPortsIn = Service->ServiceinDataStreamParameter.length();
355         for (int l=0; l<nbStreamPortsIn; l++) {
356           SALOME_ModuleCatalog::ServicesDataStreamParameter* PortIn = &(Service->ServiceinDataStreamParameter[l]);
357           QListViewItem* myPortInItem = 
358             new QListViewItem(myServiceItem, (char*)PortIn->Parametername, 
359                               getDataStreamParameterName(PortIn->Parametertype), "DataStream In");
360           myPortInItem->setSelectable(false);
361         }
362       }
363     }
364   }
365 }
366
367
368
369 SUPERVGUI_Service::~SUPERVGUI_Service() {
370     Trace("SUPERVGUI_Service::~SUPERVGUI_Service")
371       if (myMFile) delete myMFile;
372 }
373
374 void SUPERVGUI_Service::addComputeNode() {
375   SUIT_Desktop* aDesktop = SUIT_Session::session()->activeApplication()->desktop();
376   CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication());
377   if ( !anApp ) return;
378   
379   SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
380   if ( !aSupMod ) {
381     MESSAGE("NULL Supervision module!");
382     return;
383   }
384
385   SUPERVGUI_Main* aMain = aSupMod->getMain();
386   if (aMain==0) {
387     QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
388   } else if (!aMain->isEditable()) {
389     QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));      
390   } else {
391     CORBA::Object_ptr obj  = naming->Resolve("/Kernel/ModulCatalog");
392     SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
393     *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
394     if (CORBA::is_nil(*aModuleCatalog)) {
395       QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
396     } else {
397       QListViewItem*        item;
398       bool                  b = false;
399       QListViewItemIterator i(components);
400       for (; i.current(); ++i) {
401         item = i.current();
402         if (item->isSelected()) {
403           const char* service   = item->text(0).latin1();
404           const char* interface = item->parent()->text(0).latin1();
405           const char* component = item->parent()->parent()->text(0).latin1();
406           SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(anApp->moduleName(component));
407           if ( myComponent == NULL ) {
408             QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
409           } 
410           else {
411             const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
412             SUPERV_CNode aNode = aMain->getDataflow()->CNode(*myService);
413             if ( CORBA::is_nil( aNode ) ) {
414               QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));    
415               return;
416             }
417
418             SUPERV::INode_var aDummyEndNode;
419             addNode( aNode, aDummyEndNode, myX, myY );
420             b = true; // at least one node was added
421           }
422         }
423       }
424       if ( !b ) {
425         QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
426       }
427     }
428   }
429 }
430
431 void SUPERVGUI_Service::addFactoryNodeDef() {
432   SUIT_Desktop* aDesktop = SUIT_Session::session()->activeApplication()->desktop();
433   CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication());
434   if ( !anApp ) return;
435
436   SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
437   if ( !aSupMod ) {
438     MESSAGE("NULL Supervision module!");
439     return;
440   }
441
442   SUPERVGUI_Main* aMain = aSupMod->getMain();
443   if (aMain==0) {
444     QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
445   } else if (!aMain->isEditable()) {
446     QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));      
447   } else {
448     CORBA::Object_ptr obj  = naming->Resolve("/Kernel/ModulCatalog");
449     SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
450     *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
451     if (CORBA::is_nil(*aModuleCatalog)) {
452       QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
453     } else {
454       QListViewItem*        item;
455       bool                  b = false;
456       QListViewItemIterator i(components);
457       for (; i.current(); ++i) {
458         item = i.current();
459         if (item->isSelected()) {
460           const char* service   = item->text(0).latin1();
461           const char* interface = item->parent()->text(0).latin1();
462           //const char* component = anApp->moduleName(item->parent()->parent()->text(0).latin1());
463           // mkr : PAL13135 -->
464           if ( aSupMod->getInterfaceNameMap().contains(item->parent()->parent()->text(0)) ) {
465             const char* component = aSupMod->getInterfaceNameMap().find(item->parent()->parent()->text(0)).data();
466             // mkr : PAL13135 <--
467
468             SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(component);
469             if (myComponent==NULL) {
470               QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
471             } 
472             else {
473               const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
474               SUPERV_CNode aNode;
475               if ( myService->TypeOfNode == 0 ) { // ComputeNode
476                 aNode = aMain->getDataflow()->CNode(*myService);
477                 if (CORBA::is_nil( aNode ) ) {
478                   QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));        
479                   return;
480                 }
481               } 
482               else { // Factory Node
483                 aNode = aMain->getDataflow()->FNode(component, interface, *myService, myComponent->implementation_type()); // mkr : PAL11273
484                 if ( CORBA::is_nil( aNode ) ) {
485                   QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));        
486                   return;
487                 }
488               }
489               SUPERV::INode_var aDummyEndNode;
490               addNode( aNode, aDummyEndNode, myX, myY );
491               b = true;
492             }
493           }
494         }
495       }
496       if ( !b ) {
497         QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
498       }
499     }
500   }
501 }
502
503 void SUPERVGUI_Service::addFactoryNodeCust() {
504   SUIT_Desktop* aDesktop = SUIT_Session::session()->activeApplication()->desktop();
505   CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication());
506   if ( !anApp ) return;
507
508   SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
509   if ( !aSupMod ) {
510     MESSAGE("NULL Supervision module!");
511     return;
512   }
513
514   SUPERVGUI_Main* aMain = aSupMod->getMain();
515   if (aMain==0) {
516     QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
517   } else if (!aMain->isEditable()) {
518     QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));      
519   } else {
520     CORBA::Object_ptr obj  = naming->Resolve("/Kernel/ModulCatalog");
521     SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
522     *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
523     if (CORBA::is_nil(*aModuleCatalog)) {
524       QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
525     } else {
526       QListViewItem*        item;
527       bool                  b = false;
528       
529       QListViewItemIterator iSel(components);
530       int count = 0;
531       for (; iSel.current(); ++iSel) { // check : how many objects are selected (single or multi)
532         item = iSel.current();
533         if (item->isSelected()) count++;
534         if ( count > 1) break;
535       }
536            
537       QListViewItemIterator i(components);
538       QString anAuthor, aContainer, aComment;
539       bool DoneSetting = false;
540       int aRes = 0;
541       for (; i.current(); ++i) {
542         item = i.current();
543         if (item->isSelected()) {
544           const char* service   = item->text(0).latin1();
545           const char* interface = item->parent()->text(0).latin1();
546           //const char* component = anApp->moduleName(item->parent()->parent()->text(0).latin1());
547           // mkr : PAL13135 -->
548           if ( aSupMod->getInterfaceNameMap().contains(item->parent()->parent()->text(0)) ) {
549             const char* component = aSupMod->getInterfaceNameMap().find(item->parent()->parent()->text(0)).data();
550             // mkr : PAL13135 <--
551
552             SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(component);
553             if (myComponent==NULL) {
554               QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
555             } 
556             else {
557               const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
558               SUPERV_CNode aNode;
559               if ( myService->TypeOfNode == 0 ) { // ComputeNode
560                 aNode = aMain->getDataflow()->CNode(*myService);
561                 if (CORBA::is_nil( aNode ) ) {
562                   QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));        
563                   return;
564                 }
565               } 
566               else { // Factory Node
567
568                 SUPERVGUI_CustomSettings* aCSDialog = 0;
569                 if ( count > 1 && !DoneSetting) { // multi selection
570                   DoneSetting = true;
571                   aCSDialog = new SUPERVGUI_CustomSettings(item, true, myComponent->implementation_type());
572                 }
573                 else if ( count == 1 ) // single selection
574                   aCSDialog = new SUPERVGUI_CustomSettings(item, false, myComponent->implementation_type());
575                 
576                 if ( aCSDialog ) {
577                   aRes = aCSDialog->exec();
578                   if (aRes) {
579                     anAuthor = aCSDialog->Author();
580                     aContainer = aCSDialog->Container();
581                     aComment = aCSDialog->Comment();
582                   }
583                   delete aCSDialog;
584                 }
585                 
586                 aNode = aMain->getDataflow()->FNode(component, interface, *myService, myComponent->implementation_type()); // mkr : PAL11273
587                 if ( CORBA::is_nil( aNode ) ) {
588                   QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));        
589                   return;
590                 }
591
592                 if (aRes) {
593                   aNode->SetAuthor(anAuthor.latin1());
594                   SUPERV::FNode::_narrow(aNode)->SetContainer(aContainer.latin1());
595                   aNode->SetComment(aComment.latin1());
596                 }
597                 
598               }
599               SUPERV::INode_var aDummyEndNode;
600               addNode( aNode, aDummyEndNode, myX, myY );
601               b = true;
602             }
603           }
604         }
605       }
606       if ( !b ) {
607         QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
608       }
609     }
610   }
611 }
612
613 void SUPERVGUI_Service::addInlineNode() {
614   SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
615   if ( !aSupMod ) {
616     MESSAGE("NULL Supervision module!");
617     return;
618   }
619
620   SUPERVGUI_Main* aMain = aSupMod->getMain();
621   if (aMain==0) {
622     QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
623   } 
624   else if (!aMain->isEditable()) {
625     QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
626   } 
627   else {
628     int aSel = myTypeCombo->currentItem();
629     switch (aSel) {
630     case 0: // Computation
631       { 
632         SUPERV_CNode aNode = 
633           aMain->getDataflow()->INode(myScriptPane->getFuncName().isEmpty() ? "" : myScriptPane->getFuncName().latin1(), 
634                                       (myScriptPane->getFunction()).in());
635         if (CORBA::is_nil(aNode)) {
636           QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
637           return;
638         }
639         SUPERV::INode_var aDummyEndNode;
640         // here we have to 
641         // 1) parse nodes' python function to find ports names
642         // 2) create ports for engine node with found names and "undefined" types
643         //    ( aNode->InPort(name,type), aNode->OutPort(name,type) )
644         // P.S. CanvasNode->createPort(...) for create presentation of port
645         //      will be called from addNode(...) (inside CanvasNode constructor)
646         addNode( aNode, aDummyEndNode, myX, myY );
647       }
648       break;
649       
650     case 1: // Switch
651       {
652         SUPERV_INode aEndNode;
653         SUPERV_CNode aStartNode = 
654           aMain->getDataflow()->SNode(myScriptPane->getFuncName().isEmpty() ? "" : myScriptPane->getFuncName().latin1(),
655                                       (myScriptPane->getFunction()).in(),
656                                       aEndNode);
657         if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
658           QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
659           return;
660         }
661         addNode( aStartNode, aEndNode, myX, myY );
662       }
663       break;
664       
665     case 2: // Loop
666       {
667         SUPERV_INode aEndNode;
668         SUPERV_CNode aStartNode = 
669           aMain->getDataflow()->LNode(myInitPane->getFuncName().isEmpty() ? "" : myInitPane->getFuncName().latin1(), 
670                                       (myInitPane->getFunction()).in(),
671                                       myMorePane->getFuncName().isEmpty() ? "" : myMorePane->getFuncName().latin1(), 
672                                       (myMorePane->getFunction()).in(),
673                                       myNextPane->getFuncName().isEmpty() ? "" : myNextPane->getFuncName().latin1(), 
674                                       (myNextPane->getFunction()).in(),
675                                       aEndNode);
676         if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
677           QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
678           return;
679         }
680         addNode( aStartNode, aEndNode, myX, myY );
681       }
682       break;
683       
684     case 3: // GoTo
685       {
686         SUPERV_CNode aGotoNode;
687         if (myScriptPane->isDefined()) 
688           aGotoNode = aMain->getDataflow()->GNode(myScriptPane->getFuncName().latin1(), 
689                                                   (myScriptPane->getFunction()).in(), "");
690         else
691           aGotoNode = aMain->getDataflow()->GNode("GoTo", (myScriptPane->getFunction()).in(), "");
692         if (CORBA::is_nil(aGotoNode)) {
693           QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
694           return;
695         }
696         SUPERV::INode_var aDummyEndNode;
697         addNode( aGotoNode, aDummyEndNode, myX, myY );
698       }
699       break;
700     }
701   }
702 }
703
704 void SUPERVGUI_Service::addMacroNode() {
705   SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
706   if ( !aSupMod ) {
707     MESSAGE("NULL Supervision module!");
708     return;
709   }
710
711   SUPERVGUI_Main* aMain = aSupMod->getMain();
712   if (aMain==0) {
713     QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
714   } 
715   else if (!aMain->isEditable()) {
716     QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
717   } 
718   else {
719     if ( myMFile ) {
720       SUPERV_CNode aNode;
721       if (aMain->getDataflow()->IsStreamGraph()) {
722         SUPERV_StreamGraph aSGraph = aMain->getDataflow()->ToStreamGraph();
723         if (!SUPERV_isNull(aSGraph)) 
724           aNode = aSGraph->StreamMNode(myMFile->name().latin1());
725         // TMP: while stream macro nodes doesn't impemented 
726         if (CORBA::is_nil(aNode)) {
727           aNode = aSGraph->MNode(myMFile->name().latin1());
728         }
729       }
730       else 
731         aNode = aMain->getDataflow()->MNode(myMFile->name().latin1());
732       if (CORBA::is_nil(aNode)) {
733         QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));         
734         return;
735       }
736
737       SUPERV::INode_var aDummyEndNode;
738       addNode( aNode, aDummyEndNode, myX, myY );
739     }
740     else {
741       QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("WARNING"), tr("MSG_NONODE_TOADD"));
742     }
743   }
744 }
745
746 void SUPERVGUI_Service::loadGraph() {
747         if ( getenv( "ENABLE_MACRO_NODE" ) == NULL )
748         // error! if ENABLE_MACRO_NODE is set - we should NOT get here by any means..
749         {
750                 //MESSAGE("Error: ENABLE_MACRO_NODE is not set, but loadGraph() was called!");
751                 return;
752         }
753
754   QString aFileName = SUIT_FileDlg::getFileName(SUIT_Session::session()->activeApplication()->desktop(),
755                                                 "",
756                                                 "*.xml",
757                                                 tr("MSG_GRAPH_INSERT"),
758                                                 true);
759   if (aFileName.isEmpty()) return;
760
761   myMacroPane->clear();
762
763   myMFile = new QFile(aFileName);
764   if (!myMFile->open(IO_ReadOnly)) {
765     QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), 
766                          tr("MSG_CANT_LOADSCRIPT"));
767     delete myMFile; myMFile = 0;
768     return;
769   }
770
771   QTextStream* aStream = new QTextStream(myMFile);
772   if (aStream->atEnd()) {
773     QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), 
774                          tr("MSG_EMTY_FILE"));
775     delete aStream;
776     myMFile->close();
777     delete myMFile; myMFile = 0;
778     return;
779   }
780
781   // read graph info
782   // temporary display only file name
783   QFileInfo anInfo(*myMFile);
784   QListViewItem* anItem = new QListViewItem(myMacroPane, anInfo.baseName());
785   anItem->setSelectable(true);
786 }
787
788 void SUPERVGUI_Service::typeNodeSelected(int theRow) {
789   if (theRow == 2)
790     myStackWidget->raiseWidget(myLoopId);
791   else
792     myStackWidget->raiseWidget(myOtherId);
793 }
794
795
796
797 void SUPERVGUI_Service::choose() {
798     Trace("SUPERVGUI_Service::choose")
799     show();
800     raise();
801 }
802     
803
804 void SUPERVGUI_Service::showEvent(QShowEvent* theEvent) {
805   SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
806   if ( !aSupMod ) {
807     MESSAGE("NULL Supervision module!");
808     return;
809   }
810
811   SUPERVGUI_Main* aMain = aSupMod->getMain();
812   if (aMain && (!aMain->isArrayShown())) {
813     aMain->getArrayView()->viewportToContents(0, 0, myX, myY);
814     //aMain->getGraph()->viewportToContents(0, 0, myX, myY);
815   }
816   QDialog::showEvent(theEvent);
817 }
818
819
820 void SUPERVGUI_Service::tabChanged(QWidget* theWidget) {
821   myIsInline = (myTabPane->currentPageIndex() == 1);
822 }
823
824
825
826 //*****************************************************/
827 //  Pane for Python script editing
828 //*****************************************************/
829 SUPERVGUI_PythonEditPane::SUPERVGUI_PythonEditPane( QWidget* theParent, const bool isNodeCreation, int& theX, int& theY ) 
830   : myIsWithLibrary( isNodeCreation ), 
831     QFrame( theParent ),
832     myX( theX ), myY( theY )
833 {
834   QGridLayout* aEditLayout = new QGridLayout( this, 2, 8, 0, 6 );
835
836   // First row
837   if ( myIsWithLibrary ) {
838     QPushButton* aLibBtn = new QPushButton(tr("BUT_LIBRARY"), this);
839     connect(aLibBtn, SIGNAL(clicked()), this, SLOT(library()));
840     aEditLayout->addMultiCellWidget( aLibBtn, 0, 0, 1, 2 );
841   }
842
843   QPushButton* aLoadBtn = new QPushButton(tr("BUT_LOAD"), this);
844   connect(aLoadBtn, SIGNAL(clicked()), this, SLOT(loadFile()));
845   
846   aEditLayout->addMultiCellWidget( aLoadBtn, 0, 0, 3, 4 );
847
848   myFunctionsCombo = new QComboBox( this );
849   connect( myFunctionsCombo, SIGNAL( activated( int ) ), this, SLOT( readFunction( int ) ) );
850   
851   aEditLayout->addMultiCellWidget( myFunctionsCombo, 0, 0, 5, 7 );
852   
853   //Second row
854   myText = new QTextEdit(this);
855   myText->setTextFormat( Qt::PlainText ); // NOT rich text, so text() returns plain text
856   myText->setWordWrap( QTextEdit::FixedColumnWidth );
857   myText->setWrapColumnOrWidth( 80 );
858   connect( myText, SIGNAL( returnPressed() ), this, SLOT( autoIndentLine() ) );
859
860   aEditLayout->addMultiCellWidget( myText, 1, 1, 0, 7 );
861   //aEditLayout->setColStretch( 3, 1 ); // to allow myFunctionsCombo be larger when needed
862 }
863
864 /**
865  * Return a text between "def" and "("
866  * "def" must begin with position 0, which means that only global function definitions are possible
867  */ 
868 QString getFunctionName( const QString& aLine ) {
869   int aDefPos = aLine.find("def");
870   if ( aDefPos == 0 ) { // only global function definitions!
871     int aStart = aLine.find(" ", aDefPos);
872     int aEnd = aLine.find("(", aStart);
873     QString aName = aLine.mid(aStart, (aEnd-aStart));
874     return aName.stripWhiteSpace();
875   }
876   return QString();
877 }
878    
879 /**
880  * Searches for text beginning with "def" and ending with any meanful character at 
881  * beginning of line.  Starts searching with current position of given stream.
882  * Fills the myPyFunctions with strings corresponding to found fucntions.
883  */
884 void SUPERVGUI_PythonEditPane::initPyFunctions( QTextStream& theStream ) {
885
886   if ( theStream.atEnd() )
887     return;
888
889   QString aPyFunction;
890   QString aLine = theStream.readLine(); 
891
892   while ( !theStream.atEnd() ) { // not EOF
893
894     // asv : 23.11.04 : fix for PAL6870 : skip empty lines in the beginning or  between functions
895     //       find("def)==0 -> analizing only global function definitions which start with 0 indentation
896     while ( !aLine.isNull() && aLine.find( "def" ) != 0 ) 
897       aLine = theStream.readLine();
898     
899     if ( !aLine.isNull() && aLine.find("def") == 0 ) { 
900       myFunctionsCombo->insertItem( getFunctionName( aLine ) ); // aLine now == function name 
901
902       aPyFunction += aLine;
903       aPyFunction += '\n'; 
904
905       // read function body
906       aLine = theStream.readLine();
907       // asv : 23.11.04 : added "|| aLine.isEmpty()" - fix for PAL6870. readLine() returns an empty
908       //       string for "\n" string, it trails \n caracter.  but we accept such lines..
909       // asv : 22.12.04 : aLine[0].isSpace() || aLine[0]=='#' -> line must begin with space or tab
910       //       (a normal code with indentation) or comment sign.
911       while ( !aLine.isNull() && ( aLine.isEmpty() || aLine[0].isSpace() || aLine[0] == '#' ) ) {
912         aPyFunction += aLine;
913         aPyFunction += '\n'; 
914         aLine = theStream.readLine();
915       }
916
917       myPyFunctions << aPyFunction;
918       aPyFunction.setLength( 0 );
919     }
920   }
921 }
922
923 /**
924  * Load existing Python script
925  */
926 void SUPERVGUI_PythonEditPane::loadFile() {
927   QString aFileName = SUIT_FileDlg::getFileName(SUIT_Session::session()->activeApplication()->desktop(),
928                                                 "",
929                                                 "*.py",
930                                                 tr("TIT_LOADSCRIPT"),
931                                                 true);
932   if (aFileName.isEmpty()) return;
933
934   QFile aFile( aFileName );
935   if (!aFile.open(IO_ReadOnly)) {
936     QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), 
937                          tr("MSG_CANT_LOADSCRIPT"));
938     return;
939   }
940
941   myPyFunctions.clear();
942   myFunctionsCombo->clear();
943   myText->clear();
944
945   QTextStream aFileReader(&aFile);
946   if ( aFileReader.atEnd() ) {
947     QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), tr("MSG_EMTY_FILE"));
948     aFile.close();
949     return;
950   }
951
952   initPyFunctions( aFileReader );
953
954   if ( myPyFunctions.size() )
955     readFunction( 0 );
956 }
957   
958 /**
959  * Finds and Reads a function from current position in the opened file
960  * asv : Comment above is old! Present model: just take an already read string = PyFunction
961  * from the list which is filled in loadFile().
962  */
963 void SUPERVGUI_PythonEditPane::readFunction( int i ) {
964   myText->clear();
965   if ( i != -1 && myPyFunctions.size() && myPyFunctions.size() > i )
966     myText->append( myPyFunctions[ i ] );
967
968   // asv : 30.11.04 : 2.7 - Inline node function editor improvement
969   // 2.7.1 - set focus to editor widget on editor window opening
970   // 2.7.2 - scroll to the beginning of function on editor window opening
971   myText->setFocus();
972   myText->ensureVisible( 0,0 );
973 }
974
975 /**
976  * Returns the text after "def" and before "(" -- first defined function name
977  */
978 QString SUPERVGUI_PythonEditPane::getFuncName() {
979   for (int i=0; i < myText->paragraphs(); i++) {
980     QString aName = getFunctionName( myText->text(i) );
981     if ( !aName.isEmpty() )
982       return aName;
983   }
984   return QString();
985 }
986
987 /**
988  * Returns the contents of the myText widget without trailing spacing 
989  */
990 SUPERV_Strings SUPERVGUI_PythonEditPane::getFunction() {
991   SUPERV_Strings aStrings = new SUPERV::ListOfStrings();
992   aStrings->length(myText->paragraphs());
993   for (int i=0; i < myText->paragraphs(); i++) {
994     QString aLine = myText->text(i);
995     // asv : 30.11.04 - why do we have to remove trailing spaces??  
996     // it's user's responsibility to enter correct Python code, we don't do anything with it.
997     // if (..) -- initial, while(..) -- my improvement, but also commented out -- needless.
998     //if (!aLine.right(1).compare(" ")) // replaced with the line below -- loop
999     // uncommented by mkr to fix bugs IPAL12363, IPAL12885 -->
1000     while (aLine.at(aLine.length()-1).isSpace()) // remove trailing spaces
1001       aLine = aLine.remove(aLine.length()-1,1);
1002     // <--
1003     aStrings[i] = CORBA::string_dup(aLine.latin1());
1004   }
1005   return aStrings._retn();
1006 }
1007
1008
1009 void SUPERVGUI_PythonEditPane::setFunction(SUPERV_Strings theStr) {
1010   myText->clear();
1011   for ( int i=0, aLen = theStr->length(); i < aLen; i++ )
1012     myText->append(QString(theStr[i]));
1013
1014   // asv : 30.11.04 : 2.7 - Inline node function editor improvement
1015   // 2.7.1 - set focus to editor widget on editor window opening
1016   // 2.7.2 - scroll to the beginning of function on editor window opening
1017   myText->setFocus();
1018   myText->ensureVisible( 0,0 );
1019 }
1020
1021 /**
1022  * Automatic indentation rule: if a previous line ended with 
1023  * ':', then add N additional spaces in the current line.  If no ':' found, then 
1024  * the same amount of spaces as in the previous line is added. Connected to 
1025  * "returnPressed" signal of myText text edit.
1026 */
1027 void SUPERVGUI_PythonEditPane::autoIndentLine() {
1028   const int N = 4; // width of indentation "tab"
1029   if ( myText && myText->paragraphs() ) {
1030
1031     // get current cursor position and previous line (the one to be analized) 
1032     int pos, para, i;
1033     QString spacesStr;
1034     myText->getCursorPosition( &para, &pos ); // pos==0, beginning of line
1035     if ( myText->paragraphLength(para-1) > 0 ) { // mkr : IPAL9817
1036       QString line = myText->text( para-1 ); // previous paragraph line
1037
1038       // construct a string containing all leading space characters of previous line (tabs, etc.)
1039       i = -1;
1040       while ( line[++i].isSpace() ) // append all isSpace() characters at beginning of line to spacesStr
1041         spacesStr += line[i];
1042
1043       // if ':' was found -- add more spaces to spacesStr
1044       line = line.stripWhiteSpace();
1045       if ( line[ line.length()-1 ] == ':' ) {
1046         i = 0;
1047         while ( i++ < N ) 
1048           spacesStr += ' ';
1049       }
1050     }
1051
1052     // ok, append spacesStr at the beginning of the current line = make indentation
1053     myText->insertAt( spacesStr, para, pos );
1054     myText->setCursorPosition( para, pos+spacesStr.length() );
1055   }
1056 }
1057
1058 /**
1059  * Create a node by loading it from an external XML library file
1060  * This slot opens a dialog box which then "lives" by itself..
1061  */
1062 void SUPERVGUI_PythonEditPane::library() {
1063   // if CanImport() returns false, it displays an error message box, so there is no need to
1064   // display such message here ("library file not found", etc.).
1065   if ( SUPERVGUI_Library::getLibrary()->CanImport() ) {
1066     SUPERVGUI_LibDlg* aDlg = new SUPERVGUI_LibDlg( this, myX, myY );
1067     aDlg->exec();
1068   }
1069 }
1070
1071 /*!
1072  * Edit Python dialog
1073  */
1074 SUPERVGUI_EditPythonDlg::SUPERVGUI_EditPythonDlg( bool isLoop )
1075   :QDialog(SUIT_Session::session()->activeApplication()->desktop(), 0, true, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu) 
1076 {
1077   setSizeGripEnabled( true );
1078   setCaption(tr("TIT_FUNC_PYTHON"));
1079   resize( 500, 250 );
1080   QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 4);
1081   int a,b; // dummies for PythonEditPane, not used, since library = false and myX, myY are not used in PythonEditPane
1082   myIsLoop = isLoop; // mkr : PAL12236
1083   if (isLoop) {
1084     QTabWidget* aLoopTabPane = new QTabWidget(this);
1085     myInitPane = new SUPERVGUI_PythonEditPane( this, false, a, b ); // library == false, since no creation of a node is needed here
1086     aLoopTabPane->addTab(myInitPane, "Init");
1087     
1088     myMorePane = new SUPERVGUI_PythonEditPane( this, false, a, b );
1089     aLoopTabPane->addTab(myMorePane, "More");
1090     
1091     myNextPane = new SUPERVGUI_PythonEditPane( this, false, a, b );
1092     aLoopTabPane->addTab(myNextPane, "Next");
1093
1094     aMainLayout->addWidget(aLoopTabPane);    
1095   } else {
1096     myEditPane = new SUPERVGUI_PythonEditPane( this, false, a, b );
1097     aMainLayout->addWidget(myEditPane);
1098   }
1099   QGroupBox* aBtnBox = new QGroupBox( this );
1100   aBtnBox->setColumnLayout( 0, Qt::Vertical );
1101   aBtnBox->layout()->setSpacing( 0 ); aBtnBox->layout()->setMargin( 0 );
1102   QHBoxLayout* aBtnLayout = new QHBoxLayout( aBtnBox->layout() );
1103   aBtnLayout->setAlignment( Qt::AlignTop );
1104   aBtnLayout->setSpacing( 6 ); aBtnLayout->setMargin( 11 );
1105   
1106   QPushButton* aOKBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
1107   connect( aOKBtn, SIGNAL( clicked() ), this, SLOT( clickOnOk() ) );
1108   aBtnLayout->addWidget( aOKBtn );
1109
1110   aBtnLayout->addStretch();
1111
1112   QPushButton* aCancelBtn = new QPushButton( tr("BUT_CANCEL"), aBtnBox );
1113   connect( aCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
1114   aBtnLayout->addWidget( aCancelBtn );
1115
1116   aMainLayout->addWidget(aBtnBox);
1117 }
1118
1119 // mkr : IPAL9817 : to avoid a SIGSEGV when INode_Impl::SetPyFunction(...)
1120 //                  will call with null python function name
1121 void SUPERVGUI_EditPythonDlg::clickOnOk()
1122 {
1123   // mkr : PAL12236
1124   bool hasEmptyName = myIsLoop ? 
1125     ( getInitFuncName().isEmpty() || getMoreFuncName().isEmpty() || getNextFuncName().isEmpty() ) :
1126     getFuncName().isEmpty();
1127
1128   if ( hasEmptyName )
1129     QMessageBox::warning( SUIT_Session::session()->activeApplication()->desktop(), tr( "ERROR" ), tr( "MSG_INCORRECT_INDENT" ) );
1130   else  
1131     accept();
1132 }
1133
1134 /**
1135  * Do the following actions for newly created Engine's CNode:
1136  * 1. Create a presentation for it (CanvasNode)
1137  * 2. Place the CanvasNode to the current top-left corner or the current viewport
1138  * 3. Increment the coordinates of the next CanvasNode (new nodes are "cascaded" when several of them are created at once)
1139  * PS theEndNode is passed only for Loop and Switch nodes (EndLoop and EndSwitch)
1140  */ 
1141 void SUPERVGUI_Service::addNode( SUPERV::CNode_var theNode, SUPERV::INode_var theEndNode, int& theX, int& theY )  {
1142   SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
1143   if ( !aSupMod ) {
1144     MESSAGE("NULL Supervision module!");
1145     return;
1146   }
1147   
1148   SUPERVGUI_Main* aMain = aSupMod->getMain();
1149
1150   if ( !CORBA::is_nil( theNode ) && aMain ) {
1151     
1152     aMain->Editing(); // PAL6170: GUI->Engine: setting "Editing" flag, why here? -> PAL7960
1153
1154     int cx, cy;   //to appear a new node in the top-left corner of the current viewport
1155
1156     //2.8 point of improvements: Adding node to graph window with taking into account zoom factor
1157     QWMatrix aWM = aMain->getCanvasView()->worldMatrix();
1158     aMain->getCanvasView()->viewportToContents(theX, theY, cx, cy);
1159
1160     //2.8 point of improvements:
1161     cx = (int)((double)cx/aWM.m11());
1162     cy = (int)((double)cy/aWM.m22());
1163     theNode->Coords(cx, cy);
1164     if ( !CORBA::is_nil( theEndNode ) )
1165       theEndNode->Coords(cx + LABEL_WIDTH*2, cy);
1166     theX += (int)(NODE_DX*aWM.m11());
1167     theY += (int)(NODE_DY*aWM.m22());
1168
1169     if ( theNode->IsGOTO() )
1170       aMain->addGOTONode( theNode );
1171     else if ( theNode->IsMacro() )
1172       aMain->addMacroNode( theNode );
1173     else if ( theNode->IsLoop() || theNode->IsSwitch() )
1174       aMain->addControlNode( theNode, SUPERV::CNode::_narrow( theEndNode ), true );
1175     else 
1176       aMain->addComputeNode( theNode );
1177     aSupMod->nullifyInitialVF();
1178   }
1179 }
1180
1181 /*!
1182   Constructor
1183 */
1184 SUPERVGUI_CustomSettings::SUPERVGUI_CustomSettings(QListViewItem* theItem,
1185                                                    bool isMultiSel,
1186                                                    bool isCimpl)
1187      : QDialog( SUIT_Session::session()->activeApplication()->desktop(), "", true, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu ) 
1188 {
1189   Trace("SUPERVGUI_CustomSettings::SUPERVGUI_CustomSettings");
1190
1191   SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
1192   if ( !aSupMod ) {
1193     MESSAGE("NULL Supervision module!");
1194     return;
1195   }
1196
1197   SUIT_Desktop* aDesktop = SUIT_Session::session()->activeApplication()->desktop();
1198
1199   setSizeGripEnabled( true );
1200
1201   QGridLayout* TopLayout = new QGridLayout( this );
1202   TopLayout->setSpacing( 6 );
1203   TopLayout->setMargin( 11 );
1204     
1205   QGroupBox* TopGroup = new QGroupBox( this, "TopGroup" );
1206   TopGroup->setColumnLayout(0, Qt::Vertical );
1207   TopGroup->layout()->setSpacing( 0 );
1208   TopGroup->layout()->setMargin( 0 );
1209   QGridLayout* TopGroupLayout = new QGridLayout( TopGroup->layout() );
1210   TopGroupLayout->setAlignment( Qt::AlignTop );
1211   TopGroupLayout->setSpacing( 6 );
1212   TopGroupLayout->setMargin( 11 );
1213
1214   QLabel* authL = new QLabel( tr( "AUTHOR_LBL" ), TopGroup); 
1215   authV = new QLineEdit( TopGroup );
1216   authV->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
1217   authV->setMinimumSize( 200, 0 );
1218   authV->setText( "" );
1219
1220   contL = new QLabel( tr( "CONTAINER_LBL" ), TopGroup ); 
1221   contV = new QLineEdit( TopGroup );
1222   contV->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
1223   contV->setMinimumSize( 200, 0 );
1224   
1225   QLabel* commL = new QLabel( tr( "COMMENT_LBL" ), TopGroup); 
1226   commV = new QMultiLineEdit( TopGroup );
1227   commV->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
1228   commV->setMinimumSize( 200, 100 );
1229
1230   if ( !aSupMod->getInterfaceNameMap().contains(theItem->parent()->parent()->text(0)) ) {
1231     QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
1232     return;
1233   }
1234   const char* component = aSupMod->getInterfaceNameMap().find(theItem->parent()->parent()->text(0)).data();
1235
1236   QString aNodeDefComment;
1237   if ( !isMultiSel ) {
1238     // 1) set caption
1239     const char* service = theItem->text(0).latin1();
1240     aNodeDefComment = QString(service) + QString(tr("COMMENT_FROM")) + QString(component);
1241     setCaption( tr( "TLT_CUSTOMPARAMETERS_SINGLE" ) + aNodeDefComment );
1242   }
1243   else {
1244     // 1) set caption
1245     aNodeDefComment = QString("Factory Node");
1246     setCaption( tr( "TLT_CUSTOMPARAMETERS_MULTI" ) );
1247   }
1248   
1249   // 2) set Container
1250   SUPERVGUI_Main* aMain = aSupMod->getMain();
1251   if (aMain==0) {
1252     QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
1253     return;
1254   }
1255   const char* aContainer = aMain->getDataflow()->ContainerNameForComponent(component);
1256   if ( aContainer && strlen(aContainer) > 0 )
1257     contV->setText( QString(aContainer) );
1258   else if ( isCimpl ) // C++ implementation
1259     contV->setText( QString(aMain->getDataflow()->DefaultCContainerName()) );
1260   else // Python implementation
1261     contV->setText( QString(aMain->getDataflow()->DefaultPythonContainerName()) );
1262
1263   // 3) set comment
1264   commV->setText( aNodeDefComment );
1265
1266   TopGroupLayout->addWidget( authL, 1, 0 );
1267   TopGroupLayout->addWidget( authV, 1, 1 );
1268   TopGroupLayout->addWidget( contL, 2, 0 );
1269   TopGroupLayout->addWidget( contV, 2, 1 );
1270   TopGroupLayout->addWidget( commL, 7, 0 );
1271   TopGroupLayout->addMultiCellWidget( commV, 7, 8, 1, 1 );
1272   TopGroupLayout->addItem( new QSpacerItem( 5, 5, QSizePolicy::Minimum, QSizePolicy::Expanding  ), 8, 0 );
1273   TopGroupLayout->setColStretch( 1, 5 );
1274
1275   QGroupBox* GroupButtons = new QGroupBox( this, "GroupButtons" );
1276   GroupButtons->setColumnLayout(0, Qt::Vertical );
1277   GroupButtons->layout()->setSpacing( 0 );
1278   GroupButtons->layout()->setMargin( 0 );
1279   QGridLayout* GroupButtonsLayout = new QGridLayout( GroupButtons->layout() );
1280   GroupButtonsLayout->setAlignment( Qt::AlignTop );
1281   GroupButtonsLayout->setSpacing( 6 );
1282   GroupButtonsLayout->setMargin( 11 );
1283
1284   QPushButton* okB = new QPushButton( tr( "BUT_OK" ), GroupButtons );
1285   connect( okB,     SIGNAL( clicked() ), this, SLOT( okButton() ) );
1286   QPushButton* cancelB = new QPushButton( tr( "BUT_CANCEL" ), GroupButtons );
1287   connect( cancelB, SIGNAL( clicked() ), this, SLOT( koButton() ) );
1288
1289   GroupButtonsLayout->addWidget( okB, 0, 0 );
1290   GroupButtonsLayout->addItem  ( new QSpacerItem( 5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum ), 0, 1 );
1291   GroupButtonsLayout->addWidget( cancelB, 0, 2 );
1292
1293   TopLayout->addWidget( TopGroup,     0, 0 );
1294   TopLayout->addWidget( GroupButtons, 1, 0 );
1295   TopLayout->setRowStretch( 0, 1 );
1296   TopLayout->setRowStretch( 1, 0 );
1297
1298   resize(370,200);
1299 }
1300
1301 /*!
1302   Destructor
1303 */
1304 SUPERVGUI_CustomSettings::~SUPERVGUI_CustomSettings() {
1305   Trace("SUPERVGUI_CustomSettings::~SUPERVGUI_CustomSettings");
1306 }
1307
1308 /*!
1309   Get author
1310 */
1311 QString SUPERVGUI_CustomSettings::Author() {
1312   return authV->text();
1313 }
1314
1315 /*!
1316   Get container
1317 */
1318 QString SUPERVGUI_CustomSettings::Container() {
1319   return contV->text();
1320 }
1321
1322 /*!
1323   Get comment
1324 */
1325 QString SUPERVGUI_CustomSettings::Comment() {
1326   return commV->text();
1327 }
1328
1329 /*!
1330   <OK> button slot
1331 */
1332 void SUPERVGUI_CustomSettings::okButton() {
1333   Trace("SUPERVGUI_CustomSettings::okButton");
1334   accept();
1335 }
1336
1337 /*!
1338   <Cancel> button slot
1339 */
1340 void SUPERVGUI_CustomSettings::koButton() {
1341   Trace("SUPERVGUI_CustomSettings::koButton");
1342   reject();
1343 }