1 // SUPERV SUPERVGUI : GUI for Supervisor component
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // File : SUPERVGUI_Service.cxx
25 // Author : Francis KLOSS
28 #include "SUPERVGUI_Service.h"
29 #include "SUPERVGUI_Main.h"
30 #include "SUPERVGUI_Library.h"
31 #include "SUPERVGUI.h"
33 #include "CAM_Application.h"
34 #include "SUIT_Desktop.h"
35 #include "SUIT_FileDlg.h"
36 #include "SUIT_Session.h"
37 #include "SUIT_Tools.h"
39 #include "SALOME_NamingService.hxx"
40 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
44 #include <qtextstream.h>
47 static const char * ComponentIcon[] = {
54 " .................. ",
63 " .................. ",
67 " .. .. .. .. .. .. ",
69 " .. .. .. .. .. .. ",
73 static const char * InterfaceIcon[] = {
101 SUPERVGUI_Service::SUPERVGUI_Service(SALOME_NamingService* ns):
102 QDialog(SUIT_Session::session()->activeApplication()->desktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
103 naming(ns), myMFile(0)
105 setSizeGripEnabled( true );
106 setCaption(tr("TIT_SERVICES"));
108 QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 4);
110 myTabPane = new QTabWidget(this);
111 connect(myTabPane, SIGNAL(currentChanged(QWidget *)), this, SLOT(tabChanged(QWidget *)));
113 // Create Tab for Corba services
114 QWidget* aCorbaPane = new QWidget(myTabPane);
115 QVBoxLayout* aBaseLayoutV= new QVBoxLayout(aCorbaPane, 0, 4);
116 aBaseLayoutV->setMargin(5);
117 aBaseLayoutV->setSpacing(10);
119 QHBoxLayout* aBaseLayout = new QHBoxLayout(aCorbaPane); //!!
121 components = new QListView(aCorbaPane);
122 components->addColumn(tr("COL_COMPONENTS"));
123 components->addColumn(tr("COL_PORTTYPE"));
124 components->addColumn(tr("COL_PORTWAY"));
125 components->setColumnAlignment(1, AlignLeft);
126 components->setColumnAlignment(2, AlignLeft);
127 components->setColumnAlignment(3, AlignLeft);
128 components->setSelectionMode(QListView::Extended);
129 components->setRootIsDecorated(true);
130 // aBaseLayout->addWidget(components);
131 aBaseLayoutV->addWidget(components); //!!
133 //QHGroupBox* aAddBox = new QHGroupBox(tr("TIT_ADDNODE"), aCorbaPane); //!!
134 //aAddBox->setInsideSpacing(20); //!!
136 //NRI QPushButton* aComputeCBtn = new QPushButton(tr("TIT_ADDCNODE"), aCorbaPane); //!!
137 //NRI connect(aComputeCBtn, SIGNAL(clicked()), this, SLOT(addComputeNode())); //!!
138 //NRI aComputeCBtn->setDefault(false);
140 QPushButton* aComputeBtn = new QPushButton(tr("TIT_ADDFNODE"), aCorbaPane);
141 connect(aComputeBtn, SIGNAL(clicked()), this, SLOT(addFactoryNode()));
142 aComputeBtn->setDefault(true);
144 aBaseLayout->addWidget(aComputeBtn);
145 //NRI aBaseLayout->addWidget(aComputeCBtn); //!!
147 aBaseLayoutV->insertLayout(-1, aBaseLayout);
148 myTabPane->addTab(aCorbaPane, tr("MODULES_PANE"));
151 // Create Tab for Python services
152 QWidget* aPythonPane = new QWidget(myTabPane);
153 QVBoxLayout* aPythonLayout = new QVBoxLayout(aPythonPane, 0, 4);
154 aPythonLayout->setMargin(5);
155 aPythonLayout->setSpacing(10);
158 QHGroupBox* aAddBox2 = new QHGroupBox(tr("TIT_ADDNODE"), aPythonPane);
159 aAddBox2->setInsideSpacing(20);
161 /*QLabel* aTypeLbl = */new QLabel(tr("LBL_NODETYPE"), aAddBox2);
163 myTypeCombo = new QComboBox(aAddBox2);
164 myTypeCombo->insertItem( tr( "INLINE_COMP" ) );
165 myTypeCombo->insertItem( tr( "INLINE_SWTC" ) );
166 myTypeCombo->insertItem( tr( "INLINE_LOOP" ) );
167 myTypeCombo->insertItem( tr( "INLINE_GOTO") );
168 connect(myTypeCombo, SIGNAL(activated(int)), this, SLOT(typeNodeSelected(int)));
170 aPythonLayout->addWidget(aAddBox2);
173 myStackWidget = new QWidgetStack(aPythonPane);
176 myScriptPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
177 myOtherId = myStackWidget->addWidget(myScriptPane);
180 QTabWidget* aLoopTabPane = new QTabWidget(myStackWidget);
181 myInitPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
182 aLoopTabPane->addTab(myInitPane, "Init");
184 myMorePane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
185 aLoopTabPane->addTab(myMorePane, "More");
187 myNextPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
188 aLoopTabPane->addTab(myNextPane, "Next");
189 myLoopId = myStackWidget->addWidget(aLoopTabPane);
191 myStackWidget->raiseWidget(myOtherId);
193 aPythonLayout->addWidget(myStackWidget, 1);
196 QPushButton* aCreateBtn = new QPushButton(tr("TIT_ADDNODE"), aPythonPane);
197 connect(aCreateBtn, SIGNAL(clicked()), this, SLOT(addInlineNode()));
198 aPythonLayout->addWidget(aCreateBtn);
200 myTabPane->addTab(aPythonPane, tr("INLINE_PANE"));
202 // Create Tab for Macro node only if environmental variable ENABLE_MACRO_NODE is set
203 if ( getenv( "ENABLE_MACRO_NODE" ) != NULL ) {
204 QWidget* aMacroPane = new QWidget(myTabPane);
205 QVBoxLayout* aMacroLayout = new QVBoxLayout(aMacroPane, 0, 4);
206 aMacroLayout->setMargin(5);
207 aMacroLayout->setSpacing(10);
209 QHBoxLayout* aLoadLayout = new QHBoxLayout(aMacroPane); //!!
210 aLoadLayout->addStretch();
212 QPushButton* aLoadBtn = new QPushButton(tr("BUT_LOAD"), aMacroPane);
213 connect(aLoadBtn, SIGNAL(clicked()), this, SLOT(loadGraph()));
215 aLoadLayout->addWidget(aLoadBtn);
217 aMacroLayout->addLayout(aLoadLayout);
219 myMacroPane = new QListView(aMacroPane);
220 myMacroPane->addColumn(tr("COL_COMPONENTS"));
221 myMacroPane->addColumn(tr("COL_PORTTYPE"));
222 myMacroPane->addColumn(tr("COL_PORTWAY"));
223 myMacroPane->setColumnAlignment(1, AlignLeft);
224 myMacroPane->setColumnAlignment(2, AlignLeft);
225 myMacroPane->setColumnAlignment(3, AlignLeft);
226 myMacroPane->setSelectionMode(QListView::Extended);
227 myMacroPane->setRootIsDecorated(true);
228 aMacroLayout->addWidget(myMacroPane); //!!
230 QPushButton* aAddBtn = new QPushButton(tr("TIT_ADDFNODE"), aMacroPane);
231 connect(aAddBtn, SIGNAL(clicked()), this, SLOT(addMacroNode()));
232 aAddBtn->setDefault(true);
234 aMacroLayout->addWidget(aAddBtn);
236 myTabPane->addTab(aMacroPane, tr("MACRO_PANE"));
239 aMainLayout->addWidget(myTabPane);
242 QHBox* aBtnBox = new QHBox(this);
243 QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnBox->layout());
244 aBtnLayout->addStretch();
246 QPushButton* aCloseBtn = new QPushButton(tr("BUT_CLOSE"), aBtnBox);
247 connect(aCloseBtn, SIGNAL(clicked()), this, SLOT(reject()));
249 aMainLayout->addWidget(aBtnBox);
258 char* getDataStreamParameterName(int aType)
276 void SUPERVGUI_Service::initialise() {
277 CORBA::Object_ptr obj = naming->Resolve("/Kernel/ModulCatalog");
278 SALOME_ModuleCatalog::ModuleCatalog_var *aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
279 *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
280 if (CORBA::is_nil(*aModuleCatalog)) {
281 setCaption("Error in Connexion to omniNames with '/Kernel/ModulCatalog'");
285 SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
287 SALOME_ModuleCatalog::ListOfComponents_var lComponents = (*aModuleCatalog)->GetComponentList();
288 long nbComp = lComponents->length();
289 for (int i=0; i<nbComp; i++) {
290 SALOME_ModuleCatalog::Acomponent_ptr C = (*aModuleCatalog)->GetComponent((char *)lComponents[i]);
291 QListViewItem* myComponentItem = new QListViewItem(components, (char*)C->componentusername());
292 myComponentItem->setSelectable(false);
293 QString aIconName = C->component_icone();
294 if (!aIconName.isEmpty()) {
295 QString resFilePath = aResMgr->path(aResMgr->resSection(), C->componentname(), aIconName) ;
297 QPixmap aIcone(resFilePath);
298 QIconSet aIconSet(aIcone);
299 myComponentItem->setPixmap(0, aIconSet.pixmap(QIconSet::Small, QIconSet::Normal));
301 myComponentItem->setPixmap(0, ComponentIcon);
304 myComponentItem->setPixmap(0, ComponentIcon);
306 SALOME_ModuleCatalog::ListOfInterfaces* lInterfaces = C->GetInterfaceList();
307 long nbInterf = lInterfaces->length();
308 for (int j=0; j<nbInterf; j++) {
309 SALOME_ModuleCatalog::DefinitionInterface* Interface = C->GetInterface((char*)(*lInterfaces)[j]);
310 QListViewItem* myInterfaceItem = new QListViewItem(myComponentItem, (char*)Interface->interfacename);
311 myInterfaceItem->setSelectable(false);
312 myInterfaceItem->setPixmap(0, InterfaceIcon);
314 long nbServices = Interface->interfaceservicelist.length();
315 for (int k=0; k<nbServices; k++) {
316 SALOME_ModuleCatalog::Service* Service = &(Interface->interfaceservicelist[k]);
317 QListViewItem* myServiceItem = new QListViewItem(myInterfaceItem, (char*)Service->ServiceName);
318 myServiceItem->setSelectable(true);
319 //components->ensureItemVisible(myServiceItem);
321 long nbPortsOut = Service->ServiceoutParameter.length();
322 for (int m=0; m<nbPortsOut; m++) {
323 SALOME_ModuleCatalog::ServicesParameter* PortOut = &(Service->ServiceoutParameter[m]);
324 QListViewItem* myPortOutItem =
325 new QListViewItem(myServiceItem, (char*)PortOut->Parametername, (char*)PortOut->Parametertype, "Out");
326 myPortOutItem->setSelectable(false);
329 long nbStreamPortsOut = Service->ServiceoutDataStreamParameter.length();
330 for (int m=0; m<nbStreamPortsOut; m++) {
331 SALOME_ModuleCatalog::ServicesDataStreamParameter* PortOut = &(Service->ServiceoutDataStreamParameter[m]);
332 QListViewItem* myPortOutItem =
333 new QListViewItem(myServiceItem, (char*)PortOut->Parametername,
334 getDataStreamParameterName(PortOut->Parametertype), "DataStream Out");
335 myPortOutItem->setSelectable(false);
338 long nbPortsIn = Service->ServiceinParameter.length();
339 for (int l=0; l<nbPortsIn; l++) {
340 SALOME_ModuleCatalog::ServicesParameter* PortIn = &(Service->ServiceinParameter[l]);
341 QListViewItem* myPortInItem =
342 new QListViewItem(myServiceItem, (char*)PortIn->Parametername, (char*)PortIn->Parametertype, "In");
343 myPortInItem->setSelectable(false);
346 long nbStreamPortsIn = Service->ServiceinDataStreamParameter.length();
347 for (int l=0; l<nbStreamPortsIn; l++) {
348 SALOME_ModuleCatalog::ServicesDataStreamParameter* PortIn = &(Service->ServiceinDataStreamParameter[l]);
349 QListViewItem* myPortInItem =
350 new QListViewItem(myServiceItem, (char*)PortIn->Parametername,
351 getDataStreamParameterName(PortIn->Parametertype), "DataStream In");
352 myPortInItem->setSelectable(false);
361 SUPERVGUI_Service::~SUPERVGUI_Service() {
362 Trace("SUPERVGUI_Service::~SUPERVGUI_Service")
363 if (myMFile) delete myMFile;
366 void SUPERVGUI_Service::addComputeNode() {
367 SUIT_Desktop* aDesktop = SUIT_Session::session()->activeApplication()->desktop();
368 CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication());
369 if ( !anApp ) return;
371 SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
373 MESSAGE("NULL Supervision module!");
377 SUPERVGUI_Main* aMain = aSupMod->getMain();
379 QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
380 } else if (!aMain->isEditable()) {
381 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
383 CORBA::Object_ptr obj = naming->Resolve("/Kernel/ModulCatalog");
384 SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
385 *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
386 if (CORBA::is_nil(*aModuleCatalog)) {
387 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
391 QListViewItemIterator i(components);
392 for (; i.current(); ++i) {
394 if (item->isSelected()) {
395 const char* service = item->text(0).latin1();
396 const char* interface = item->parent()->text(0).latin1();
397 const char* component = item->parent()->parent()->text(0).latin1();
398 SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(anApp->moduleName(component));
399 if ( myComponent == NULL ) {
400 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
403 const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
404 SUPERV_CNode aNode = aMain->getDataflow()->CNode(*myService);
405 if ( CORBA::is_nil( aNode ) ) {
406 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
410 SUPERV::INode_var aDummyEndNode;
411 addNode( aNode, aDummyEndNode, myX, myY );
412 b = true; // at least one node was added
417 QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
423 void SUPERVGUI_Service::addFactoryNode() {
424 SUIT_Desktop* aDesktop = SUIT_Session::session()->activeApplication()->desktop();
425 CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication());
426 if ( !anApp ) return;
428 SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
430 MESSAGE("NULL Supervision module!");
434 SUPERVGUI_Main* aMain = aSupMod->getMain();
436 QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
437 } else if (!aMain->isEditable()) {
438 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
440 CORBA::Object_ptr obj = naming->Resolve("/Kernel/ModulCatalog");
441 SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
442 *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
443 if (CORBA::is_nil(*aModuleCatalog)) {
444 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
448 QListViewItemIterator i(components);
449 for (; i.current(); ++i) {
451 if (item->isSelected()) {
452 const char* service = item->text(0).latin1();
453 const char* interface = item->parent()->text(0).latin1();
454 //const char* component = anApp->moduleName(item->parent()->parent()->text(0).latin1());
455 if ( aSupMod->getInterfaceNameMap().contains(item->parent()->text(0)) ) {
456 const char* component = aSupMod->getInterfaceNameMap().find(item->parent()->text(0)).data();
458 SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(component);
459 if (myComponent==NULL) {
460 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
463 const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
465 if ( myService->TypeOfNode == 0 ) { // ComputeNode
466 aNode = aMain->getDataflow()->CNode(*myService);
467 if (CORBA::is_nil( aNode ) ) {
468 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
472 else { // Factory Node
473 aNode = aMain->getDataflow()->FNode(component, interface, *myService, myComponent->implementation_type()); // mkr : PAL11273
474 if ( CORBA::is_nil( aNode ) ) {
475 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
479 SUPERV::INode_var aDummyEndNode;
480 addNode( aNode, aDummyEndNode, myX, myY );
487 QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
494 void SUPERVGUI_Service::addInlineNode() {
495 SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
497 MESSAGE("NULL Supervision module!");
501 SUPERVGUI_Main* aMain = aSupMod->getMain();
503 QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
505 else if (!aMain->isEditable()) {
506 QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
509 int aSel = myTypeCombo->currentItem();
511 case 0: // Computation
514 aMain->getDataflow()->INode(myScriptPane->getFuncName().isEmpty() ? "" : myScriptPane->getFuncName().latin1(),
515 (myScriptPane->getFunction()).in());
516 if (CORBA::is_nil(aNode)) {
517 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
520 SUPERV::INode_var aDummyEndNode;
522 // 1) parse nodes' python function to find ports names
523 // 2) create ports for engine node with found names and "undefined" types
524 // ( aNode->InPort(name,type), aNode->OutPort(name,type) )
525 // P.S. CanvasNode->createPort(...) for create presentation of port
526 // will be called from addNode(...) (inside CanvasNode constructor)
527 addNode( aNode, aDummyEndNode, myX, myY );
533 SUPERV_INode aEndNode;
534 SUPERV_CNode aStartNode =
535 aMain->getDataflow()->SNode(myScriptPane->getFuncName().isEmpty() ? "" : myScriptPane->getFuncName().latin1(),
536 (myScriptPane->getFunction()).in(),
538 if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
539 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
542 addNode( aStartNode, aEndNode, myX, myY );
548 SUPERV_INode aEndNode;
549 SUPERV_CNode aStartNode =
550 aMain->getDataflow()->LNode(myInitPane->getFuncName().isEmpty() ? "" : myInitPane->getFuncName().latin1(),
551 (myInitPane->getFunction()).in(),
552 myMorePane->getFuncName().isEmpty() ? "" : myMorePane->getFuncName().latin1(),
553 (myMorePane->getFunction()).in(),
554 myNextPane->getFuncName().isEmpty() ? "" : myNextPane->getFuncName().latin1(),
555 (myNextPane->getFunction()).in(),
557 if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
558 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
561 addNode( aStartNode, aEndNode, myX, myY );
567 SUPERV_CNode aGotoNode;
568 if (myScriptPane->isDefined())
569 aGotoNode = aMain->getDataflow()->GNode(myScriptPane->getFuncName().latin1(),
570 (myScriptPane->getFunction()).in(), "");
572 aGotoNode = aMain->getDataflow()->GNode("GoTo", (myScriptPane->getFunction()).in(), "");
573 if (CORBA::is_nil(aGotoNode)) {
574 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
577 SUPERV::INode_var aDummyEndNode;
578 addNode( aGotoNode, aDummyEndNode, myX, myY );
585 void SUPERVGUI_Service::addMacroNode() {
586 SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
588 MESSAGE("NULL Supervision module!");
592 SUPERVGUI_Main* aMain = aSupMod->getMain();
594 QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
596 else if (!aMain->isEditable()) {
597 QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
602 if (aMain->getDataflow()->IsStreamGraph()) {
603 SUPERV_StreamGraph aSGraph = aMain->getDataflow()->ToStreamGraph();
604 if (!SUPERV_isNull(aSGraph))
605 aNode = aSGraph->StreamMNode(myMFile->name().latin1());
606 // TMP: while stream macro nodes doesn't impemented
607 if (CORBA::is_nil(aNode)) {
608 aNode = aSGraph->MNode(myMFile->name().latin1());
612 aNode = aMain->getDataflow()->MNode(myMFile->name().latin1());
613 if (CORBA::is_nil(aNode)) {
614 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
618 SUPERV::INode_var aDummyEndNode;
619 addNode( aNode, aDummyEndNode, myX, myY );
622 QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("WARNING"), tr("MSG_NONODE_TOADD"));
627 void SUPERVGUI_Service::loadGraph() {
628 if ( getenv( "ENABLE_MACRO_NODE" ) == NULL )
629 // error! if ENABLE_MACRO_NODE is set - we should NOT get here by any means..
631 //MESSAGE("Error: ENABLE_MACRO_NODE is not set, but loadGraph() was called!");
635 QString aFileName = SUIT_FileDlg::getFileName(SUIT_Session::session()->activeApplication()->desktop(),
638 tr("MSG_GRAPH_INSERT"),
640 if (aFileName.isEmpty()) return;
642 myMacroPane->clear();
644 myMFile = new QFile(aFileName);
645 if (!myMFile->open(IO_ReadOnly)) {
646 QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"),
647 tr("MSG_CANT_LOADSCRIPT"));
648 delete myMFile; myMFile = 0;
652 QTextStream* aStream = new QTextStream(myMFile);
653 if (aStream->atEnd()) {
654 QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"),
655 tr("MSG_EMTY_FILE"));
658 delete myMFile; myMFile = 0;
663 // temporary display only file name
664 QFileInfo anInfo(*myMFile);
665 QListViewItem* anItem = new QListViewItem(myMacroPane, anInfo.baseName());
666 anItem->setSelectable(true);
669 void SUPERVGUI_Service::typeNodeSelected(int theRow) {
671 myStackWidget->raiseWidget(myLoopId);
673 myStackWidget->raiseWidget(myOtherId);
678 void SUPERVGUI_Service::choose() {
679 Trace("SUPERVGUI_Service::choose")
685 void SUPERVGUI_Service::showEvent(QShowEvent* theEvent) {
686 SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
688 MESSAGE("NULL Supervision module!");
692 SUPERVGUI_Main* aMain = aSupMod->getMain();
693 if (aMain && (!aMain->isArrayShown())) {
694 aMain->getArrayView()->viewportToContents(0, 0, myX, myY);
695 //aMain->getGraph()->viewportToContents(0, 0, myX, myY);
697 QDialog::showEvent(theEvent);
701 void SUPERVGUI_Service::tabChanged(QWidget* theWidget) {
702 myIsInline = (myTabPane->currentPageIndex() == 1);
707 //*****************************************************
708 // Pane for Python script editing
709 //*****************************************************
710 SUPERVGUI_PythonEditPane::SUPERVGUI_PythonEditPane( QWidget* theParent, const bool isNodeCreation, int& theX, int& theY )
711 : myIsWithLibrary( isNodeCreation ),
713 myX( theX ), myY( theY )
715 QGridLayout* aEditLayout = new QGridLayout( this, 2, 8, 0, 6 );
718 if ( myIsWithLibrary ) {
719 QPushButton* aLibBtn = new QPushButton(tr("BUT_LIBRARY"), this);
720 connect(aLibBtn, SIGNAL(clicked()), this, SLOT(library()));
721 aEditLayout->addMultiCellWidget( aLibBtn, 0, 0, 1, 2 );
724 QPushButton* aLoadBtn = new QPushButton(tr("BUT_LOAD"), this);
725 connect(aLoadBtn, SIGNAL(clicked()), this, SLOT(loadFile()));
727 aEditLayout->addMultiCellWidget( aLoadBtn, 0, 0, 3, 4 );
729 myFunctionsCombo = new QComboBox( this );
730 connect( myFunctionsCombo, SIGNAL( activated( int ) ), this, SLOT( readFunction( int ) ) );
732 aEditLayout->addMultiCellWidget( myFunctionsCombo, 0, 0, 5, 7 );
735 myText = new QTextEdit(this);
736 myText->setTextFormat( Qt::PlainText ); // NOT rich text, so text() returns plain text
737 myText->setWordWrap( QTextEdit::FixedColumnWidth );
738 myText->setWrapColumnOrWidth( 80 );
739 connect( myText, SIGNAL( returnPressed() ), this, SLOT( autoIndentLine() ) );
741 aEditLayout->addMultiCellWidget( myText, 1, 1, 0, 7 );
742 //aEditLayout->setColStretch( 3, 1 ); // to allow myFunctionsCombo be larger when needed
746 * Return a text between "def" and "("
747 * "def" must begin with position 0, which means that only global function definitions are possible
749 QString getFunctionName( const QString& aLine ) {
750 int aDefPos = aLine.find("def");
751 if ( aDefPos == 0 ) { // only global function definitions!
752 int aStart = aLine.find(" ", aDefPos);
753 int aEnd = aLine.find("(", aStart);
754 QString aName = aLine.mid(aStart, (aEnd-aStart));
755 return aName.stripWhiteSpace();
761 * Searches for text beginning with "def" and ending with any meanful character at
762 * beginning of line. Starts searching with current position of given stream.
763 * Fills the myPyFunctions with strings corresponding to found fucntions.
765 void SUPERVGUI_PythonEditPane::initPyFunctions( QTextStream& theStream ) {
767 if ( theStream.atEnd() )
771 QString aLine = theStream.readLine();
773 while ( !theStream.atEnd() ) { // not EOF
775 // asv : 23.11.04 : fix for PAL6870 : skip empty lines in the beginning or between functions
776 // find("def)==0 -> analizing only global function definitions which start with 0 indentation
777 while ( !aLine.isNull() && aLine.find( "def" ) != 0 )
778 aLine = theStream.readLine();
780 if ( !aLine.isNull() && aLine.find("def") == 0 ) {
781 myFunctionsCombo->insertItem( getFunctionName( aLine ) ); // aLine now == function name
783 aPyFunction += aLine;
786 // read function body
787 aLine = theStream.readLine();
788 // asv : 23.11.04 : added "|| aLine.isEmpty()" - fix for PAL6870. readLine() returns an empty
789 // string for "\n" string, it trails \n caracter. but we accept such lines..
790 // asv : 22.12.04 : aLine[0].isSpace() || aLine[0]=='#' -> line must begin with space or tab
791 // (a normal code with indentation) or comment sign.
792 while ( !aLine.isNull() && ( aLine.isEmpty() || aLine[0].isSpace() || aLine[0] == '#' ) ) {
793 aPyFunction += aLine;
795 aLine = theStream.readLine();
798 myPyFunctions << aPyFunction;
799 aPyFunction.setLength( 0 );
805 * Load existing Python script
807 void SUPERVGUI_PythonEditPane::loadFile() {
808 QString aFileName = SUIT_FileDlg::getFileName(SUIT_Session::session()->activeApplication()->desktop(),
811 tr("TIT_LOADSCRIPT"),
813 if (aFileName.isEmpty()) return;
815 QFile aFile( aFileName );
816 if (!aFile.open(IO_ReadOnly)) {
817 QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"),
818 tr("MSG_CANT_LOADSCRIPT"));
822 myPyFunctions.clear();
823 myFunctionsCombo->clear();
826 QTextStream aFileReader(&aFile);
827 if ( aFileReader.atEnd() ) {
828 QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), tr("MSG_EMTY_FILE"));
833 initPyFunctions( aFileReader );
835 if ( myPyFunctions.size() )
840 * Finds and Reads a function from current position in the opened file
841 * asv : Comment above is old! Present model: just take an already read string = PyFunction
842 * from the list which is filled in loadFile().
844 void SUPERVGUI_PythonEditPane::readFunction( int i ) {
846 if ( i != -1 && myPyFunctions.size() && myPyFunctions.size() > i )
847 myText->append( myPyFunctions[ i ] );
849 // asv : 30.11.04 : 2.7 - Inline node function editor improvement
850 // 2.7.1 - set focus to editor widget on editor window opening
851 // 2.7.2 - scroll to the beginning of function on editor window opening
853 myText->ensureVisible( 0,0 );
857 * Returns the text after "def" and before "(" -- first defined function name
859 QString SUPERVGUI_PythonEditPane::getFuncName() {
860 for (int i=0; i < myText->paragraphs(); i++) {
861 QString aName = getFunctionName( myText->text(i) );
862 if ( !aName.isEmpty() )
869 * Returns the contents of the myText widget without trailing spacing
871 SUPERV_Strings SUPERVGUI_PythonEditPane::getFunction() {
872 SUPERV_Strings aStrings = new SUPERV::ListOfStrings();
873 aStrings->length(myText->paragraphs());
874 for (int i=0; i < myText->paragraphs(); i++) {
875 QString aLine = myText->text(i);
876 // asv : 30.11.04 - why do we have to remove trailing spaces??
877 // it's user's responsibility to enter correct Python code, we don't do anything with it.
878 // if (..) -- initial, while(..) -- my improvement, but also commented out -- needless.
879 //if (!aLine.right(1).compare(" ")) // replaced with the line below -- loop
880 //while (aLine.at(aLine.length()-1).isSpace()) // remove trailing spaces
881 // aLine = aLine.remove(aLine.length()-1,1);
882 aStrings[i] = CORBA::string_dup(aLine.latin1());
884 return aStrings._retn();
888 void SUPERVGUI_PythonEditPane::setFunction(SUPERV_Strings theStr) {
890 for ( int i=0, aLen = theStr->length(); i < aLen; i++ )
891 myText->append(QString(theStr[i]));
893 // asv : 30.11.04 : 2.7 - Inline node function editor improvement
894 // 2.7.1 - set focus to editor widget on editor window opening
895 // 2.7.2 - scroll to the beginning of function on editor window opening
897 myText->ensureVisible( 0,0 );
901 * Automatic indentation rule: if a previous line ended with
902 * ':', then add N additional spaces in the current line. If no ':' found, then
903 * the same amount of spaces as in the previous line is added. Connected to
904 * "returnPressed" signal of myText text edit.
906 void SUPERVGUI_PythonEditPane::autoIndentLine() {
907 const int N = 4; // width of indentation "tab"
908 if ( myText && myText->paragraphs() ) {
910 // get current cursor position and previous line (the one to be analized)
913 myText->getCursorPosition( ¶, &pos ); // pos==0, beginning of line
914 if ( myText->paragraphLength(para-1) > 0 ) { // mkr : IPAL9817
915 QString line = myText->text( para-1 ); // previous paragraph line
917 // construct a string containing all leading space characters of previous line (tabs, etc.)
919 while ( line[++i].isSpace() ) // append all isSpace() characters at beginning of line to spacesStr
920 spacesStr += line[i];
922 // if ':' was found -- add more spaces to spacesStr
923 line = line.stripWhiteSpace();
924 if ( line[ line.length()-1 ] == ':' ) {
931 // ok, append spacesStr at the beginning of the current line = make indentation
932 myText->insertAt( spacesStr, para, pos );
933 myText->setCursorPosition( para, pos+spacesStr.length() );
938 * Create a node by loading it from an external XML library file
939 * This slot opens a dialog box which then "lives" by itself..
941 void SUPERVGUI_PythonEditPane::library() {
942 // if CanImport() returns false, it displays an error message box, so there is no need to
943 // display such message here ("library file not found", etc.).
944 if ( SUPERVGUI_Library::getLibrary()->CanImport() ) {
945 SUPERVGUI_LibDlg* aDlg = new SUPERVGUI_LibDlg( this, myX, myY );
953 SUPERVGUI_EditPythonDlg::SUPERVGUI_EditPythonDlg( bool isLoop )
954 :QDialog(SUIT_Session::session()->activeApplication()->desktop(), 0, true, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu)
956 setSizeGripEnabled( true );
957 setCaption(tr("TIT_FUNC_PYTHON"));
959 QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 4);
960 int a,b; // dummies for PythonEditPane, not used, since library = false and myX, myY are not used in PythonEditPane
961 myIsLoop = isLoop; // mkr : PAL12236
963 QTabWidget* aLoopTabPane = new QTabWidget(this);
964 myInitPane = new SUPERVGUI_PythonEditPane( this, false, a, b ); // library == false, since no creation of a node is needed here
965 aLoopTabPane->addTab(myInitPane, "Init");
967 myMorePane = new SUPERVGUI_PythonEditPane( this, false, a, b );
968 aLoopTabPane->addTab(myMorePane, "More");
970 myNextPane = new SUPERVGUI_PythonEditPane( this, false, a, b );
971 aLoopTabPane->addTab(myNextPane, "Next");
973 aMainLayout->addWidget(aLoopTabPane);
975 myEditPane = new SUPERVGUI_PythonEditPane( this, false, a, b );
976 aMainLayout->addWidget(myEditPane);
978 QGroupBox* aBtnBox = new QGroupBox( this );
979 aBtnBox->setColumnLayout( 0, Qt::Vertical );
980 aBtnBox->layout()->setSpacing( 0 ); aBtnBox->layout()->setMargin( 0 );
981 QHBoxLayout* aBtnLayout = new QHBoxLayout( aBtnBox->layout() );
982 aBtnLayout->setAlignment( Qt::AlignTop );
983 aBtnLayout->setSpacing( 6 ); aBtnLayout->setMargin( 11 );
985 QPushButton* aOKBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
986 connect( aOKBtn, SIGNAL( clicked() ), this, SLOT( clickOnOk() ) );
987 aBtnLayout->addWidget( aOKBtn );
989 aBtnLayout->addStretch();
991 QPushButton* aCancelBtn = new QPushButton( tr("BUT_CANCEL"), aBtnBox );
992 connect( aCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
993 aBtnLayout->addWidget( aCancelBtn );
995 aMainLayout->addWidget(aBtnBox);
998 // mkr : IPAL9817 : to avoid a SIGSEGV when INode_Impl::SetPyFunction(...)
999 // will call with null python function name
1000 void SUPERVGUI_EditPythonDlg::clickOnOk()
1003 bool hasEmptyName = myIsLoop ?
1004 ( getInitFuncName().isEmpty() || getMoreFuncName().isEmpty() || getNextFuncName().isEmpty() ) :
1005 getFuncName().isEmpty();
1008 QMessageBox::warning( SUIT_Session::session()->activeApplication()->desktop(), tr( "ERROR" ), tr( "MSG_INCORRECT_INDENT" ) );
1014 * Do the following actions for newly created Engine's CNode:
1015 * 1. Create a presentation for it (CanvasNode)
1016 * 2. Place the CanvasNode to the current top-left corner or the current viewport
1017 * 3. Increment the coordinates of the next CanvasNode (new nodes are "cascaded" when several of them are created at once)
1018 * PS theEndNode is passed only for Loop and Switch nodes (EndLoop and EndSwitch)
1020 void SUPERVGUI_Service::addNode( SUPERV::CNode_var theNode, SUPERV::INode_var theEndNode, int& theX, int& theY ) {
1021 SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
1023 MESSAGE("NULL Supervision module!");
1027 SUPERVGUI_Main* aMain = aSupMod->getMain();
1029 if ( !CORBA::is_nil( theNode ) && aMain ) {
1031 aMain->Editing(); // PAL6170: GUI->Engine: setting "Editing" flag, why here? -> PAL7960
1033 int cx, cy; //to appear a new node in the top-left corner of the current viewport
1035 //2.8 point of improvements: Adding node to graph window with taking into account zoom factor
1036 QWMatrix aWM = aMain->getCanvasView()->worldMatrix();
1037 aMain->getCanvasView()->viewportToContents(theX, theY, cx, cy);
1039 //2.8 point of improvements:
1040 cx = (int)((double)cx/aWM.m11());
1041 cy = (int)((double)cy/aWM.m22());
1042 theNode->Coords(cx, cy);
1043 if ( !CORBA::is_nil( theEndNode ) )
1044 theEndNode->Coords(cx + LABEL_WIDTH*2, cy);
1045 theX += (int)(NODE_DX*aWM.m11());
1046 theY += (int)(NODE_DY*aWM.m22());
1048 if ( theNode->IsGOTO() )
1049 aMain->addGOTONode( theNode );
1050 else if ( theNode->IsMacro() )
1051 aMain->addMacroNode( theNode );
1052 else if ( theNode->IsLoop() || theNode->IsSwitch() )
1053 aMain->addControlNode( theNode, SUPERV::CNode::_narrow( theEndNode ), true );
1055 aMain->addComputeNode( theNode );
1056 aSupMod->nullifyInitialVF();