Salome HOME
merge from branch DEV tag mergeto_trunk_04apr08
[modules/yacs.git] / src / gui / YACSGui_ServiceNodePage.cxx
1 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
3 // 
4 //  This library is free software; you can redistribute it and/or 
5 //  modify it under the terms of the GNU Lesser General Public 
6 //  License as published by the Free Software Foundation; either 
7 //  version 2.1 of the License. 
8 // 
9 //  This library is distributed in the hope that it will be useful, 
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 //  Lesser General Public License for more details. 
13 // 
14 //  You should have received a copy of the GNU Lesser General Public 
15 //  License along with this library; if not, write to the Free Software 
16 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
17 // 
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20
21 #include <Python.h>
22 #include <PythonNode.hxx>
23
24 #include <SALOME_ResourcesManager.hxx>
25 #include <SALOME_LifeCycleCORBA.hxx>
26
27 #include <YACSGui_InputPanel.h>
28 #include <YACSGui_Module.h>
29 #include <YACSGui_PlusMinusGrp.h>
30 #include <YACSGui_Table.h>
31 #include <YACSGui_Graph.h>
32 #include <YACSGui_Executor.h>
33 #include <YACSGui_TreeView.h>
34 #include <YACSGui_TreeViewItem.h>
35 #include <YACSGui_LogViewer.h>
36
37 #include <YACSPrs_ElementaryNode.h>
38
39 #include <QxGraph_Canvas.h>
40
41 #include <LightApp_Application.h>
42 #include <CAM_Application.h>
43 #include <SUIT_Session.h>
44 #include <SUIT_Application.h>
45 #include <SUIT_MessageBox.h>
46 #include <LogWindow.h>
47
48 #include <InPort.hxx>
49 #include <OutPort.hxx>
50 #include <InputPort.hxx>
51 #include <OutputPort.hxx>
52 #include <CalStreamPort.hxx>
53 #include <ConditionInputPort.hxx>
54 #include <ForLoop.hxx>
55 #include <ForEachLoop.hxx>
56 #include <WhileLoop.hxx>
57 #include <Switch.hxx>
58 #include <CORBAPorts.hxx>
59 #include <PythonPorts.hxx>
60 #include <XMLPorts.hxx>
61 #include <InlineNode.hxx>
62 #include <ServiceNode.hxx>
63 #include <ServiceInlineNode.hxx>
64 #include <CORBANode.hxx>
65 #include <SalomePythonNode.hxx>
66 #include <CppNode.hxx>
67 #include <XMLNode.hxx>
68 #include <Exception.hxx>
69 #include <Catalog.hxx>
70 #include <ComponentDefinition.hxx>
71 #include <CORBAComponent.hxx>
72 #include <CppComponent.hxx>
73 #include <SalomeComponent.hxx>
74 #include <SalomePythonComponent.hxx>
75 #include <RuntimeSALOME.hxx>
76
77 #include <qwindowsstyle.h>
78 #include <qpushbutton.h>
79 #include <qlayout.h>
80 #include <qhbox.h>
81 #include <qlabel.h>
82 #include <qlineedit.h>
83 #include <qbuttongroup.h>
84 #include <qradiobutton.h>
85 #include <qcombobox.h>
86 #include <qtextedit.h>
87 #include <qtoolbutton.h>
88 #include <qspinbox.h>
89 #include <qprogressbar.h>
90 #include <qobjectlist.h>
91 #include <qfiledialog.h>
92 #include <qcheckbox.h>
93
94 #include <sstream>
95
96 //#define _DEVDEBUG_
97 #include "YacsTrace.hxx"
98
99 #define SPACING 5
100 #define MARGIN 5
101
102 using namespace YACS;
103 using namespace YACS::ENGINE;
104 using namespace YACS::HMI;
105 using namespace std;
106
107
108 /*
109   Class : YACSGui_ServiceNodePage
110   Description :  Page for SALOME and CORBA service nodes properties
111 */
112
113 YACSGui_ServiceNodePage::YACSGui_ServiceNodePage( QWidget* theParent, const char* theName, WFlags theFlags )
114   : ServiceNodePage( theParent, theName, theFlags ),
115     YACSGui_NodePage(),
116     myComponent( 0 ),
117     mySCNode( 0 )
118 {
119   // the possibility to search is hided according to the Num. 14 from NEWS file
120   Search->hide();
121   mySearch->hide();
122
123   //#undef HAVE_QEXTSCINTILLA_H
124 #ifdef HAVE_QEXTSCINTILLA_H
125   _myTextEdit = new QextScintilla( InPythonEditorGroupBox, "Python Editor" );
126   _myTextEdit->setMinimumHeight(150);
127   InPythonEditorGroupBoxLayout->insertWidget(InPythonEditorGroupBoxLayout->findWidget(myTextEdit),
128                                              _myTextEdit );
129   InPythonEditorGroupBoxLayout->remove(myTextEdit);
130   delete myTextEdit;
131   _myTextEdit->setUtf8(1);
132   QextScintillaLexerPython *lex = new QextScintillaLexerPython(_myTextEdit);
133   _myTextEdit->setLexer(lex);
134   _myTextEdit->setBraceMatching(QextScintilla::SloppyBraceMatch);
135   _myTextEdit->setAutoIndent(1);
136   _myTextEdit->setIndentationWidth(4);
137   _myTextEdit->setIndentationGuides(1);
138   _myTextEdit->setIndentationsUseTabs(0);
139   _myTextEdit->setAutoCompletionThreshold(2);
140 #endif
141
142   if ( !myInputPortsGroupBox || !myOutputPortsGroupBox ) return;
143
144   QString aPortTypes = QString("Data Flow;Data Stream (BASIC);Data Stream (CALCIUM);Data Stream (PALM)");
145   QString aValueTypes = QString("Double;Int;String;Bool;Objref;Sequence;Array;Struct");
146
147   // Input Ports table
148   myInputPortsGroupBox->setTitle( tr("Input Ports") );
149   YACSGui_Table* aTable = myInputPortsGroupBox->Table();
150   //aTable->setFixedHeight( 100 );
151   aTable->setNumCols( 4 );
152   aTable->horizontalHeader()->setLabel( 0, tr( "Name" ) );
153   aTable->horizontalHeader()->setLabel( 1, tr( "Class" ) );
154   aTable->horizontalHeader()->setLabel( 2, tr( "Type" ) );
155   aTable->horizontalHeader()->setLabel( 3, tr( "Value" ) );
156   aTable->setColumnWidth(0,58);
157   aTable->setColumnWidth(1,84);
158   aTable->setColumnWidth(2,80);
159   aTable->setCellType( -1, 0, YACSGui_Table::String );
160   aTable->setCellType( -1, 1, YACSGui_Table::Combo );
161   aTable->setCellType( -1, 2, YACSGui_Table::Combo );
162   //aTable->setCellType( -1, 3, YACSGui_Table::??? ); depends on combo box item choosen in the "Value type" column
163
164   aTable->setParams( 0, 1, aPortTypes );
165   aTable->setParams( 0, 2, aValueTypes );
166
167   aTable->setEditorSync(true);
168
169   connect( aTable, SIGNAL(valueChanged( int, int )), this, SLOT(onValueChanged( int, int )) );
170   
171   myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn |
172                                  YACSGui_PlusMinusGrp::InsertBtn | YACSGui_PlusMinusGrp::SelectBtn );
173   myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
174   myInputPortsGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
175
176   // Output Ports table  
177   myOutputPortsGroupBox->setTitle( tr("Output Ports") );
178   aTable = myOutputPortsGroupBox->Table();
179   //aTable->setFixedHeight( 100 );
180   aTable->setNumCols( 5 );
181   aTable->horizontalHeader()->setLabel( 0, tr( "Name" ) );
182   aTable->horizontalHeader()->setLabel( 1, tr( "Class" ) );
183   aTable->horizontalHeader()->setLabel( 2, tr( "Type" ) );
184   aTable->horizontalHeader()->setLabel( 3, tr( "Value" ) );
185   aTable->horizontalHeader()->setLabel( 4, tr( "Is in study" ) );
186   aTable->setColumnWidth(0,58);
187   aTable->setColumnWidth(1,84);
188   aTable->setColumnWidth(2,80);
189
190   aTable->setCellType( -1, 0, YACSGui_Table::String );
191   aTable->setCellType( -1, 1, YACSGui_Table::Combo );
192   aTable->setCellType( -1, 2, YACSGui_Table::Combo );
193   //aTable->setCellType( -1, 3, YACSGui_Table::??? ); depends on combo box item choosen in the "Value type" column
194   aTable->setCellType( -1, 4, YACSGui_Table::Combo );
195
196   aTable->setParams( 0, 1, aPortTypes );
197   aTable->setParams( 0, 2, aValueTypes );
198   aTable->setParams( 0, 4, QString("Yes;No") );
199   aTable->setDefValue( 0, 4, QString("Yes") );
200
201   aTable->setEditorSync(true);
202
203   myPara = 0;
204   myIndex = 0;
205
206   connect( aTable, SIGNAL(valueChanged( int, int )), this, SLOT(onValueChanged( int, int )) );
207
208   myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn |
209                                   YACSGui_PlusMinusGrp::InsertBtn | YACSGui_PlusMinusGrp::SelectBtn );
210   myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
211   myOutputPortsGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
212
213   myProcName = "";
214   myProcRadioButton->setEnabled(false);
215
216   connect( myNodeName, SIGNAL(textChanged( const QString& )), this, SLOT(onNodeNameChanged( const QString& )) );
217   connect( myInstanceName, SIGNAL(activated( const QString& )), this, SLOT(onInstanceNameChanged( const QString& ) ) );
218   connect( myBrowseButton, SIGNAL(clicked(  )), this, SLOT(onBrowse( )) );
219   connect( this, SIGNAL( enableApply( bool ) ), getInputPanel(), SLOT( onApplyEnabled( bool ) ) );
220   connect( CatalogTree, SIGNAL( clicked( QListViewItem* ) ), this, SLOT( onCatalogMethodClicked( QListViewItem* ) ) );
221   connect( mySessionRadioButton, SIGNAL( stateChanged( int ) ), this, SLOT( onCatalogChanged( int ) ) );
222   connect( myProcRadioButton, SIGNAL( stateChanged( int ) ), this, SLOT( onCatalogChanged( int ) ) );
223
224   //connect( this, SIGNAL(visibilityChanged( bool )), this, SLOT(onVisibilityChanged( bool )) );
225 }
226
227 YACSGui_ServiceNodePage::~YACSGui_ServiceNodePage()
228 {
229   if (getInputPanel()) getInputPanel()->removePage(this);
230 }
231
232 void YACSGui_ServiceNodePage::setSCNode( YACS::HMI::SubjectComposedNode* theSCNode )
233 {
234   DEBTRACE("YACSGui_ServiceNodePage::setSCNode");
235   if ( theSCNode && mySCNode != theSCNode )
236     mySCNode = theSCNode;
237 }
238
239 void YACSGui_ServiceNodePage::setSNode( YACS::HMI::SubjectNode* theSNode )
240 {
241   if ( !theSNode ) return;
242
243   if ( YACS::ENGINE::ServiceNode* aServiceNode = dynamic_cast<ServiceNode*>( theSNode->getNode() ) )
244   {
245     myComponentName = QString::null;
246     myComponent = aServiceNode->getComponent();
247     YACSGui_NodePage::setSNode( theSNode );
248   }
249 }
250
251 void YACSGui_ServiceNodePage::setComponent( YACS::ENGINE::ComponentInstance* theComponent )
252 {
253   DEBTRACE("YACSGui_ServiceNodePage::setComponent");
254   if (!theComponent) return;
255   ServiceNode* aServiceNode = dynamic_cast<ServiceNode*>(getNode());
256   if (!aServiceNode) return;
257   ComponentInstance* compo = aServiceNode->getComponent();
258   if (!compo) return;
259   
260   std::string currentInstName = compo->getInstanceName();
261   std::string anInstanceName = theComponent->getInstanceName();
262   
263   if( currentInstName != anInstanceName )
264   {
265     myComponentName = theComponent->getCompoName();
266     myInstanceName->setCurrentText(theComponent->getInstanceName());
267     myComponent = theComponent;
268     updateState();
269
270     YACSGui_ComponentPage* aCompPage = 
271       dynamic_cast<YACSGui_ComponentPage*>( getInputPanel()->getPage( YACSGui_InputPanel::ComponentId ) );
272     if ( aCompPage )
273       aCompPage->setSComponent( GuiContext::getCurrent()->_mapOfSubjectComponent[theComponent], false );
274   }
275 }
276
277 void YACSGui_ServiceNodePage::setMode( const YACSGui_InputPanel::PageMode theMode )
278 {
279   DEBTRACE("YACSGui_ServiceNodePage::setMode");
280   YACSGui_NodePage::setMode(theMode);
281
282   if ( myMode == YACSGui_InputPanel::NewMode )
283   {
284     DEBTRACE("new mode");
285     CatalogGroupBox->show();
286     PortListGroupBox->hide();
287     InPythonEditorGroupBox->hide();
288     NameGroupBox->hide();
289 //     ComponentDefinitionLabel->hide();
290 //     myComponentDefinition->hide();
291 //     MethodName->hide();
292 //     myMethodName->hide();
293     ExecutionGroupBox->hide();
294     stringstream aName;
295     string aType = getInputPanel()->getModule()->getNodeType(SALOMENODE);
296     aName << aType << GuiContext::getCurrent()->getNewId(SALOMENODE);
297     myNodeName->setText(aName.str());
298     myNodeFullName->setText(aName.str());
299     getInputPanel()->onApplyEnabled(false);
300     mySNode = 0;
301     updateState();
302   }
303   else
304   {
305     DEBTRACE("not new mode");
306     CatalogGroupBox->hide();
307     PortListGroupBox->show();
308     NameGroupBox->show();
309 //     ComponentDefinitionLabel->show();
310 //     myComponentDefinition->show();
311 //     MethodName->show();
312 //     myMethodName->show();
313     getInputPanel()->onApplyEnabled(true);
314   }
315
316   myMethodName->setReadOnly(true);
317
318   if ( myMode == YACSGui_InputPanel::EditMode )
319   {
320     DEBTRACE("edit mode");
321     myNodeName->setReadOnly(false);
322     ExecutionGroupBox->hide();
323
324     myInputPortsGroupBox->ShowBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
325     myOutputPortsGroupBox->ShowBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
326   } 
327   else if ( myMode == YACSGui_InputPanel::RunMode )
328   {
329     DEBTRACE("run mode");
330     myNodeName->setReadOnly(true);
331     ExecutionGroupBox->show();
332
333     myInputPortsGroupBox->HideBtn();
334     myOutputPortsGroupBox->HideBtn();
335   }
336 }
337
338 void YACSGui_ServiceNodePage::notifyNodeStatus( int theStatus )
339 {
340   if ( myNodeState )
341   {
342     myNodeState->setPaletteForegroundColor(getColor(theStatus));
343     myNodeState->setText(getText(theStatus));
344   }
345 }
346
347 void YACSGui_ServiceNodePage::notifyNodeProgress()
348 {
349   if ( myProgressBar )
350   {
351     if (!getNode()) return;
352     Proc* aProc = dynamic_cast<Proc*>(getNode()->getRootNode());
353     if ( !aProc ) return;
354
355     YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc );
356     if ( !aGraph ) return;
357
358     if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) )
359     {
360       int aProgress = (int)( ( (anItem->getStoredPercentage() < 0) ? anItem->getPercentage() :
361                                                                      anItem->getStoredPercentage() ) );
362       myProgressBar->setProgress(aProgress);
363     }
364   }
365 }
366
367 void YACSGui_ServiceNodePage::notifyInPortValues( std::map<std::string,std::string> theInPortName2Value )
368 {
369   DEBTRACE("YACSGui_ServiceNodePage::notifyInPortValues");
370   QStringList aValues;
371
372   QStringList aPortNames;
373   myInputPortsGroupBox->Table()->strings( 0, aPortNames );
374
375   for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it )
376   {
377     if ( (*it).isEmpty() ) continue;
378
379     map<string,string>::iterator it1 = theInPortName2Value.find( (*it).latin1() );
380     if ( it1 != theInPortName2Value.end() )
381       aValues.append( QString((*it1).second.c_str()) );
382   }
383
384   if ( aPortNames.count() == aValues.count() )
385     myInputPortsGroupBox->Table()->setStrings( 3, aValues );
386 }
387
388 void YACSGui_ServiceNodePage::notifyOutPortValues( std::map<std::string,std::string> theOutPortName2Value )
389 {
390   DEBTRACE("YACSGui_ServiceNodePage::notifyOutPortValues");
391   QStringList aValues;
392
393   QStringList aPortNames;
394   myOutputPortsGroupBox->Table()->strings( 0, aPortNames );
395
396   for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it )
397   {
398     if ( (*it).isEmpty() ) continue;
399
400     map<string,string>::iterator it1 = theOutPortName2Value.find( (*it).latin1() );
401     if ( it1 != theOutPortName2Value.end() )
402       aValues.append( QString((*it1).second.c_str()) );
403   }
404
405   if ( aPortNames.count() == aValues.count() )
406     myOutputPortsGroupBox->Table()->setStrings( 3, aValues );
407 }
408
409 void YACSGui_ServiceNodePage::checkModifications( bool& theWarnToShow, bool& theToApply )
410 {
411   DEBTRACE("YACSGui_ServiceNodePage::checkModifications " << theWarnToShow <<","<<theToApply);
412   if ( !getNode() || !theWarnToShow && !theToApply ) return;
413
414   // 1) check if the content of the page is really modified (in compare with the content of engine object)
415   bool isModified = false;
416   ServiceNode* aServiceNode = dynamic_cast<ServiceNode*>( getNode() );
417   if ( !aServiceNode ) return;
418
419   if ( myNodeName->text().compare(getNodeName()) != 0) isModified = true;
420
421   if ( !isModified )
422   {
423     if (aServiceNode->getComponent())
424       if(QString::compare(myInstanceName->currentText(),aServiceNode->getComponent()->getInstanceName()) != 0)
425         isModified = true;
426   }
427
428   if ( !isModified )
429   {
430     // read input data and input data stream ports values from the table
431     YACSGui_Table* aTable = myInputPortsGroupBox->Table();
432     aTable->stopEdit(true);
433     
434     QStringList aPortNames;
435     QStringList aValues;
436     
437     aTable->strings( 0, aPortNames );
438     aTable->strings( 3, aValues );
439     
440     int aRowId = 0;
441     for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it )
442     {
443       InPort* anInPort = aServiceNode->getInPort(*it);
444       QString value=aValues[aRowId];
445       if(value.isNull())
446         value="< ? >";
447       DEBTRACE(getPortValue( anInPort ) << "," <<value);
448
449       if ( anInPort && getPortValue( anInPort ).compare(value) != 0 )
450       {
451         isModified = true;
452         break;
453       }
454       aRowId++;
455     }
456   }
457
458   //if ( !isModified )
459   //  TODO: compare "Is in study" fields (not yet in use)
460
461   if ( !isModified  && (myType == ServiceInline || myType == XMLNode) )
462   {
463     // check the code modifications in the built-in Python code editor
464     QString aScript;
465     if ( ServiceInlineNode* aSIN = dynamic_cast<ServiceInlineNode*>( getNode() ) ) aScript = QString(aSIN->getScript());
466     else if ( XmlNode* aXN = dynamic_cast<XmlNode*>( getNode() ) ) aScript = QString(aXN->getScript());
467
468 #ifdef HAVE_QEXTSCINTILLA_H
469     QString theText = _myTextEdit->text();
470 #else
471     QString theText = myTextEdit->text();
472 #endif
473     if ( theText.compare(aScript) != 0 ) isModified = true;
474   }
475     
476   // 2) if yes, show a warning message: Apply or Cancel
477   if ( isModified )
478     if ( theWarnToShow )
479     {
480       theWarnToShow = false;
481       if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(),
482                                   tr("WRN_WARNING"),
483                                   tr("APPLY_CANCEL_MODIFICATIONS"),
484                                   tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 )
485       {
486         onApply();
487         theToApply = true;
488         if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::ServiceNodeId);
489       }
490       else
491         theToApply = false;
492     }
493     else if ( theToApply )
494     {
495       onApply();
496       if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::ServiceNodeId);
497     }
498 }
499
500 void YACSGui_ServiceNodePage::onCatalogChanged( int )
501 {
502   DEBTRACE("YACSGui_ServiceNodePage::onCatalogChanged");
503   getInputPanel()->onApplyEnabled(false);
504
505   // generate name of node if session catalog is active one. Name for proc catalog
506   // is generated when node is selected in catalog view
507   /*if ( !myProcRadioButton->isChecked() )
508   {
509     stringstream aName;
510     string aType = getInputPanel()->getModule()->getNodeType( SALOMENODE );
511     aName << aType << GuiContext::getCurrent()->getNewId( SALOMENODE );
512     myNodeName->setText(aName.str());
513   }*/
514   
515   updateState();
516 }
517
518 void YACSGui_ServiceNodePage::onCatalogMethodClicked( QListViewItem* it )
519 {
520     if ( it )
521   {
522     if ( !myProcRadioButton->isChecked() )
523     {
524       // session catalog is used
525       std::pair<std::string, std::string> compoServ = myServiceMap[it];
526       getInputPanel()->onApplyEnabled(!compoServ.first.empty() && !compoServ.second.empty());
527     }
528     else 
529     {
530       // This block of code is commented because service nodes can be creatwed here only
531
532       // proc catalog is used. Apply button should be enabled if selected item is not
533       // "Nodes" or "Composed nodes" one.
534       QListViewItem* aParent = it->parent();
535       getInputPanel()->onApplyEnabled( aParent != 0 );
536
537       // At the time service nodes can be created only so there is no point in 
538       // regenerating default node name in accordance with its type
539       // Update name
540       if ( myProcNodesMap.count( it ) )
541         {
542           YACS::ENGINE::Node* aNode = myProcNodesMap[ it ];
543           if ( aNode )
544             {
545               YACS::HMI::TypeOfElem aTypeId = ProcInvoc::getTypeOfNode( aNode );
546               stringstream aName;
547               string aType = getInputPanel()->getModule()->getNodeType( aTypeId );
548               aName << aType << GuiContext::getCurrent()->getNewId( aTypeId );
549               myNodeName->setText( aName.str() );
550               myNodeFullName->setText( aName.str() );
551               myNodeType->setText( aType.c_str() );
552             }
553         }
554     }
555   }
556 }
557
558 void YACSGui_ServiceNodePage::onBrowse()
559 {
560   DEBTRACE("YACSGui_ServiceNodePage::onBrowse");
561   QString fn = QFileDialog::getOpenFileName( QString::null,
562                                              tr( "XML-Files (*.xml);;All Files (*)" ),
563                                              this,
564                                              "load YACS scheme file dialog as catalog",
565                                              "Choose a filename to load"  );
566   if ( fn.isEmpty() )
567     return;
568   
569   myProcName = fn.latin1();
570   
571   myProcRadioButton->setEnabled(true);
572   myProcRadioButton->setChecked(true);
573
574   getInputPanel()->onApplyEnabled(false);
575   updateState();
576 }
577
578 void YACSGui_ServiceNodePage::onApply()
579 {
580   DEBTRACE("YACSGui_ServiceNodePage::onApply");
581   if ( myMode == YACSGui_InputPanel::NewMode )
582   {
583     // --- NewMode: import a node or composed node of any type from catalog ---------
584
585     GuiContext* aContext = GuiContext::getCurrent();
586     if ( !aContext ) return;
587
588     YACSGui_Module* aModule = getInputPanel()->getModule();
589     if ( !aModule ) return;
590
591     YACSGui_EditionTreeView * aETV = dynamic_cast<YACSGui_EditionTreeView*>(aModule->activeTreeView());
592     if ( !aETV ) return;
593
594     SubjectProc* aSchema = aContext->getSubjectProc();
595     DEBTRACE("YACSGui_ServiceNodePage::onApply: "<< aSchema);
596
597     YACS::ENGINE::Catalog* aCatalog = 0;
598     if ( myProcRadioButton->isChecked() )
599       {
600         aCatalog = YACS::ENGINE::getSALOMERuntime()->loadCatalog( "proc", myProcName.c_str() );
601         std::string errors=aCatalog->getErrors();
602         if(errors != "")
603           {
604
605             std::string msg="The imported file ";
606             msg=msg+myProcName+" has errors. Some nodes can be uncompletely built\n";
607             LogViewer* log=new LogViewer(msg+errors,getInputPanel()->getModule()->getApp()->desktop(),"dialog",WDestructiveClose);
608             log->show();
609             getInputPanel()->getModule()->getApp()->logWindow()->putMessage(msg+errors );
610           }
611       }
612     else
613       aCatalog = aModule->getCatalog();
614     
615     QListViewItem* anItem = CatalogTree->selectedItem();
616
617     SubjectServiceNode* aNewSNode = 0;
618     if ( aSchema && aCatalog && anItem && mySCNode )
619     {
620       string compo;
621       string service;
622       YACS::HMI::TypeOfElem aTypeId = UNKNOWN;
623       if ( !myProcRadioButton->isChecked() ) 
624       {
625         if ( myServiceMap.find( anItem ) == myServiceMap.end() )
626           return;
627          
628         pair<string, string> compoServ = myServiceMap[anItem];
629         compo = compoServ.first;
630         service = compoServ.second;
631         aTypeId = SALOMENODE;
632       }
633       else 
634       {
635         if ( anItem->text( 0 ).isNull() )
636           return;
637
638         compo = "";
639         service = anItem->text( 0 ).latin1();
640
641         if ( !myProcNodesMap.count( anItem ) )
642           return; // nonsense
643
644         YACS::ENGINE::Node* aNode = myProcNodesMap[ anItem ];
645         
646         // Add node in catalog map if necessary. In the other case it will not be
647         // found in CommandAddNodeFromCatalog method
648         if ( !aCatalog->_nodeMap.count( service ) && 
649              !aCatalog->_composednodeMap.count( service ) )
650         {
651           aCatalog->_nodeMap[ service ] = aNode;
652         }
653
654         YACS::ENGINE::ServiceNode* aServiceNode = 
655           dynamic_cast< YACS::ENGINE::ServiceNode* >( aNode );
656         if ( aServiceNode )
657           aServiceNode->setComponent( 0 );
658
659          aTypeId = ProcInvoc::getTypeOfNode( aNode );
660       }
661
662       myComponentName = compo;
663       myMethodName->setText( service );
664
665       Proc* aProc = aContext->getProc();
666       DEBTRACE("YACSGui_ServiceNodePage::onApply: " << aProc);
667       if ( !aProc ) return;
668
669       YACSGui_Graph* aGraph = aModule->getGraph( aProc );
670       if ( !aGraph ) return;
671
672       stringstream aName;
673       string aType = aModule->getNodeType( aTypeId );
674       aName << aType << aContext->getNewId( aTypeId );
675
676       // ---> block for correct node (engine - subject - presentation) creation
677       SubjectNode* aCreatedSNode = 0;
678       if ( mySCNode )
679       {
680         if ( SubjectSwitch* aSwitch = dynamic_cast<SubjectSwitch*>(mySCNode) )
681         {
682           map<int, SubjectNode*> bodyMap = aSwitch->getBodyMap();
683           int aSwCase = 0;
684           if (bodyMap.empty()) aSwCase = 1;
685           else
686           {
687             map<int, SubjectNode*>::reverse_iterator rit = bodyMap.rbegin();
688             aSwCase = (*rit).first + 1;
689           }
690           aCreatedSNode = aSwitch->addNode( aCatalog, compo, service, aName.str(), aSwCase);
691         }
692         else if ( SubjectForLoop* aForLoop = dynamic_cast<SubjectForLoop*>(mySCNode) )
693         {
694           aCreatedSNode = aModule->createBody( SALOMENODE, mySCNode, aCatalog, compo, service );
695         }
696         else if ( SubjectForEachLoop* aForEachLoop = dynamic_cast<SubjectForEachLoop*>(mySCNode) )
697         {
698           aCreatedSNode = aModule->createBody( SALOMENODE, mySCNode, aCatalog, compo, service );
699         }
700         else if ( SubjectWhileLoop* aWhileLoop = dynamic_cast<SubjectWhileLoop*>(mySCNode) )
701         {
702           aCreatedSNode = aModule->createBody( SALOMENODE, mySCNode, aCatalog, compo, service );
703         }
704         else if ( SubjectProc* aSchema = dynamic_cast<SubjectProc*>(mySCNode) )
705         {
706           DEBTRACE("YACSGui_ServiceNodePage::onApply: " << aSchema);
707           aCreatedSNode = aSchema->addNode( aCatalog, compo, service, aName.str() );
708         }
709         else if ( SubjectBloc* aBloc = dynamic_cast<SubjectBloc*>(mySCNode) )
710         {
711           aCreatedSNode = aBloc->addNode( aCatalog, compo, service, aName.str() );
712           if( SubjectComposedNode* aParent = dynamic_cast<SubjectComposedNode*>(aBloc->getParent()) )
713             aGraph->update(aBloc->getNode(), aParent);
714         }
715       }
716       else
717       {  
718         aCreatedSNode = aSchema->addNode( aCatalog, compo, service, aName.str() );
719       }
720       // <---
721
722       if ( SubjectBloc* aSB = dynamic_cast<SubjectBloc*>(mySCNode) )
723         aSB->update( EDIT, 0, aSB );
724       
725       aNewSNode = dynamic_cast<SubjectServiceNode*>(aCreatedSNode);
726       ServiceNode* aNewNode =0;
727       if ( aNewSNode )
728         aNewNode = dynamic_cast<ServiceNode*>(aNewSNode->getNode());
729       ComponentInstance* aComp = 0;
730       if ( aNewNode )
731         aComp = aNewNode->getComponent();
732       SubjectComponent* aSComp = 0;
733       if ( aComp ) // find the component subject in the current GuiContext
734         if ( aContext->_mapOfSubjectComponent.find(aComp) != aContext->_mapOfSubjectComponent.end() )
735           aSComp = aContext->_mapOfSubjectComponent[aComp];
736       
737       if ( aSComp )
738         {
739           SubjectContainer* aSCont = 0;
740           SalomeContainer* aCont = dynamic_cast<SalomeContainer*>(aComp->getContainer());
741           if ( !aCont )
742             { // container is not found
743               // 1) try to find the first container with the suitable type (i.e. Salome container)
744               //    in the current GuiContext
745               map<Container*, SubjectContainer*>::iterator itCont = aContext->_mapOfSubjectContainer.begin();
746               for ( ; itCont!=aContext->_mapOfSubjectContainer.end(); itCont++ )
747                 {
748                   SalomeContainer* aSalomeCont = dynamic_cast<SalomeContainer*>( (*itCont).first );
749                   if ( aSalomeCont )
750                     {
751                       aSCont = (*itCont).second;
752                       aCont = aSalomeCont;
753                       break;
754                     }
755                 }
756
757               if ( !aSCont )
758                 {
759                   // 2) create a new default Salome container and subject for it
760                   string aDefContainer = "DefaultContainer";
761                   if ( !aProc->containerMap.count(aDefContainer) )
762                     {
763                       aSCont = aSchema->addContainer(aDefContainer);
764                       aCont = dynamic_cast<SalomeContainer*>(aSCont->getContainer());
765                     }
766                 }
767             }
768           else
769             { //container is found => try to get its subject from the current GuiContext
770               if ( aContext->_mapOfSubjectContainer.find(aCont) != aContext->_mapOfSubjectContainer.end() )
771                 aSCont = aContext->_mapOfSubjectContainer[aCont];
772             }
773         
774           if ( aSCont )
775             {
776               YACSGui_ContainerViewItem* aContainerItem = 0;
777
778               // get the "Containers" label view item
779               YACSGui_LabelViewItem* aContainersL = 
780                 dynamic_cast<YACSGui_LabelViewItem*>(aETV->firstChild()->firstChild()->nextSibling()->nextSibling()->nextSibling());
781               if ( !aContainersL || aContainersL->text(0).compare(QString("Containers")) ) return;
782           
783               YACSGui_ContainerViewItem* anAfter = 0;
784               if ( QListViewItem* aChild = aContainersL->firstChild() )
785                 {
786                   while( aChild )
787                     {
788                       if ( anAfter = dynamic_cast<YACSGui_ContainerViewItem*>(aChild) )
789                         if ( anAfter->getContainer() == aCont )
790                           {
791                             aContainerItem = anAfter;
792                             break;
793                           }
794                       aChild = aChild->nextSibling();
795                     }
796                 }
797
798               if ( aContainerItem )
799                 {
800                   aContainerItem->addComponentItem(aSComp);
801                   aSComp->associateToContainer( aSCont );
802                   aNewSNode->associateToComponent(aSComp);
803                 }
804             }
805         }
806
807       aModule->temporaryExport();
808     }  
809
810     // --- commented to avoid to close the NewMode panel    
811 //     aModule->setGuiMode(YACSGui_Module::EditMode);
812 //     setMode(YACSGui_InputPanel::EditMode);
813     if ( aNewSNode ) setSNode(aNewSNode);
814
815     if ( aModule->activeTreeView() )
816       aModule->activeTreeView()->syncPageTypeWithSelection();
817
818     return;
819   }
820
821   // --- not NewMode: edition of an existing Service Node -----------
822
823   // Rename a node
824   if ( myNodeName )
825     setNodeName( myNodeName->text() );
826
827   if ( ServiceNode* aServiceNode = dynamic_cast<ServiceNode*>( getNode() ) )
828   {
829     SubjectServiceNode* aSSNode = dynamic_cast<SubjectServiceNode*>(mySNode);
830     // change component
831     if (ComponentInstance* aPrevComponent = aServiceNode->getComponent())
832       {
833         SubjectComponent* aPrevSComponent = GuiContext::getCurrent()->_mapOfSubjectComponent[aPrevComponent];
834
835         if(QString::compare(myInstanceName->currentText(),aServiceNode->getComponent()->getInstanceName()) != 0)
836           {
837             ComponentInstance* compo = 0;
838             Proc* aProc = GuiContext::getCurrent()->getProc();
839             if (aProc)
840               {
841                 map<pair<string,int>,ComponentInstance*>::const_iterator it = aProc->componentInstanceMap.begin();
842                 for(; it!=aProc->componentInstanceMap.end(); ++it)
843                   {
844                     ComponentInstance *inst=(*it).second;
845                     if (! QString::compare(inst->getInstanceName(), myInstanceName->currentText())) // if same instance name
846                       {
847                         compo = inst;
848                         break;
849                       }
850                   }
851               }
852             if (compo)
853               {
854                 SubjectComponent* aSComp = GuiContext::getCurrent()->_mapOfSubjectComponent[compo];
855                 if ( aSSNode && aSComp ) aSSNode->associateToComponent(aSComp);
856                 setComponent(compo);
857               }
858           }
859       }
860     else
861       {
862         SubjectComponent* aSComp = GuiContext::getCurrent()->_mapOfSubjectComponent[myComponent];
863         if ( aSSNode && aSComp ) aSSNode->associateToComponent(aSComp);
864       }
865   }
866
867   // Reset the list of input ports
868   setInputPorts();
869   
870   // Reset the list of output ports
871   setOutputPorts();
872
873   // Reset Python function/script
874   string aScript = scriptText().isEmpty() ? string("") : scriptText().latin1();
875   if ( ServiceInlineNode* aSIN = dynamic_cast<ServiceInlineNode*>( getNode() ) ) aSIN->setScript( aScript );
876   else if ( XmlNode* aXN = dynamic_cast<XmlNode*>( getNode() ) ) aXN->setScript( aScript );
877
878   updateBlocSize();
879 }
880
881 void YACSGui_ServiceNodePage::buildTree( YACS::ENGINE::Node* theNode,
882                                          QListViewItem* nodeLabel,
883                                          QListViewItem* compoNodeLabel )
884 {
885   if ( !theNode )
886     return;
887
888   // --- Create item corresponding to the node
889   QString aName( theNode->getName().c_str() );
890   if ( aName.isNull())
891     return;
892
893   QListViewItem* theParent = nodeLabel;
894   if (YACS::ENGINE::ComposedNode* aCompNode = dynamic_cast<YACS::ENGINE::ComposedNode*>(theNode))
895     {
896       theParent = compoNodeLabel;
897       std::list<Node*> aNodes = aCompNode->edGetDirectDescendants();
898       std::list<Node*>::iterator anIter;
899       for ( anIter = aNodes.begin(); anIter != aNodes.end(); ++anIter )
900         buildTree( *anIter, nodeLabel, compoNodeLabel );
901     }
902
903   QListViewItem* anItem = new QListViewItem( theParent, aName );
904   anItem->setPixmap( 0, YACSGui_NodeViewItem::icon( theNode ) );
905   myProcNodesMap[ anItem ] = theNode;
906 }
907
908
909 void YACSGui_ServiceNodePage::updateState()
910 {
911   DEBTRACE("YACSGui_ServiceNodePage::updateState");
912   if ( myMode == YACSGui_InputPanel::NewMode )
913     {
914       //DEBTRACE("New mode");
915       //myNodeType->setText( tr( "SALOME_SERVICE_NODE" ) ); // SALOME service node
916       CatalogTree->clear();
917       CatalogTree->setRootIsDecorated( TRUE );
918
919       YACS::ENGINE::Catalog *_currentCatalog =0;
920       if ( myProcRadioButton->isChecked() )
921         {
922           _currentCatalog = YACS::ENGINE::getSALOMERuntime()->loadCatalog( "proc", myProcName.c_str() );
923           std::string errors=_currentCatalog->getErrors();
924           if(errors != "")
925             {
926               std::string msg="The imported file ";
927               msg=msg+myProcName+" has errors. Some nodes can be uncompletely built\n";
928               LogViewer* log=new LogViewer(msg+errors,getInputPanel()->getModule()->getApp()->desktop(),"dialog",WDestructiveClose);
929               log->show();
930               getInputPanel()->getModule()->getApp()->logWindow()->putMessage(msg+errors );
931             }
932         }
933       else
934         _currentCatalog = getInputPanel()->getModule()->getCatalog();
935
936       if ( _currentCatalog )
937         {
938           myProcNodesMap.clear();
939
940           // --- nodes and composed nodes
941           std::map< std::string, Node* >& aNodeMap = _currentCatalog->_nodeMap;
942           std::map< std::string, ComposedNode* >& aCompMap = _currentCatalog->_composednodeMap;
943           QListViewItem* aNodeRoot = new QListViewItem( CatalogTree, tr( "NODES" ) );
944           QListViewItem* aCompRoot = new QListViewItem( CatalogTree, tr( "COMPOSED_NODES" ) );
945
946           if ( aCompMap.size() )
947             {
948               std::map< std::string, ComposedNode* >::iterator cIter;
949               for ( cIter = aCompMap.begin(); cIter != aCompMap.end(); ++cIter )
950                 {
951                   YACS::ENGINE::Node* aNode = cIter->second;
952                   buildTree( aNode, aNodeRoot, aCompRoot );
953                 }
954             }
955           if ( aNodeMap.size() )
956             {
957               std::map< std::string, Node* >::iterator nIter;
958               for ( nIter = aNodeMap.begin(); nIter != aNodeMap.end(); ++nIter )
959                 {
960                   YACS::ENGINE::Node* aNode = nIter->second;
961                   buildTree( aNode, aNodeRoot, aCompRoot );
962                 }
963             }
964
965           // --- composed nodes
966
967           // --- component and services
968           map<string, YACS::ENGINE::ComponentDefinition*>::const_iterator itComp; 
969           for (itComp = _currentCatalog->_componentMap.begin();
970                itComp != _currentCatalog->_componentMap.end();
971                ++itComp)
972             {
973               string compoName = (*itComp).first;
974               YACS::ENGINE::ComponentDefinition* compo = (*itComp).second;
975               QListViewItem *item = new QListViewItem(CatalogTree, compoName.c_str());
976               myServiceMap[item] = pair<string,string>(compoName,"");
977               map<string, YACS::ENGINE::ServiceNode*>::iterator itServ;
978               for (itServ = compo->_serviceMap.begin(); itServ != compo->_serviceMap.end(); ++itServ)
979                 {
980                   string serviceName = (*itServ).first;
981                   YACS::ENGINE::ServiceNode* service = (*itServ).second;
982                   QListViewItem *sitem = new QListViewItem(item, serviceName.c_str());
983                   myServiceMap[sitem] = pair<string,string>(compoName,serviceName);
984                 }
985             }
986         }
987       return;
988     }
989   //DEBTRACE("not new mode");
990
991   if ( myType != SALOMEService )
992   {
993     //DEBTRACE("myType != SALOMEService");
994     myInputPortsGroupBox->ShowBtn( YACSGui_PlusMinusGrp::AllBtn );
995     myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn );
996     myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn |
997                                      YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn |
998                                      YACSGui_PlusMinusGrp::InsertBtn );
999
1000     myOutputPortsGroupBox->ShowBtn( YACSGui_PlusMinusGrp::AllBtn );
1001     myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn );
1002     myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn |
1003                                       YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn |
1004                                       YACSGui_PlusMinusGrp::InsertBtn );
1005   }
1006   else
1007   {
1008     //DEBTRACE("myType == SALOMEService");
1009     myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn |
1010                                    YACSGui_PlusMinusGrp::InsertBtn | YACSGui_PlusMinusGrp::SelectBtn );
1011     myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
1012
1013     myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn |
1014                                     YACSGui_PlusMinusGrp::InsertBtn | YACSGui_PlusMinusGrp::SelectBtn );
1015     myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
1016   }
1017
1018   if ( (myType == ServiceInline || myType == XMLNode) && InPythonEditorGroupBox )
1019   {
1020     // show built-in Python code editor
1021     InPythonEditorGroupBox->show();
1022     connect( mySearch, SIGNAL(returnPressed()), this, SLOT(onSearch()) );
1023   }
1024   else if ( InPythonEditorGroupBox )
1025   {
1026     // hide built-in Python code editor
1027     InPythonEditorGroupBox->hide();
1028     disconnect( mySearch, SIGNAL(returnPressed()), this, SLOT(onSearch()) );
1029   }
1030   
1031   // Clear input ports table and output ports tables, if they are not empty
1032   if ( myInputPortsGroupBox )
1033   {
1034     myInputPortsGroupBox->Table()->setNumRows( 0 );
1035     myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
1036   }
1037   if ( myOutputPortsGroupBox )
1038   {
1039     myOutputPortsGroupBox->Table()->setNumRows( 0 );
1040     myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
1041   }
1042   
1043   // Set node name
1044   if ( myNodeName ) myNodeName->setText( getNodeName() );
1045   
1046   // Set node full name (read only)
1047   if ( myNodeFullName )
1048     myNodeFullName->setText( getNode()->getRootNode()->getChildName(getNode()) );
1049   
1050   // Set node type: SALOME or CORBA service
1051   switch (myType)
1052   {
1053   case SALOMEService:
1054     myNodeType->setText( tr( "SALOME_SERVICE_NODE" ) ); break;
1055   case CORBAService:
1056     myNodeType->setText( tr( "CORBA_SERVICE_NODE" ) );  break;
1057   case CPPNode:
1058     myNodeType->setText( tr( "CPP_NODE" ) );            break;
1059   case ServiceInline:
1060     myNodeType->setText( tr( "SERVICE_INLINE_NODE" ) ); break;
1061   case XMLNode:
1062     myNodeType->setText( tr( "XML_NODE" ) );            break;
1063   default:                                              break;
1064   }
1065
1066   // Set component instance and services
1067   if( myComponentDefinition && myMethodName )
1068     updateServices();
1069
1070   // --- always fill the table seems safer (salome nodes)
1071   // if ( myType == CORBAService || myType == CPPNode /*|| myType == ServiceInline || myType == XMLNode*/ )
1072   {
1073     // Fill the table of input ports of the node
1074     fillInputPortsTable( getNode() );
1075     
1076     // Fill the table of output ports of the node
1077     fillOutputPortsTable( getNode() );
1078   }
1079 }
1080
1081 void YACSGui_ServiceNodePage::onNodeNameChanged( const QString& theName )
1082 {
1083   if ( myNodeFullName )
1084   {
1085     QString anOldName = myNodeFullName->text();
1086     int aRDotId = anOldName.findRev('.');
1087     myNodeFullName->setText( anOldName.replace( aRDotId+1, anOldName.length()-(aRDotId+1), theName ) );
1088   }
1089 }
1090
1091 void YACSGui_ServiceNodePage::onInstanceNameChanged( const QString& theInstanceName )
1092 {
1093   Proc* aProc = GuiContext::getCurrent()->getProc();
1094   if ( !aProc ) return;
1095
1096   ComponentInstance* compo = 0;
1097   map<pair<string,int>,ComponentInstance*>::const_iterator it = aProc->componentInstanceMap.begin();
1098   for(; it!=aProc->componentInstanceMap.end(); ++it)
1099     {
1100       ComponentInstance *inst=(*it).second;
1101       if (! QString::compare(inst->getInstanceName(), theInstanceName)) // if same instance name
1102         {
1103           compo = inst;
1104           break;
1105         }
1106     }
1107   if (!compo) return;
1108   
1109   YACSGui_ComponentPage* aCompPage = 
1110     dynamic_cast<YACSGui_ComponentPage*>( getInputPanel()->getPage( YACSGui_InputPanel::ComponentId ) );
1111   if ( aCompPage )
1112     aCompPage->setSComponent( GuiContext::getCurrent()->_mapOfSubjectComponent[compo], false );
1113 }
1114
1115 void YACSGui_ServiceNodePage::onValueChanged( int theRow, int theCol )
1116 {
1117   DEBTRACE("YACSGui_ServiceNodePage::onValueChanged " << theRow << "," << theCol);
1118   if ( YACSGui_Table* aTable = ( YACSGui_Table* )sender() )
1119     if ( theCol == 2 ) // the value type of the port was changed
1120       setValueCellValidator( aTable, theRow );
1121 }
1122
1123 void YACSGui_ServiceNodePage::hideEvent( QHideEvent* )
1124 {
1125   myPara = 0;
1126   myIndex = 0;
1127 #ifdef HAVE_QEXTSCINTILLA_H
1128 //   _myTextEdit->removeSelection(); // --- see if replacement ?
1129 #else
1130   myTextEdit->removeSelection();
1131 #endif
1132 }
1133
1134 void YACSGui_ServiceNodePage::onSearch()
1135 {
1136 #ifdef HAVE_QEXTSCINTILLA_H
1137   if ( _myTextEdit && mySearch )
1138   {
1139     if ( _myTextEdit->findFirst( mySearch->text(), true, false, true, &myPara, &myIndex ) )
1140     {
1141       _myTextEdit->setSelection( myPara, myIndex, myPara, myIndex + mySearch->text().length() );
1142       myIndex += mySearch->text().length();
1143     } else {
1144       myPara = 0;
1145       myIndex = 0;
1146     }
1147   }
1148 #else
1149   if ( myTextEdit && mySearch )
1150   {
1151     if ( myTextEdit->find( mySearch->text(), true, false, true, &myPara, &myIndex ) )
1152     {
1153       myTextEdit->setSelection( myPara, myIndex, myPara, myIndex + mySearch->text().length() );
1154       myIndex += mySearch->text().length();
1155     } else {
1156       myPara = 0;
1157       myIndex = 0;
1158     }
1159   }
1160 #endif
1161 }
1162
1163 void YACSGui_ServiceNodePage::updateServices()
1164 {
1165   if ( !myComponent )
1166   {
1167     if ( myComponentDefinition ) myComponentDefinition->clear();
1168     if ( myMethodName ) myMethodName->clear();
1169     return;
1170   }
1171
1172   YACS::ENGINE::ServiceNode* aServiceNode = dynamic_cast<ServiceNode*>( getNode() );
1173   if( !aServiceNode ) return;
1174
1175   if( myComponentName.isNull() )
1176     myComponentName = aServiceNode->getComponent()->getCompoName();
1177
1178   myComponentDefinition->setText( myComponentName );
1179   myMethodName->setText( aServiceNode->getMethod() );
1180   fillInstanceNames();
1181   myInstanceName->setCurrentText( aServiceNode->getComponent()->getInstanceName() );
1182
1183   fillInputPortsTable( aServiceNode );
1184   fillOutputPortsTable( aServiceNode );
1185 }
1186
1187 void YACSGui_ServiceNodePage::fillInstanceNames()
1188 {
1189   myInstanceName->clear();
1190   YACS::ENGINE::ServiceNode* aServiceNode = dynamic_cast<ServiceNode*>( getNode() );
1191   if( !aServiceNode ) return;
1192   ComponentInstance* compo = aServiceNode->getComponent();
1193   if (!compo) return;
1194
1195   if (compo->getKind() == "Salome")
1196     myInstanceName->setEnabled(true);
1197   else
1198     myInstanceName->setEnabled(false);  
1199
1200   Proc* aProc = GuiContext::getCurrent()->getProc();
1201   if ( !aProc ) return;
1202
1203   map<pair<string,int>,ComponentInstance*>::const_iterator it = aProc->componentInstanceMap.begin();
1204   for(; it!=aProc->componentInstanceMap.end(); ++it)
1205     {
1206       ComponentInstance *inst=(*it).second;
1207       QString aComponentName = inst->getCompoName();
1208       if (! QString::compare(compo->getCompoName(), aComponentName)) // if same component name
1209         myInstanceName->insertItem( QString(inst->getInstanceName()));
1210     }
1211 }
1212
1213 void YACSGui_ServiceNodePage::fillInputPortsTable( YACS::ENGINE::Node* theNode )
1214 {
1215   DEBTRACE("YACSGui_ServiceNodePage::fillInputPortsTable");
1216   if( !theNode )
1217     return;
1218
1219   QStringList aPortNames;
1220   QStringList aPortTypes;
1221   QStringList aValueTypes;
1222   QStringList aValues;
1223
1224   QValueList<bool> aReadOnlyFlags;
1225
1226   YACSGui_Table* aTable = myInputPortsGroupBox->Table();
1227   QStringList aPTCB = aTable->Params( 0, 1 );
1228
1229   list<InPort*> anInPortsEngine = theNode->getSetOfInPort();
1230   list<InPort*>::iterator anInPortsIter = anInPortsEngine.begin();
1231   for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++)
1232   {
1233     InPort* anInPort = *anInPortsIter;
1234
1235     // Collect port names in the list
1236     aPortNames.append( anInPort->getName() );
1237     
1238     // Port type
1239     if ( InputPort* anInputP = dynamic_cast<InputPort*>(anInPort) )
1240     {
1241       aPortTypes.append( aPTCB[0] );
1242
1243       int nbLinks = anInPort->edGetNumberOfLinks();
1244       aReadOnlyFlags.append( nbLinks > 0 );
1245     }
1246     //else if ( InputBasicStreamPort* aBasicStreamP = dynamic_cast<InputBasicStreamPort*>(anInPort) )
1247     //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box
1248     //  aPortTypes.append( aPTCB[1] ); 
1249     //}
1250     else if ( InputCalStreamPort* aCalStreamP = dynamic_cast<InputCalStreamPort*>(anInPort) )
1251     {
1252       aPortTypes.append( aPTCB[2] );
1253       aReadOnlyFlags.append( true );
1254     }
1255     //else if ( InputPalmStreamPort* aPalmStreamP = dynamic_cast<InputPalmStreamPort*>(anInPort) )
1256     //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box
1257     //  aPortTypes.append( aPTCB[3] );
1258     //}
1259     else if ( InputDataStreamPort* aCalStreamP = dynamic_cast<InputDataStreamPort*>(anInPort) )
1260     {
1261       aPortTypes.append( aPTCB[2] );
1262       aReadOnlyFlags.append( true );
1263     }
1264     else
1265     { // take default value from combo box
1266       aPortTypes.append( aPTCB[0] );
1267       aReadOnlyFlags.append( true );
1268     }
1269
1270     // Value type
1271     aValueTypes.append( getPortType( anInPort ) );
1272
1273     // Value
1274     aValues.append( getPortValue( anInPort ) );
1275   }
1276
1277   // Fill "Port name" column
1278   aTable->setStrings( 0, aPortNames, true );
1279
1280   // Fill "Port type" column
1281   aTable->setStrings( 1, aPortTypes, true );
1282
1283   // Fill "Value type" column
1284   aTable->setStrings( 2, aValueTypes, true );
1285
1286   if ( myType == SALOMEService )
1287     // Set the valid cell type for the input ports values
1288     for ( int i=0; i<aTable->numRows(); i++ )
1289       setValueCellValidator( aTable, i );
1290
1291   // Fill "Value" column
1292   aTable->setStrings( 3, aValues, true );
1293
1294   if ( myType == SALOMEService )
1295   {
1296     // Set all columns read only (except "Value" column)
1297     aTable->setReadOnly( -1, 0, true );
1298     aTable->setReadOnly( -1, 1, true );
1299     aTable->setReadOnly( -1, 2, true );
1300   }
1301
1302   // Set "Value" column read only (for linked ports)
1303   for ( int i = 0, n = aTable->numRows(); i < n; i++ )
1304   {
1305     aTable->setDefValue( i, 2, aValueTypes[i] );
1306     aTable->setReadOnly( i, 3, aReadOnlyFlags[ i ] );
1307   }
1308   
1309   if ( aPortNames.count() > 1 )
1310     myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
1311
1312 }
1313
1314 void YACSGui_ServiceNodePage::fillOutputPortsTable( YACS::ENGINE::Node* theNode )
1315 {
1316   if( !theNode )
1317     return;
1318
1319   QStringList aPortNames;
1320   QStringList aPortTypes;
1321   QStringList aValueTypes;
1322   QStringList aValues;
1323   QStringList anIsInStudy;
1324   
1325   YACSGui_Table* aTable = myOutputPortsGroupBox->Table();
1326   QStringList aPTCB = aTable->Params( 0, 1 );
1327
1328   list<OutPort*> anOutPortsEngine = theNode->getSetOfOutPort();
1329   list<OutPort*>::iterator anOutPortsIter = anOutPortsEngine.begin();
1330   for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++)
1331   {
1332     OutPort* anOutPort = *anOutPortsIter;
1333
1334     // Collect port names in the list
1335     aPortNames.append( anOutPort->getName() );
1336     
1337     // Port type
1338     if ( OutputPort* anOutputP = dynamic_cast<OutputPort*>(anOutPort) )
1339     {
1340       aPortTypes.append( aPTCB[0] );
1341     }
1342     //else if ( OutputBasicStreamPort* aBasicStreamP = dynamic_cast<OutputBasicStreamPort*>(anOutPort) )
1343     //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box
1344     //  aPortTypes.append( aPTCB[1] ); 
1345     //}
1346     else if ( OutputCalStreamPort* aCalStreamP = dynamic_cast<OutputCalStreamPort*>(anOutPort) )
1347     {
1348       aPortTypes.append( aPTCB[2] );
1349     }
1350     //else if ( OutputPalmStreamPort* aPalmStreamP = dynamic_cast<OutputPalmStreamPort*>(anOutPort) )
1351     //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box
1352     //  aPortTypes.append( aPTCB[3] );
1353     //}
1354     else if ( OutputDataStreamPort* aCalStreamP = dynamic_cast<OutputDataStreamPort*>(anOutPort) )
1355     {
1356       aPortTypes.append( aPTCB[2] );
1357     }
1358     else
1359     { // take default value from combo box
1360       aPortTypes.append( aPTCB[0] );
1361     }
1362       
1363     // Value type
1364     aValueTypes.append( getPortType( anOutPort ) );
1365
1366     // Value
1367     aValues.append( getPortValue( anOutPort ) );
1368
1369     // Is in study
1370     // There is no a such parameter either in engine or GUI at the current moment.
1371     // TODO: we need to implement it at GUI side.
1372     // As a temporary solution we set the default value
1373     anIsInStudy.append( aTable->defValue( 0, 4 ) );
1374   }
1375
1376   // Fill "Port name" column
1377   aTable->setStrings( 0, aPortNames, true );
1378
1379   // Fill "Port type" column
1380   aTable->setStrings( 1, aPortTypes, true );
1381
1382   // Fill "Value type" column
1383   aTable->setStrings( 2, aValueTypes, true );
1384
1385   // Fill "Value" column
1386   aTable->setStrings( 3, aValues, true );
1387
1388   // Fill "Is in study" column
1389   aTable->setStrings( 4, anIsInStudy, true );
1390
1391   if ( myType == SALOMEService )
1392   {
1393     // Set all columns read only
1394     aTable->setReadOnly( -1, 0, true );
1395     aTable->setReadOnly( -1, 1, true );
1396     aTable->setReadOnly( -1, 2, true );
1397     aTable->setReadOnly( -1, 3, true );
1398   }
1399
1400   for ( int i = 0, n = aTable->numRows(); i < n; i++ )
1401     aTable->setDefValue( i, 2, aValueTypes[i] );
1402
1403   if ( aPortNames.count() > 1 )
1404     myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn );
1405 }
1406
1407 QString YACSGui_ServiceNodePage::getPortType( YACS::ENGINE::Port* thePort ) const
1408 {
1409   QString aType;
1410
1411   YACSGui_Table* aTable = 0;
1412   if ( dynamic_cast<InPort*>(thePort) )
1413     aTable = myInputPortsGroupBox->Table();
1414   else if ( dynamic_cast<OutPort*>(thePort) )
1415     aTable = myOutputPortsGroupBox->Table();
1416
1417   if ( !aTable ) return aType;
1418
1419   QStringList aVTCB = aTable->Params( 0, 2 );
1420
1421   if ( DataPort* aDataPort = dynamic_cast<DataPort*>(thePort) )
1422   {
1423     DynType aDType = aDataPort->edGetType()->kind();
1424     if ( aDType > NONE && aDType < Objref ) //if (aDType != NONE)
1425       aType = aVTCB[aDType-1];
1426     else
1427       aType = QString(aDataPort->edGetType()->name());
1428     //SCRUTE(aType);
1429   }
1430   
1431   return aType;
1432 }
1433
1434 void YACSGui_ServiceNodePage::setInputPorts()
1435 {
1436   DEBTRACE("YACSGui_ServiceNodePage::setInputPorts");
1437   if ( !myInputPortsGroupBox ) return;
1438
1439   ServiceNode* aNode = dynamic_cast<ServiceNode*>( getNode() );
1440   if ( !aNode ) return;
1441
1442   myInputPortsGroupBox->Table()->stopEdit(true);
1443
1444   if ( myType != SALOMEService )
1445   {
1446     // remove old ports
1447     list<InPort*> anInPortsEngine = aNode->getSetOfInPort();
1448     list<InPort*>::iterator anInPortsIter = anInPortsEngine.begin();
1449     for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++)
1450     {
1451       mySNode->update( REMOVE,
1452                        ( dynamic_cast<InputPort*>(*anInPortsIter) ? INPUTPORT : INPUTDATASTREAMPORT ),
1453                        GuiContext::getCurrent()->_mapOfSubjectDataPort[*anInPortsIter] );
1454       
1455       //aNode->edRemovePort(*anInPortsIter);
1456       // remove port subject (and all subject links connected to this port)
1457       mySNode->destroy( GuiContext::getCurrent()->_mapOfSubjectDataPort[*anInPortsIter] );
1458     }
1459     
1460     // create a set of new input ports
1461     YACS::ENGINE::Catalog* aCatalog = getInputPanel()->getModule()->getCatalog();
1462     if ( aCatalog && aNode->getComponent()
1463          &&
1464          aCatalog->_componentMap.count(aNode->getComponent()->getCompoName()) )
1465     {
1466       ComponentDefinition* aCompodef = aCatalog->_componentMap[aNode->getComponent()->getCompoName()];
1467       if ( aCompodef && aCompodef->_serviceMap.count(aNode->getMethod()) )
1468         if ( ServiceNode* aNodeToClone = aCompodef->_serviceMap[aNode->getMethod()] )
1469         {
1470           list<InPort*> anInPortsClone = aNodeToClone->getSetOfInPort();
1471           list<InPort*>::iterator anInPortsIter = anInPortsClone.begin();
1472           for( ;anInPortsIter!=anInPortsClone.end();anInPortsIter++)
1473             if ( InputPort* anIP = dynamic_cast<InputPort*>(*anInPortsIter) ) // Data Flow port
1474               dynamic_cast<SubjectElementaryNode*>(mySNode)->addInputPort( aCatalog,
1475                                                                            portValueType(anIP->edGetType()),
1476                                                                            anIP->getName() );
1477             else if ( InputDataStreamPort* anIDSP = dynamic_cast<InputDataStreamPort*>(*anInPortsIter) ) // Data Stream port
1478               dynamic_cast<SubjectElementaryNode*>(mySNode)->addIDSPort( aCatalog,
1479                                                                          portValueType(anIDSP->edGetType()),
1480                                                                          anIDSP->getName() );
1481         }
1482     }
1483   }
1484   
1485   // read input data and input data stream ports from the table
1486   YACSGui_Table* aTable = myInputPortsGroupBox->Table();
1487   
1488   QStringList aPortNames;
1489   QStringList aValues;
1490
1491   aTable->strings( 0, aPortNames );
1492   aTable->strings( 3, aValues );
1493
1494   // initialize created input ports with values
1495   int aRowId = 0;
1496   for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it,++aRowId )
1497   {
1498     if ( (*it).isEmpty() ) continue;
1499
1500     if ( aTable->intValueCombo( 1, aRowId ) == 0 ) // Data Flow port
1501     {
1502       InputPort* aIDP;
1503       try {
1504         aIDP = aNode->getInputPort(*it);
1505       }
1506       catch (YACS::Exception& ex) {
1507         continue;
1508       }
1509       if ( !aIDP )
1510         continue;
1511
1512       TypeCode* aTC = aIDP->edGetType();
1513       if ( !aTC )
1514         continue;
1515
1516 #ifdef _DEVDEBUG_
1517         if(!aValues[aRowId].isNull())
1518           std::cerr << aValues[aRowId] << std::endl;
1519         else
1520           std::cerr << "Qnull" << std::endl;
1521 #endif
1522
1523       if( aValues[aRowId] == "< ? >")
1524         continue;
1525
1526       // initialize new created input data port
1527       double d;
1528       bool ok;
1529       switch ( aTC->kind() )
1530       {
1531       case Double:
1532         d=aValues[aRowId].toDouble(&ok);
1533         if(ok)
1534           aIDP->edInit(d);
1535         break;
1536       case Int:
1537         aIDP->edInit( aValues[aRowId].toInt() );
1538         break;
1539       case String:
1540         aIDP->edInit( aValues[aRowId].latin1() );
1541         break;
1542       case Bool:
1543         aIDP->edInit( aValues[aRowId].compare( aTable->Params(aRowId,3)[0] ) ? false : true );
1544         break;
1545       case Objref:
1546         //aIDP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it
1547         break;
1548       case Sequence:
1549         //aIDP->edInit( "" ); // TODO : create an Any* (i.e. SequenceAny*) with corresponding type and initialize with it
1550         break;
1551       case Array:
1552         //aIDP->edInit( "" ); // TODO : create an Any* (i.e. ArrayAny*) with corresponding type and initialize with it
1553         break;
1554       case Struct:
1555         //aIDP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it
1556         break;
1557       default:
1558         break;
1559       }
1560
1561       mySNode->update( EDIT, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDP]);
1562     }
1563     //else if ( aTable->intValueCombo( 1, aRowId ) == 1 )    // Data Stream (BASIC) port
1564     //  // TODO : set value for input data stream port
1565     //else if ( aTable->intValueCombo( 1, aRowId ) == 2 )    // Data Stream (CALCIUM) port
1566     //  // TODO : set value for input data stream port
1567     //else if ( aTable->intValueCombo( 1, aRowId ) == 3 )    // Data Stream (PALM) port
1568     //  // TODO : set value for input data stream port
1569     
1570   }
1571 }
1572
1573 void YACSGui_ServiceNodePage::setOutputPorts()
1574 {
1575   DEBTRACE("YACSGui_ServiceNodePage::setOutputPorts");
1576   if ( !myOutputPortsGroupBox ) return;
1577
1578   ServiceNode* aNode = dynamic_cast<ServiceNode*>( getNode() );
1579   if ( !aNode ) return;
1580
1581   myOutputPortsGroupBox->Table()->stopEdit(true);
1582
1583   if ( myType != SALOMEService )
1584   {
1585     // remove old ports
1586     list<OutPort*> anOutPortsEngine = aNode->getSetOfOutPort();
1587     list<OutPort*>::iterator anOutPortsIter = anOutPortsEngine.begin();
1588     for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++)
1589     {
1590       mySNode->update( REMOVE,
1591                        ( dynamic_cast<OutputPort*>(*anOutPortsIter) ? OUTPUTPORT : OUTPUTDATASTREAMPORT ),
1592                        GuiContext::getCurrent()->_mapOfSubjectDataPort[*anOutPortsIter] );
1593       
1594       //aNode->edRemovePort(*anOutPortsIter);
1595       // remove port subject (and all subject links connected to this port)
1596       mySNode->destroy( GuiContext::getCurrent()->_mapOfSubjectDataPort[*anOutPortsIter] );
1597     }
1598     
1599     // create a set of new input ports
1600     YACS::ENGINE::Catalog* aCatalog = getInputPanel()->getModule()->getCatalog();
1601     if ( aCatalog && aNode->getComponent()
1602          &&
1603          aCatalog->_componentMap.count(aNode->getComponent()->getCompoName()) )
1604     {
1605       ComponentDefinition* aCompodef = aCatalog->_componentMap[aNode->getComponent()->getCompoName()];
1606       if ( aCompodef && aCompodef->_serviceMap.count(aNode->getMethod()) )
1607         if ( ServiceNode* aNodeToClone = aCompodef->_serviceMap[aNode->getMethod()] )
1608         {
1609           list<OutPort*> anOutPortsClone = aNodeToClone->getSetOfOutPort();
1610           list<OutPort*>::iterator anOutPortsIter = anOutPortsClone.begin();
1611           for( ;anOutPortsIter!=anOutPortsClone.end();anOutPortsIter++)
1612             if ( OutputPort* anOP = dynamic_cast<OutputPort*>(*anOutPortsIter) ) // Data Flow port
1613               dynamic_cast<SubjectElementaryNode*>(mySNode)->addOutputPort( aCatalog,
1614                                                                             portValueType(anOP->edGetType()),
1615                                                                             anOP->getName() );
1616             else if ( OutputDataStreamPort* anODSP = dynamic_cast<OutputDataStreamPort*>(*anOutPortsIter) ) // Data Stream port
1617               dynamic_cast<SubjectElementaryNode*>(mySNode)->addODSPort( aCatalog,
1618                                                                          portValueType(anODSP->edGetType()),
1619                                                                          anODSP->getName() );
1620         }
1621     }
1622   }
1623
1624   // read output data and output data stream ports from the table
1625   YACSGui_Table* aTable = myOutputPortsGroupBox->Table();
1626   
1627   QStringList aPortNames;
1628   aTable->strings( 0, aPortNames );
1629
1630   int aRowId = 0;
1631   for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it )
1632   {
1633     if ( (*it).isEmpty() ) continue;
1634
1635     // TODO : Remember "Is in study" flag for output port
1636     // ...
1637
1638     aRowId++;
1639   }
1640 }
1641
1642 YACS::ENGINE::TypeCode* YACSGui_ServiceNodePage::createTypeCode( YACS::ENGINE::DynType theType,
1643                                                                  YACSGui_Table* theTable,
1644                                                                  int theRowId )
1645 {
1646   TypeCode* aTC = 0;
1647
1648   switch (theType)
1649   {
1650   case Double:
1651   case Int:
1652   case String:
1653   case Bool:
1654     aTC = new TypeCode(theType);
1655     break;
1656   case Objref:
1657     {
1658       if ( theTable->intValueCombo( 1, theRowId ) == 2 ) // Data Stream (CALCIUM) port
1659         aTC = new TypeCodeObjref("CALCIUM","CALCIUM");
1660       else if ( theTable->intValueCombo( 1, theRowId ) == 1 ) // Data Stream (BASIC) port
1661         aTC = new TypeCodeObjref("BASIC","BASIC");
1662       else if ( theTable->intValueCombo( 1, theRowId ) == 3 ) // Data Stream (PALM) port
1663         aTC = new TypeCodeObjref("PALM","PALM");
1664       else
1665         aTC = new TypeCodeObjref("","");
1666     }
1667     break;
1668   case Sequence:
1669     aTC = new TypeCodeSeq("","",(new TypeCode(Double)));
1670     break;
1671   case Array:
1672     aTC = new TypeCodeArray("","",(new TypeCode(Double)),0);
1673     break;
1674   case Struct:
1675     aTC = new TypeCodeStruct("","");
1676     break;
1677   default:
1678     break;
1679   }
1680
1681   return aTC;
1682 }
1683
1684 QString YACSGui_ServiceNodePage::scriptText() const
1685 {
1686 #ifdef HAVE_QEXTSCINTILLA_H
1687   return _myTextEdit->text();
1688 #else
1689   return myTextEdit->text();
1690 #endif
1691 }
1692
1693 void YACSGui_ServiceNodePage::setScriptText( const QString& txt )
1694 {
1695 #ifdef HAVE_QEXTSCINTILLA_H
1696   _myTextEdit->setText( txt );
1697 #else
1698   myTextEdit->setText( txt );
1699 #endif
1700 }