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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : SUPERVGUI_Service.cxx
25 // Author : Francis KLOSS
29 #include "SUPERVGUI_Service.h"
30 #include "SUPERVGUI_Main.h"
31 #include "SUPERVGUI_Library.h"
32 #include "SUPERVGUI.h"
33 #include "QAD_Tools.h"
34 #include "QAD_FileDlg.h"
36 #include "SALOME_NamingService.hxx"
37 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
40 #include <qtextstream.h>
43 static const char * ComponentIcon[] = {
50 " .................. ",
59 " .................. ",
63 " .. .. .. .. .. .. ",
65 " .. .. .. .. .. .. ",
69 static const char * InterfaceIcon[] = {
97 SUPERVGUI_Service::SUPERVGUI_Service(SALOME_NamingService* ns):
98 QDialog(QAD_Application::getDesktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
99 naming(ns), myMFile(0)
101 setSizeGripEnabled( true );
102 setCaption(tr("TIT_SERVICES"));
104 QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 4);
106 myTabPane = new QTabWidget(this);
107 connect(myTabPane, SIGNAL(currentChanged(QWidget *)), this, SLOT(tabChanged(QWidget *)));
109 // Create Tab for Corba services
110 QWidget* aCorbaPane = new QWidget(myTabPane);
111 QVBoxLayout* aBaseLayoutV= new QVBoxLayout(aCorbaPane, 0, 4);
112 aBaseLayoutV->setMargin(5);
113 aBaseLayoutV->setSpacing(10);
115 QHBoxLayout* aBaseLayout = new QHBoxLayout(aCorbaPane); //!!
117 components = new QListView(aCorbaPane);
118 components->addColumn(tr("COL_COMPONENTS"));
119 components->addColumn(tr("COL_PORTTYPE"));
120 components->addColumn(tr("COL_PORTWAY"));
121 components->setColumnAlignment(1, AlignLeft);
122 components->setColumnAlignment(2, AlignLeft);
123 components->setColumnAlignment(3, AlignLeft);
124 components->setSelectionMode(QListView::Extended);
125 components->setRootIsDecorated(true);
126 // aBaseLayout->addWidget(components);
127 aBaseLayoutV->addWidget(components); //!!
129 //QHGroupBox* aAddBox = new QHGroupBox(tr("TIT_ADDNODE"), aCorbaPane); //!!
130 //aAddBox->setInsideSpacing(20); //!!
132 //NRI QPushButton* aComputeCBtn = new QPushButton(tr("TIT_ADDCNODE"), aCorbaPane); //!!
133 //NRI connect(aComputeCBtn, SIGNAL(clicked()), this, SLOT(addComputeNode())); //!!
134 //NRI aComputeCBtn->setDefault(false);
136 QPushButton* aComputeBtn = new QPushButton(tr("TIT_ADDFNODE"), aCorbaPane);
137 connect(aComputeBtn, SIGNAL(clicked()), this, SLOT(addFactoryNode()));
138 aComputeBtn->setDefault(true);
140 aBaseLayout->addWidget(aComputeBtn);
141 //NRI aBaseLayout->addWidget(aComputeCBtn); //!!
143 aBaseLayoutV->insertLayout(-1, aBaseLayout);
144 myTabPane->addTab(aCorbaPane, tr("MODULES_PANE"));
147 // Create Tab for Python services
148 QWidget* aPythonPane = new QWidget(myTabPane);
149 QVBoxLayout* aPythonLayout = new QVBoxLayout(aPythonPane, 0, 4);
150 aPythonLayout->setMargin(5);
151 aPythonLayout->setSpacing(10);
154 QHGroupBox* aAddBox2 = new QHGroupBox(tr("TIT_ADDNODE"), aPythonPane);
155 aAddBox2->setInsideSpacing(20);
157 /*QLabel* aTypeLbl = */new QLabel(tr("LBL_NODETYPE"), aAddBox2);
159 myTypeCombo = new QComboBox(aAddBox2);
160 myTypeCombo->insertItem( tr( "INLINE_COMP" ) );
161 myTypeCombo->insertItem( tr( "INLINE_SWTC" ) );
162 myTypeCombo->insertItem( tr( "INLINE_LOOP" ) );
163 myTypeCombo->insertItem( tr( "INLINE_GOTO") );
164 connect(myTypeCombo, SIGNAL(activated(int)), this, SLOT(typeNodeSelected(int)));
166 aPythonLayout->addWidget(aAddBox2);
169 myStackWidget = new QWidgetStack(aPythonPane);
172 myScriptPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
173 myOtherId = myStackWidget->addWidget(myScriptPane);
176 QTabWidget* aLoopTabPane = new QTabWidget(myStackWidget);
177 myInitPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
178 aLoopTabPane->addTab(myInitPane, "Init");
180 myMorePane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
181 aLoopTabPane->addTab(myMorePane, "More");
183 myNextPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
184 aLoopTabPane->addTab(myNextPane, "Next");
185 myLoopId = myStackWidget->addWidget(aLoopTabPane);
187 myStackWidget->raiseWidget(myOtherId);
189 aPythonLayout->addWidget(myStackWidget, 1);
192 QPushButton* aCreateBtn = new QPushButton(tr("TIT_ADDNODE"), aPythonPane);
193 connect(aCreateBtn, SIGNAL(clicked()), this, SLOT(addInlineNode()));
194 aPythonLayout->addWidget(aCreateBtn);
196 myTabPane->addTab(aPythonPane, tr("INLINE_PANE"));
198 // Create Tab for Macro node only if environmental variable ENABLE_MACRO_NODE is set
199 if ( getenv( "ENABLE_MACRO_NODE" ) != NULL ) {
200 QWidget* aMacroPane = new QWidget(myTabPane);
201 QVBoxLayout* aMacroLayout = new QVBoxLayout(aMacroPane, 0, 4);
202 aMacroLayout->setMargin(5);
203 aMacroLayout->setSpacing(10);
205 QHBoxLayout* aLoadLayout = new QHBoxLayout(aMacroPane); //!!
206 aLoadLayout->addStretch();
208 QPushButton* aLoadBtn = new QPushButton(tr("BUT_LOAD"), aMacroPane);
209 connect(aLoadBtn, SIGNAL(clicked()), this, SLOT(loadGraph()));
211 aLoadLayout->addWidget(aLoadBtn);
213 aMacroLayout->addLayout(aLoadLayout);
215 myMacroPane = new QListView(aMacroPane);
216 myMacroPane->addColumn(tr("COL_COMPONENTS"));
217 myMacroPane->addColumn(tr("COL_PORTTYPE"));
218 myMacroPane->addColumn(tr("COL_PORTWAY"));
219 myMacroPane->setColumnAlignment(1, AlignLeft);
220 myMacroPane->setColumnAlignment(2, AlignLeft);
221 myMacroPane->setColumnAlignment(3, AlignLeft);
222 myMacroPane->setSelectionMode(QListView::Extended);
223 myMacroPane->setRootIsDecorated(true);
224 aMacroLayout->addWidget(myMacroPane); //!!
226 QPushButton* aAddBtn = new QPushButton(tr("TIT_ADDFNODE"), aMacroPane);
227 connect(aAddBtn, SIGNAL(clicked()), this, SLOT(addMacroNode()));
228 aAddBtn->setDefault(true);
230 aMacroLayout->addWidget(aAddBtn);
232 myTabPane->addTab(aMacroPane, tr("MACRO_PANE"));
235 aMainLayout->addWidget(myTabPane);
238 QHBox* aBtnBox = new QHBox(this);
239 QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnBox->layout());
240 aBtnLayout->addStretch();
242 QPushButton* aCloseBtn = new QPushButton(tr("BUT_CLOSE"), aBtnBox);
243 connect(aCloseBtn, SIGNAL(clicked()), this, SLOT(reject()));
245 aMainLayout->addWidget(aBtnBox);
254 char* getDataStreamParameterName(int aType)
272 void SUPERVGUI_Service::initialise() {
273 CORBA::Object_ptr obj = naming->Resolve("/Kernel/ModulCatalog");
274 SALOME_ModuleCatalog::ModuleCatalog_var *aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
275 *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
276 if (CORBA::is_nil(*aModuleCatalog)) {
277 setCaption("Error in Connexion to omniNames with '/Kernel/ModulCatalog'");
281 QAD_ResourceMgr* aResMgr = QAD_Desktop::createResourceManager();
283 SALOME_ModuleCatalog::ListOfComponents_var lComponents = (*aModuleCatalog)->GetComponentList();
284 long nbComp = lComponents->length();
285 for (int i=0; i<nbComp; i++) {
286 SALOME_ModuleCatalog::Acomponent_ptr C = (*aModuleCatalog)->GetComponent((char *)lComponents[i]);
287 QListViewItem* myComponentItem = new QListViewItem(components, (char*)C->componentusername());
288 myComponentItem->setSelectable(false);
289 QString aIconName = C->component_icone();
290 if (!aIconName.isEmpty()) {
291 QString resDir = aResMgr->findFile(aIconName, C->componentname()) ;
293 resDir = QAD_Tools::addSlash(resDir);
294 QPixmap aIcone(resDir + aIconName);
295 QIconSet aIconSet(aIcone);
296 myComponentItem->setPixmap(0, aIconSet.pixmap(QIconSet::Small, QIconSet::Normal));
298 myComponentItem->setPixmap(0, ComponentIcon);
301 myComponentItem->setPixmap(0, ComponentIcon);
303 SALOME_ModuleCatalog::ListOfInterfaces* lInterfaces = C->GetInterfaceList();
304 long nbInterf = lInterfaces->length();
305 for (int j=0; j<nbInterf; j++) {
306 SALOME_ModuleCatalog::DefinitionInterface* Interface = C->GetInterface((char*)(*lInterfaces)[j]);
307 QListViewItem* myInterfaceItem = new QListViewItem(myComponentItem, (char*)Interface->interfacename);
308 myInterfaceItem->setSelectable(false);
309 myInterfaceItem->setPixmap(0, InterfaceIcon);
311 long nbServices = Interface->interfaceservicelist.length();
312 for (int k=0; k<nbServices; k++) {
313 SALOME_ModuleCatalog::Service* Service = &(Interface->interfaceservicelist[k]);
314 QListViewItem* myServiceItem = new QListViewItem(myInterfaceItem, (char*)Service->ServiceName);
315 myServiceItem->setSelectable(true);
316 components->ensureItemVisible(myServiceItem);
318 long nbPortsOut = Service->ServiceoutParameter.length();
319 for (int m=0; m<nbPortsOut; m++) {
320 SALOME_ModuleCatalog::ServicesParameter* PortOut = &(Service->ServiceoutParameter[m]);
321 QListViewItem* myPortOutItem =
322 new QListViewItem(myServiceItem, (char*)PortOut->Parametername, (char*)PortOut->Parametertype, "Out");
323 myPortOutItem->setSelectable(false);
326 long nbStreamPortsOut = Service->ServiceoutDataStreamParameter.length();
327 for (int m=0; m<nbStreamPortsOut; m++) {
328 SALOME_ModuleCatalog::ServicesDataStreamParameter* PortOut = &(Service->ServiceoutDataStreamParameter[m]);
329 QListViewItem* myPortOutItem =
330 new QListViewItem(myServiceItem, (char*)PortOut->Parametername,
331 getDataStreamParameterName(PortOut->Parametertype), "DataStream Out");
332 myPortOutItem->setSelectable(false);
335 long nbPortsIn = Service->ServiceinParameter.length();
336 for (int l=0; l<nbPortsIn; l++) {
337 SALOME_ModuleCatalog::ServicesParameter* PortIn = &(Service->ServiceinParameter[l]);
338 QListViewItem* myPortInItem =
339 new QListViewItem(myServiceItem, (char*)PortIn->Parametername, (char*)PortIn->Parametertype, "In");
340 myPortInItem->setSelectable(false);
343 long nbStreamPortsIn = Service->ServiceinDataStreamParameter.length();
344 for (int l=0; l<nbStreamPortsIn; l++) {
345 SALOME_ModuleCatalog::ServicesDataStreamParameter* PortIn = &(Service->ServiceinDataStreamParameter[l]);
346 QListViewItem* myPortInItem =
347 new QListViewItem(myServiceItem, (char*)PortIn->Parametername,
348 getDataStreamParameterName(PortIn->Parametertype), "DataStream In");
349 myPortInItem->setSelectable(false);
358 SUPERVGUI_Service::~SUPERVGUI_Service() {
359 Trace("SUPERVGUI_Service::~SUPERVGUI_Service")
360 if (myMFile) delete myMFile;
363 void SUPERVGUI_Service::addComputeNode() {
364 QAD_Desktop* aDesktop = QAD_Application::getDesktop();
365 SUPERVGUI_Main* aMain = Supervision.getMain();
367 QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
368 } else if (!aMain->isEditable()) {
369 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
371 CORBA::Object_ptr obj = naming->Resolve("/Kernel/ModulCatalog");
372 SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
373 *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
374 if (CORBA::is_nil(*aModuleCatalog)) {
375 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
379 QListViewItemIterator i(components);
380 for (; i.current(); ++i) {
382 if (item->isSelected()) {
383 const char* service = item->text(0).latin1();
384 const char* interface = item->parent()->text(0).latin1();
385 const char* component = item->parent()->parent()->text(0).latin1();
386 SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(aDesktop->getComponentName(component));
387 if ( myComponent == NULL ) {
388 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
391 const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
392 SUPERV_CNode aNode = aMain->getDataflow()->CNode(*myService);
393 if ( CORBA::is_nil( aNode ) ) {
394 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
398 SUPERV::INode_var aDummyEndNode;
399 addNode( aNode, aDummyEndNode, myX, myY );
400 b = true; // at least one node was added
405 QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
411 void SUPERVGUI_Service::addFactoryNode() {
412 QAD_Desktop* aDesktop = QAD_Application::getDesktop();
413 SUPERVGUI_Main* aMain = Supervision.getMain();
415 QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
416 } else if (!aMain->isEditable()) {
417 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
419 CORBA::Object_ptr obj = naming->Resolve("/Kernel/ModulCatalog");
420 SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
421 *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
422 if (CORBA::is_nil(*aModuleCatalog)) {
423 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
427 QListViewItemIterator i(components);
428 for (; i.current(); ++i) {
430 if (item->isSelected()) {
431 const char* service = item->text(0).latin1();
432 const char* interface = item->parent()->text(0).latin1();
433 const char* component = aDesktop->getComponentName(item->parent()->parent()->text(0).latin1());
434 SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(component);
435 if (myComponent==NULL) {
436 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
439 const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
441 if ( myService->TypeOfNode == 0 ) { // ComputeNode
442 aNode = aMain->getDataflow()->CNode(*myService);
443 if (CORBA::is_nil( aNode ) ) {
444 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
448 else { // Factory Node
449 aNode = aMain->getDataflow()->FNode(component, interface, *myService);
450 if ( CORBA::is_nil( aNode ) ) {
451 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
455 SUPERV::INode_var aDummyEndNode;
456 addNode( aNode, aDummyEndNode, myX, myY );
462 QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
469 void SUPERVGUI_Service::addInlineNode() {
470 SUPERVGUI_Main* aMain = Supervision.getMain();
472 QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
474 else if (!aMain->isEditable()) {
475 QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
478 int aSel = myTypeCombo->currentItem();
480 case 0: // Computation
482 SUPERV_CNode aNode = aMain->getDataflow()->INode(myScriptPane->getFuncName().latin1(),
483 (myScriptPane->getFunction()).in());
484 if (CORBA::is_nil(aNode)) {
485 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
488 SUPERV::INode_var aDummyEndNode;
489 addNode( aNode, aDummyEndNode, myX, myY );
495 SUPERV_INode aEndNode;
496 SUPERV_CNode aStartNode = aMain->getDataflow()->SNode(myScriptPane->getFuncName().latin1(),
497 (myScriptPane->getFunction()).in(),
499 if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
500 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
503 addNode( aStartNode, aEndNode, myX, myY );
509 SUPERV_INode aEndNode;
510 SUPERV_CNode aStartNode = aMain->getDataflow()->LNode(myInitPane->getFuncName().latin1(), (myInitPane->getFunction()).in(),
511 myMorePane->getFuncName().latin1(), (myMorePane->getFunction()).in(),
512 myNextPane->getFuncName().latin1(), (myNextPane->getFunction()).in(),
514 if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
515 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
518 addNode( aStartNode, aEndNode, myX, myY );
524 SUPERV_CNode aGotoNode;
525 if (myScriptPane->isDefined())
526 aGotoNode = aMain->getDataflow()->GNode(myScriptPane->getFuncName().latin1(),
527 (myScriptPane->getFunction()).in(), "");
529 aGotoNode = aMain->getDataflow()->GNode("GoTo", (myScriptPane->getFunction()).in(), "");
530 if (CORBA::is_nil(aGotoNode)) {
531 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
534 SUPERV::INode_var aDummyEndNode;
535 addNode( aGotoNode, aDummyEndNode, myX, myY );
542 void SUPERVGUI_Service::addMacroNode() {
543 SUPERVGUI_Main* aMain = Supervision.getMain();
545 QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
547 else if (!aMain->isEditable()) {
548 QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
553 if (aMain->getDataflow()->IsStreamGraph()) {
554 SUPERV_StreamGraph aSGraph = aMain->getDataflow()->ToStreamGraph();
555 if (!SUPERV_isNull(aSGraph))
556 aNode = aSGraph->StreamMNode(myMFile->name().latin1());
557 // TMP: while stream macro nodes doesn't impemented
558 if (CORBA::is_nil(aNode)) {
559 aNode = aSGraph->MNode(myMFile->name().latin1());
563 aNode = aMain->getDataflow()->MNode(myMFile->name().latin1());
564 if (CORBA::is_nil(aNode)) {
565 QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
569 SUPERV::INode_var aDummyEndNode;
570 addNode( aNode, aDummyEndNode, myX, myY );
573 QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NONODE_TOADD"));
578 void SUPERVGUI_Service::loadGraph() {
579 if ( getenv( "ENABLE_MACRO_NODE" ) == NULL )
580 // error! if ENABLE_MACRO_NODE is set - we should NOT get here by any means..
582 //MESSAGE("Error: ENABLE_MACRO_NODE is not set, but loadGraph() was called!");
586 QString aFileName = QAD_FileDlg::getFileName(QAD_Application::getDesktop(),
589 tr("MSG_GRAPH_INSERT"),
591 if (aFileName.isEmpty()) return;
593 myMacroPane->clear();
595 myMFile = new QFile(aFileName);
596 if (!myMFile->open(IO_ReadOnly)) {
597 QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"),
598 tr("MSG_CANT_LOADSCRIPT"));
599 delete myMFile; myMFile = 0;
603 QTextStream* aStream = new QTextStream(myMFile);
604 if (aStream->atEnd()) {
605 QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"),
606 tr("MSG_EMTY_FILE"));
609 delete myMFile; myMFile = 0;
614 // temporary display only file name
615 QFileInfo anInfo(*myMFile);
616 QListViewItem* anItem = new QListViewItem(myMacroPane, anInfo.baseName());
617 anItem->setSelectable(true);
620 void SUPERVGUI_Service::typeNodeSelected(int theRow) {
622 myStackWidget->raiseWidget(myLoopId);
624 myStackWidget->raiseWidget(myOtherId);
629 void SUPERVGUI_Service::choose() {
630 Trace("SUPERVGUI_Service::choose")
636 void SUPERVGUI_Service::showEvent(QShowEvent* theEvent) {
637 SUPERVGUI_Main* aMain = Supervision.getMain();
638 if (aMain && (!aMain->isArrayShown())) {
639 aMain->getArrayView()->viewportToContents(0, 0, myX, myY);
640 //aMain->getGraph()->viewportToContents(0, 0, myX, myY);
642 QDialog::showEvent(theEvent);
646 void SUPERVGUI_Service::tabChanged(QWidget* theWidget) {
647 myIsInline = (myTabPane->currentPageIndex() == 1);
652 //*****************************************************
653 // Pane for Python script editing
654 //*****************************************************
655 SUPERVGUI_PythonEditPane::SUPERVGUI_PythonEditPane( QWidget* theParent, const bool isNodeCreation, int& theX, int& theY )
656 : myIsWithLibrary( isNodeCreation ),
658 myX( theX ), myY( theY )
660 QGridLayout* aEditLayout = new QGridLayout( this, 2, 8, 0, 6 );
663 if ( myIsWithLibrary ) {
664 QPushButton* aLibBtn = new QPushButton(tr("BUT_LIBRARY"), this);
665 connect(aLibBtn, SIGNAL(clicked()), this, SLOT(library()));
666 aEditLayout->addMultiCellWidget( aLibBtn, 0, 0, 1, 2 );
669 QPushButton* aLoadBtn = new QPushButton(tr("BUT_LOAD"), this);
670 connect(aLoadBtn, SIGNAL(clicked()), this, SLOT(loadFile()));
672 aEditLayout->addMultiCellWidget( aLoadBtn, 0, 0, 3, 4 );
674 myFunctionsCombo = new QComboBox( this );
675 connect( myFunctionsCombo, SIGNAL( activated( int ) ), this, SLOT( readFunction( int ) ) );
677 aEditLayout->addMultiCellWidget( myFunctionsCombo, 0, 0, 5, 7 );
680 myText = new QTextEdit(this);
681 myText->setTextFormat( Qt::PlainText ); // NOT rich text, so text() returns plain text
682 myText->setWordWrap( QTextEdit::FixedColumnWidth );
683 myText->setWrapColumnOrWidth( 80 );
684 connect( myText, SIGNAL( returnPressed() ), this, SLOT( autoIndentLine() ) );
686 aEditLayout->addMultiCellWidget( myText, 1, 1, 0, 7 );
687 //aEditLayout->setColStretch( 3, 1 ); // to allow myFunctionsCombo be larger when needed
691 * Return a text between "def" and "("
692 * "def" must begin with position 0, which means that only global function definitions are possible
694 QString getFunctionName( const QString& aLine ) {
695 int aDefPos = aLine.find("def");
696 if ( aDefPos == 0 ) { // only global function definitions!
697 int aStart = aLine.find(" ", aDefPos);
698 int aEnd = aLine.find("(", aStart);
699 QString aName = aLine.mid(aStart, (aEnd-aStart));
700 return aName.stripWhiteSpace();
706 * Searches for text beginning with "def" and ending with any meanful character at
707 * beginning of line. Starts searching with current position of given stream.
708 * Fills the myPyFunctions with strings corresponding to found fucntions.
710 void SUPERVGUI_PythonEditPane::initPyFunctions( QTextStream& theStream ) {
712 if ( theStream.atEnd() )
716 QString aLine = theStream.readLine();
718 while ( !theStream.atEnd() ) { // not EOF
720 // asv : 23.11.04 : fix for PAL6870 : skip empty lines in the beginning or between functions
721 // find("def)==0 -> analizing only global function definitions which start with 0 indentation
722 while ( !aLine.isNull() && aLine.find( "def" ) != 0 )
723 aLine = theStream.readLine();
725 if ( !aLine.isNull() && aLine.find("def") == 0 ) {
726 myFunctionsCombo->insertItem( getFunctionName( aLine ) ); // aLine now == function name
728 aPyFunction += aLine;
731 // read function body
732 aLine = theStream.readLine();
733 // asv : 23.11.04 : added "|| aLine.isEmpty()" - fix for PAL6870. readLine() returns an empty
734 // string for "\n" string, it trails \n caracter. but we accept such lines..
735 // asv : 22.12.04 : aLine[0].isSpace() || aLine[0]=='#' -> line must begin with space or tab
736 // (a normal code with indentation) or comment sign.
737 while ( !aLine.isNull() && ( aLine.isEmpty() || aLine[0].isSpace() || aLine[0] == '#' ) ) {
738 aPyFunction += aLine;
740 aLine = theStream.readLine();
743 myPyFunctions << aPyFunction;
744 aPyFunction.setLength( 0 );
750 * Load existing Python script
752 void SUPERVGUI_PythonEditPane::loadFile() {
753 QString aFileName = QAD_FileDlg::getFileName(QAD_Application::getDesktop(),
756 tr("TIT_LOADSCRIPT"),
758 if (aFileName.isEmpty()) return;
760 QFile aFile( aFileName );
761 if (!aFile.open(IO_ReadOnly)) {
762 QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"),
763 tr("MSG_CANT_LOADSCRIPT"));
767 myPyFunctions.clear();
768 myFunctionsCombo->clear();
771 QTextStream aFileReader(&aFile);
772 if ( aFileReader.atEnd() ) {
773 QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_EMTY_FILE"));
778 initPyFunctions( aFileReader );
780 if ( myPyFunctions.size() )
785 * Finds and Reads a function from current position in the opened file
786 * asv : Comment above is old! Present model: just take an already read string = PyFunction
787 * from the list which is filled in loadFile().
789 void SUPERVGUI_PythonEditPane::readFunction( int i ) {
791 if ( i != -1 && myPyFunctions.size() && myPyFunctions.size() > i )
792 myText->append( myPyFunctions[ i ] );
794 // asv : 30.11.04 : 2.7 - Inline node function editor improvement
795 // 2.7.1 - set focus to editor widget on editor window opening
796 // 2.7.2 - scroll to the beginning of function on editor window opening
798 myText->ensureVisible( 0,0 );
802 * Returns the text after "def" and before "(" -- first defined function name
804 QString SUPERVGUI_PythonEditPane::getFuncName() {
805 for (int i=0; i < myText->paragraphs(); i++) {
806 QString aName = getFunctionName( myText->text(i) );
807 if ( !aName.isEmpty() )
814 * Returns the contents of the myText widget without trailing spacing
816 SUPERV_Strings SUPERVGUI_PythonEditPane::getFunction() {
817 SUPERV_Strings aStrings = new SUPERV::ListOfStrings();
818 aStrings->length(myText->paragraphs());
819 for (int i=0; i < myText->paragraphs(); i++) {
820 QString aLine = myText->text(i);
821 // asv : 30.11.04 - why do we have to remove trailing spaces??
822 // it's user's responsibility to enter correct Python code, we don't do anything with it.
823 // if (..) -- initial, while(..) -- my improvement, but also commented out -- needless.
824 //if (!aLine.right(1).compare(" ")) // replaced with the line below -- loop
825 //while (aLine.at(aLine.length()-1).isSpace()) // remove trailing spaces
826 // aLine = aLine.remove(aLine.length()-1,1);
827 aStrings[i] = CORBA::string_dup(aLine.latin1());
829 return aStrings._retn();
833 void SUPERVGUI_PythonEditPane::setFunction(SUPERV_Strings theStr) {
835 for ( int i=0, aLen = theStr->length(); i < aLen; i++ )
836 myText->append(QString(theStr[i]));
838 // asv : 30.11.04 : 2.7 - Inline node function editor improvement
839 // 2.7.1 - set focus to editor widget on editor window opening
840 // 2.7.2 - scroll to the beginning of function on editor window opening
842 myText->ensureVisible( 0,0 );
846 * Automatic indentation rule: if a previous line ended with
847 * ':', then add N additional spaces in the current line. If no ':' found, then
848 * the same amount of spaces as in the previous line is added. Connected to
849 * "returnPressed" signal of myText text edit.
851 void SUPERVGUI_PythonEditPane::autoIndentLine() {
852 const int N = 4; // width of indentation "tab"
853 if ( myText && myText->paragraphs() ) {
855 // get current cursor position and previous line (the one to be analized)
857 myText->getCursorPosition( ¶, &pos ); // pos==0, beginning of line
858 QString line = myText->text( para-1 ); // previous paragraph line
860 // construct a string containing all leading space characters of previous line (tabs, etc.)
863 while ( line[++i].isSpace() ) // append all isSpace() characters at beginning of line to spacesStr
864 spacesStr += line[i];
866 // if ':' was found -- add more spaces to spacesStr
867 line = line.stripWhiteSpace();
868 if ( line[ line.length()-1 ] == ':' ) {
874 // ok, append spacesStr at the beginning of the current line = make indentation
875 myText->insertAt( spacesStr, para, pos );
876 myText->setCursorPosition( para, pos+spacesStr.length() );
881 * Create a node by loading it from an external XML library file
882 * This slot opens a dialog box which then "lives" by itself..
884 void SUPERVGUI_PythonEditPane::library() {
885 SUPERVGUI_LibDlg* aDlg = new SUPERVGUI_LibDlg( this, myX, myY );
892 SUPERVGUI_EditPythonDlg::SUPERVGUI_EditPythonDlg( bool isLoop )
893 :QDialog(QAD_Application::getDesktop(), 0, true, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu)
895 setSizeGripEnabled( true );
896 setCaption(tr("TIT_FUNC_PYTHON"));
898 QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 4);
899 int a,b; // dummies for PythonEditPane, not used, since library = false and myX, myY are not used in PythonEditPane
901 QTabWidget* aLoopTabPane = new QTabWidget(this);
902 myInitPane = new SUPERVGUI_PythonEditPane( this, false, a, b ); // library == false, since no creation of a node is needed here
903 aLoopTabPane->addTab(myInitPane, "Init");
905 myMorePane = new SUPERVGUI_PythonEditPane( this, false, a, b );
906 aLoopTabPane->addTab(myMorePane, "More");
908 myNextPane = new SUPERVGUI_PythonEditPane( this, false, a, b );
909 aLoopTabPane->addTab(myNextPane, "Next");
911 aMainLayout->addWidget(aLoopTabPane);
913 myEditPane = new SUPERVGUI_PythonEditPane( this, false, a, b );
914 aMainLayout->addWidget(myEditPane);
916 QGroupBox* aBtnBox = new QGroupBox( this );
917 aBtnBox->setColumnLayout( 0, Qt::Vertical );
918 aBtnBox->layout()->setSpacing( 0 ); aBtnBox->layout()->setMargin( 0 );
919 QHBoxLayout* aBtnLayout = new QHBoxLayout( aBtnBox->layout() );
920 aBtnLayout->setAlignment( Qt::AlignTop );
921 aBtnLayout->setSpacing( 6 ); aBtnLayout->setMargin( 11 );
923 QPushButton* aOKBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
924 connect( aOKBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
925 aBtnLayout->addWidget( aOKBtn );
927 aBtnLayout->addStretch();
929 QPushButton* aCancelBtn = new QPushButton( tr("BUT_CANCEL"), aBtnBox );
930 connect( aCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
931 aBtnLayout->addWidget( aCancelBtn );
933 aMainLayout->addWidget(aBtnBox);
937 * Do the following actions for newly created Engine's CNode:
938 * 1. Create a presentation for it (CanvasNode)
939 * 2. Place the CanvasNode to the current top-left corner or the current viewport
940 * 3. Increment the coordinates of the next CanvasNode (new nodes are "cascaded" when several of them are created at once)
941 * PS theEndNode is passed only for Loop and Switch nodes (EndLoop and EndSwitch)
943 void SUPERVGUI_Service::addNode( SUPERV::CNode_var theNode, SUPERV::INode_var theEndNode, int& theX, int& theY ) {
944 if ( !CORBA::is_nil( theNode ) ) {
945 int cx, cy; //to appear a new node in the top-left corner of the current viewport
946 SUPERVGUI_Main* aMain = Supervision.getMain();
948 //2.8 point of improvements: Adding node to graph window with taking into account zoom factor
949 QWMatrix aWM = aMain->getCanvasView()->worldMatrix();
950 aMain->getCanvasView()->viewportToContents(theX, theY, cx, cy);
952 //2.8 point of improvements:
953 cx = (int)((double)cx/aWM.m11());
954 cy = (int)((double)cy/aWM.m22());
955 theNode->Coords(cx, cy);
956 if ( !CORBA::is_nil( theEndNode ) )
957 theEndNode->Coords(cx + LABEL_WIDTH*2, cy);
958 theX += (int)(NODE_DX*aWM.m11());
959 theY += (int)(NODE_DY*aWM.m22());
961 if ( theNode->IsGOTO() )
962 aMain->addGOTONode( theNode );
963 else if ( theNode->IsMacro() )
964 aMain->addMacroNode( theNode );
965 else if ( theNode->IsLoop() || theNode->IsSwitch() )
966 aMain->addControlNode( theNode, SUPERV::CNode::_narrow( theEndNode ), true );
968 aMain->addComputeNode( theNode );