Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_ManagePortsDlg.cxx
1 //  SUPERV SUPERVGUI : GUI for Supervisor component
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SUPERVGUI_ManagePortsDlg.cxx
23 //  Author : Alexander SLADKOV
24 //  Module : SUPERV
25
26 #include "SUIT_Desktop.h"
27 #include "SUIT_Session.h"
28
29 #include "SUPERVGUI_ManagePortsDlg.h"
30 #include "SUPERVGUI_CanvasNode.h"
31 #include "SUPERVGUI_CanvasNodePrs.h"
32 #include "SUPERVGUI_CanvasPort.h"
33 #include "SUPERVGUI_CanvasControlNode.h"
34 #include "SUPERVGUI_CanvasLink.h"
35
36 #include <qlayout.h>
37 #include <qlabel.h>
38 #include <qpushbutton.h>
39 #include <qhbox.h>
40 #include <qgroupbox.h>
41
42 static const char* gTypes[] = 
43   {"string", "boolean", "char", "short", "int", "long", "float", "double", "objref"};
44
45 static const char* const add_pix_data[] = { 
46 "20 20 4 1",
47 ". c None",
48 "b c #084818",
49 "a c #186929",
50 "# c #208541",
51 "....................",
52 "....................",
53 "....................",
54 "....................",
55 "........##a.........",
56 "........##b.........",
57 "........##b.........",
58 "........##b.........",
59 "........##b.........",
60 "...############a....",
61 "...############b....",
62 "...abbbb##bbbbbb....",
63 "........##b.........",
64 "........##b.........",
65 "........##b.........",
66 "........##b.........",
67 "........abb.........",
68 "....................",
69 "....................",
70 "...................."};
71
72 static const char* const del_pix_data[] = { 
73 "16 16 3 1",
74 ". c None",
75 "# c #800000",
76 "a c #ffffff",
77 "................",
78 "................",
79 ".##a........##a.",
80 ".####a.....##a..",
81 "..####a...##a...",
82 "....###a.#a.....",
83 ".....#####a.....",
84 "......###a......",
85 ".....#####a.....",
86 "....###a.##a....",
87 "...###a...##a...",
88 "..###a.....#a...",
89 "..###a......#a..",
90 "...#a........#a.",
91 "................",
92 "................"};
93
94 static const char* const up_pix_data[] = { 
95 "16 16 5 1",
96 ". c None",
97 "# c #000000",
98 "a c #838183",
99 "c c #c5c2c5",
100 "b c #ffffff",
101 "................",
102 "................",
103 "........#.......",
104 "......a#b#......",
105 ".....a#bbb#.....",
106 "....a#bccbb#....",
107 "...a#bccccbb#...",
108 "..a####ccb####..",
109 ".aaaaa#ccb#.....",
110 ".....a#ccb#.....",
111 ".....a#ccb#.....",
112 ".....a#ccb#.....",
113 ".....a#ccb#.....",
114 ".....a#ccb#.....",
115 ".....a#####.....",
116 "................"};
117
118 static const char* const down_pix_data[] = { 
119 "16 16 5 1",
120 ". c None",
121 "# c #000000",
122 "a c #838183",
123 "c c #c5c2c5",
124 "b c #ffffff",
125 "................",
126 ".....#####a.....",
127 ".....#bcc#a.....",
128 ".....#bcc#a.....",
129 ".....#bcc#a.....",
130 ".....#bcc#a.....",
131 ".....#bcc#a.....",
132 ".....#bcc#aaaaa.",
133 "..####bcc####a..",
134 "...#bbccccb#a...",
135 "....#bbccb#a....",
136 ".....#bbb#a.....",
137 "......#b#a......",
138 ".......#........",
139 "................",
140 "................"};
141
142
143 /**
144  * Constructor
145  */
146 SUPERVGUI_ManagePortsDlg::SUPERVGUI_ManagePortsDlg( SUPERVGUI_CanvasNode* theNode )
147   : QDialog( SUIT_Session::session()->activeApplication()->desktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu )
148 {
149   myNode = theNode;
150   myLastItem = 0;
151   init();
152 }
153
154 void SUPERVGUI_ManagePortsDlg::init()
155 {
156   setName( "SUPERVGUI_ManagePortsDlg" );
157
158   SUPERV_CNode aCNode = myNode->getEngine();
159   setCaption( tr( "TIT_MANAGE_PORTS" ) + aCNode->Name() );
160
161   QGridLayout* aBaseLayout = new QGridLayout( this );
162   aBaseLayout->setMargin( 11 ); 
163   aBaseLayout->setSpacing( 6 );
164
165   // -- name and type upper line widgets --
166   QLabel* aNameLbl = new QLabel( tr( "NAME_LBL") , this );
167   myNameEdt = new QLineEdit( this );
168   QLabel* aTypeLbl = new QLabel( tr( "TYPE_LBL" ), this );
169   myTypeCombo = new QComboBox( false, this ); // input field not editable
170
171   aBaseLayout->addWidget( aNameLbl, 0, 0 );
172   aBaseLayout->addWidget( myNameEdt, 0, 1 );
173   aBaseLayout->addWidget( aTypeLbl, 0, 2 );  
174   aBaseLayout->addWidget( myTypeCombo, 0, 3 );
175   aBaseLayout->setColStretch( 1, 1 );
176   aBaseLayout->setColStretch( 3, 1 );
177
178   // -- common Input/Output variables --
179   QPixmap adPix( (const char**) add_pix_data );
180   QPixmap rmPix( (const char**) del_pix_data );
181   QPixmap upPix( (const char**) up_pix_data );
182   QPixmap dnPix( (const char**) down_pix_data );
183
184   // -- Input ports group box --
185   QGroupBox* anInputGr = new QGroupBox( 1, Qt::Vertical, tr( "INPUT" ), this );
186   anInputGr->layout()->setSpacing( 6 ); 
187   anInputGr->layout()->setMargin( 11 );
188
189   myInList = new QListBox( anInputGr );
190   myInList->setSelectionMode( QListBox::Single );
191
192   QGroupBox* anInputBtnGr = new QGroupBox( 0, Qt::Vertical, anInputGr );
193   anInputBtnGr->setFrameStyle( QFrame::NoFrame );
194   anInputBtnGr->layout()->setSpacing( 0 ); 
195   anInputBtnGr->layout()->setMargin( 0 );  
196
197   QVBoxLayout* anInputBtnLay = new QVBoxLayout( anInputBtnGr->layout() );
198   anInputBtnLay->layout()->setSpacing( 6 ); 
199   anInputBtnLay->layout()->setMargin( 0 );
200   
201   QPushButton* anAddInputBtn = new QPushButton( anInputBtnGr );
202   anAddInputBtn->setPixmap( adPix );
203   QPushButton* aDeleteInputBtn = new QPushButton( anInputBtnGr );
204   aDeleteInputBtn->setPixmap( rmPix );
205   QPushButton* anUpInputBtn = new QPushButton( anInputBtnGr );
206   anUpInputBtn->setPixmap( upPix );
207   QPushButton* aDownInputBtn = new QPushButton( anInputBtnGr );
208   aDownInputBtn->setPixmap( dnPix );
209
210   connect( anAddInputBtn, SIGNAL( clicked() ), this, SLOT( addInput() ) );
211   connect( aDeleteInputBtn, SIGNAL( clicked() ), this, SLOT( removeInput() ) );
212   connect( anUpInputBtn, SIGNAL( clicked() ), this, SLOT( upInput() ) );
213   connect( aDownInputBtn, SIGNAL( clicked() ), this, SLOT( downInput() ) );
214
215   anInputBtnLay->addWidget( anAddInputBtn );
216   anInputBtnLay->addWidget( aDeleteInputBtn );
217   anInputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
218   anInputBtnLay->addWidget( anUpInputBtn );
219   anInputBtnLay->addWidget( aDownInputBtn );
220   anInputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
221
222   aBaseLayout->addMultiCellWidget( anInputGr, 1, 1, 0, 1 );
223
224   // -- Output ports group box --
225   QGroupBox* anOutputGr = new QGroupBox( 1, Qt::Vertical, tr( "OUTPUT" ), this );
226   anOutputGr->layout()->setSpacing( 6 ); 
227   anOutputGr->layout()->setMargin( 11 );
228
229   myOutList = new QListBox( anOutputGr );
230   myOutList->setSelectionMode( QListBox::Single );
231
232   QGroupBox* anOutputBtnGr = new QGroupBox( 0, Qt::Vertical, anOutputGr );
233   anOutputBtnGr->setFrameStyle( QFrame::NoFrame );
234   anOutputBtnGr->layout()->setSpacing( 0 ); 
235   anOutputBtnGr->layout()->setMargin( 0 );  
236
237   QVBoxLayout* anOutputBtnLay = new QVBoxLayout( anOutputBtnGr->layout() );
238   anOutputBtnLay->layout()->setSpacing( 6 ); 
239   anOutputBtnLay->layout()->setMargin( 0 );
240   
241   QPushButton* anAddOutputBtn = new QPushButton( anOutputBtnGr );
242   anAddOutputBtn->setPixmap( adPix );
243   QPushButton* aDeleteOutputBtn = new QPushButton( anOutputBtnGr );
244   aDeleteOutputBtn->setPixmap( rmPix );
245   QPushButton* anUpOutputBtn = new QPushButton( anOutputBtnGr );
246   anUpOutputBtn->setPixmap( upPix );
247   QPushButton* aDownOutputBtn = new QPushButton( anOutputBtnGr );
248   aDownOutputBtn->setPixmap( dnPix );
249
250   connect( anAddOutputBtn, SIGNAL( clicked() ), this, SLOT( addOutput() ) );
251   connect( aDeleteOutputBtn, SIGNAL( clicked() ), this, SLOT( removeOutput() ) );
252   connect( anUpOutputBtn, SIGNAL( clicked() ), this, SLOT( upOutput() ) );
253   connect( aDownOutputBtn, SIGNAL( clicked() ), this, SLOT( downOutput() ) );
254
255   anOutputBtnLay->addWidget( anAddOutputBtn );
256   anOutputBtnLay->addWidget( aDeleteOutputBtn );
257   anOutputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
258   anOutputBtnLay->addWidget( anUpOutputBtn );
259   anOutputBtnLay->addWidget( aDownOutputBtn );
260   anOutputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
261
262   aBaseLayout->addMultiCellWidget( anOutputGr, 1, 1, 2, 3 );
263
264   // -- Ok / Cancel buttons line at the bottom of dialog -- 
265   QGroupBox* aBtnBox = new QGroupBox( this );
266   aBtnBox->setColumnLayout( 0, Qt::Vertical );
267   aBtnBox->layout()->setSpacing( 0 ); 
268   aBtnBox->layout()->setMargin( 0 );
269   
270   QHBoxLayout* aBtnLayout = new QHBoxLayout( aBtnBox->layout() );
271   aBtnLayout->setAlignment( Qt::AlignTop );
272   aBtnLayout->setSpacing( 6 ); 
273   aBtnLayout->setMargin( 11 );
274
275   QPushButton* aOkBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
276   QPushButton* aCancelBtn = new QPushButton( tr( "BUT_CANCEL" ), aBtnBox );
277   connect( aOkBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
278   connect( aCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
279
280   aBtnLayout->addWidget( aOkBtn );
281   aBtnLayout->addStretch();
282   aBtnLayout->addWidget( aCancelBtn );
283   
284   aBaseLayout->addMultiCellWidget( aBtnBox, 2, 2, 0, 3 );
285   // -----------
286
287   connect( myInList,SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
288   connect( myOutList, SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
289   connect( myNameEdt, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
290   connect( myTypeCombo, SIGNAL(activated(const QString&)), this, SLOT(typeChanged(const QString&)));
291
292   // mkr: PAL12448
293   connect( myInList,  SIGNAL(rightButtonClicked(QListBoxItem*, const QPoint&)),
294            this, SLOT(itemDeselect(QListBoxItem*, const QPoint&)));
295   connect( myOutList, SIGNAL(rightButtonClicked(QListBoxItem*, const QPoint&)),
296            this, SLOT(itemDeselect(QListBoxItem*, const QPoint&)));
297
298   myNode->getMain()->lockedGraph( true );
299
300   // asv : 11.01.05 : if a node is a loop node, then only INPUT ports can be added/removed
301   if ( myNode->getNodeType() == SUPERV::LoopNode ) {
302     myOutList->setEnabled( false );
303     anAddOutputBtn->setEnabled( false );
304     aDeleteOutputBtn->setEnabled( false );
305     anUpOutputBtn->setEnabled( false );
306     aDownOutputBtn->setEnabled( false );
307   }
308
309   // NPAL15537: initialization moved here from showEvent()
310   init( myNode );
311 }
312
313 /**
314  * Destructor
315  */
316 SUPERVGUI_ManagePortsDlg::~SUPERVGUI_ManagePortsDlg() {
317 }
318
319 // mkr : PAL8060
320 void SUPERVGUI_ManagePortsDlg::createLinkEngine (SUPERV::Port_ptr thePort, 
321                                                  QValueList< QPair< QString,QString > >& theOwnList, 
322                                                  QValueList< QPair< QString,QString > >& theCorrespList) {
323   // pair <NodeName, PortName> for the given port
324   QPair<QString, QString> anOwnPair(QString(thePort->Node()->Name()), QString(thePort->Name()));
325   int aNum = theOwnList.contains(anOwnPair);
326   while ( aNum > 0 ) {
327     int anId = theOwnList.findIndex(anOwnPair); // get index in theOwnList
328     QPair<QString, QString> aCorrespPair = theCorrespList[anId]; // corresponding pair in theCorrespList
329     
330     theOwnList.remove(theOwnList.at(anId));
331     theCorrespList.remove(theCorrespList.at(anId));
332     
333     SUPERV_Port aCorrespPort =
334       myNode->getMain()->getDataflow()->Node(aCorrespPair.first)->Port(aCorrespPair.second);
335     SUPERV_Link aLinkEngine;
336     if ( thePort->IsInput() )
337       aLinkEngine = myNode->getMain()->getDataflow()->Link(aCorrespPort, thePort);
338     else
339       aLinkEngine = myNode->getMain()->getDataflow()->Link(thePort, aCorrespPort);
340     SUPERVGUI_CanvasLink* aLink = new SUPERVGUI_CanvasLink(myNode->getMain()->getCanvas(),
341                                                            myNode->getMain(), aLinkEngine);
342     aLink->show();
343
344     aNum--;
345   }
346 }
347
348 /** 
349  * Set the ports as entered by user (order, name/type, etc.) and close the dialog
350  */
351 void SUPERVGUI_ManagePortsDlg::accept()
352 {
353   myNode->getMain()->Editing(); // PAL6170: GUI->Engine: setting "Editing" flag 
354
355   // 1. set the ports to Engine's CNode
356   SUPERV_INode aINode = myNode->getInlineNode();
357   if ( !SUPERV_isNull( aINode ) ) {
358     int i; 
359     const bool isLoop = ( myNode->getNodeType() == SUPERV::LoopNode );
360
361     // 1.1 form a list of ports to be removed
362     QObjectList* oldPorts = myNode->queryList("SUPERVGUI_CanvasPort");
363
364     // asv : 11.01.05 : fix for a bug: for Loop node, removal of an Input Port
365     // automatically removes the corresponding Output Port. So for Loops the
366     // oldPorts list should be filtered to include only Input Ports.
367     // But I'll filter Gate-s as well..
368     QObjectList portsToRemove;
369     QObject *obj;
370     QObjectListIt it ( *oldPorts ); // iterate over the old ports
371     for (; (obj = it.current()) != 0; ++it) {
372       SUPERV::Port_var aPort = ((SUPERVGUI_CanvasPort*)obj)->getEngine();
373       if ( !aPort->IsGate() ) {
374         if ( !isLoop || aPort->IsInput() ) {
375           portsToRemove.append( obj );
376         }
377       }
378     }
379     delete oldPorts; // delete the list, not the objects
380
381     // 1.2 create new ports in INode and CanvasPort in myNode
382     //     or just reorder existing ports
383     PortListItem* item;
384     for (i = 0; i < myInList->count(); i++) {
385       item = (PortListItem*)myInList->item( i );
386       // try existing ports
387       bool isExisting = false;
388       QObjectListIt itRem (portsToRemove);
389       QObject *objRem;
390       for (; (objRem = itRem.current()) != 0 && !isExisting; ++itRem) {
391         SUPERV::Port_var aPort = ((SUPERVGUI_CanvasPort*)objRem)->getEngine();
392         if (item->PortName.compare(aPort->Name()) == 0 &&
393             item->PortType.compare(aPort->Type()) == 0) {
394           // ports reordering
395           myNode->removeChild(objRem);
396           myNode->insertChild(objRem);
397           portsToRemove.remove(objRem);
398           isExisting = true;
399         }
400       }
401       if (!isExisting) {
402         // create a new port
403         SUPERV::Port_var aPort = aINode->InPort( item->PortName.latin1(), item->PortType.latin1() );
404         myNode->createPort( aPort.in() );
405       }
406     }
407
408     // 1.3 create/reorder Out-ports
409     if (isLoop) {
410       // asv : 11.01.05 : for Loop nodes do the same as in SUPERVGUI_CanvasStartNode::addInputPort()
411       SUPERVGUI_CanvasStartNode* aStartLoopNode = (SUPERVGUI_CanvasStartNode*)myNode;
412       aStartLoopNode->merge();
413       aStartLoopNode->getCoupled()->merge();
414     }
415     else {
416       // for non-loop nodes manage out-ports in the same way as in-ports
417       for (i = 0; i < myOutList->count(); i++) {
418         item = (PortListItem*)myOutList->item( i );
419         // try existing ports
420         bool isExisting = false;
421         QObjectListIt itRem (portsToRemove);
422         QObject *objRem;
423         for (; (objRem = itRem.current()) != 0 && !isExisting; ++itRem) {
424           SUPERV::Port_var aPort = ((SUPERVGUI_CanvasPort*)objRem)->getEngine();
425           if (item->PortName.compare(aPort->Name()) == 0 &&
426               item->PortType.compare(aPort->Type()) == 0) {
427             // ports reordering
428             myNode->removeChild(objRem);
429             myNode->insertChild(objRem);
430             portsToRemove.remove(objRem);
431             isExisting = true;
432           }
433         }
434         if (!isExisting) {
435           // create a new port
436           SUPERV::Port_var aPort = aINode->OutPort(item->PortName.latin1(), item->PortType.latin1());
437           myNode->createPort(aPort.in());
438         }
439       }
440     }
441
442     // 1.4 remove disappeared ports
443     QObjectListIt itRem ( portsToRemove );
444     QObject *objRem;
445     for (; (objRem = itRem.current()) != 0; ++itRem) {
446       ((SUPERVGUI_CanvasPort*)objRem)->remove();
447     }
448
449     // 2. update the node's presentation
450     myNode->getPrs()->updatePorts();
451     myNode->getMain()->getCanvas()->update();
452   }
453
454   // 3. close the dialog
455   myNode->getMain()->lockedGraph( false );
456   QDialog::accept();
457 }
458
459 /** 
460  * Simply close the dialog
461  */
462 void SUPERVGUI_ManagePortsDlg::reject() {
463   myNode->getMain()->lockedGraph( false );
464   QDialog::reject();
465   close();
466 }
467
468 /**
469  * Initialize In/Out tables with values from the given node
470  */
471 void SUPERVGUI_ManagePortsDlg::init( const SUPERVGUI_CanvasNode* theNode ) {
472   if ( !theNode ) {
473     MESSAGE("ERROR: SUPERVGUI_ManagePortsDlg: the CanvasNode is nil!");
474     return;
475   }
476
477   SUPERV_INode aINode = myNode->getInlineNode();
478   if ( SUPERV_isNull( aINode ) ) {
479     MESSAGE("ERROR: SUPERVGUI_ManagePortsDlg: the node of wrong type is found (not InLine node)!");
480     return;
481   }
482   
483   // 1. fill myTypeCombo with all available types
484   myTypeCombo->insertStrList( gTypes );
485   
486   // 2. fill Input and Output listboxes with Ports' names/types
487   QStringList aTypes;
488   SUPERV_Ports aPorts = aINode->Ports();
489   for ( int i=0; i < aPorts->length(); i++ ) {
490     if ( aPorts[i]->IsGate() )
491       continue;
492     if ( aPorts[i]->IsInput()
493          &&
494          !myInList->findItem( QString( "%1 (%2)" ).arg( aPorts[i]->Name() ).arg( aPorts[i]->Type() ) ) ) // mkr : PAL11332
495       new PortListItem( myInList, aPorts[i]->Name(), aPorts[i]->Type() );
496     if ( !aPorts[i]->IsInput()
497          &&
498          !myOutList->findItem( QString( "%1 (%2)" ).arg( aPorts[i]->Name() ).arg( aPorts[i]->Type() ) ) ) // mkr : PAL11332 
499       new PortListItem( myOutList, aPorts[i]->Name(), aPorts[i]->Type() );
500   }
501 }
502
503 void SUPERVGUI_ManagePortsDlg::addPort( QListBox* theLB ) {
504   if ( !theLB )
505     return;
506   QString name = myNameEdt->text();
507   if ( !name.isNull() && name.length() ) {
508     bool found = false; // check if already exists -- and don't allow if yes
509     for ( int i = 0; i < theLB->count(); i++ ) {
510       if ( ((PortListItem*)theLB->item(i))->PortName == name ) {
511         found = true;
512         break;
513       }
514     }
515     if ( found )
516       QMessageBox::warning( this, tr("ERROR"), tr("MSG_PORT_EXIST") ); // mkr : IPAL10386
517     else
518       new PortListItem( theLB, name, myTypeCombo->currentText() );
519   }
520 }
521
522 /**
523  * called on 'X' button press - remove selected port item
524  */
525 void SUPERVGUI_ManagePortsDlg::removePort( QListBox* theLB ) {
526   if ( !theLB )
527     return;
528
529   const int i = theLB->currentItem();
530   if ( i >=0 )
531     delete theLB->item( i );    
532 }
533
534 /**
535  * called on up/down key press - move the selected list box item from position 'from' to position 'to'
536  */
537 void SUPERVGUI_ManagePortsDlg::moveItem( QListBox* theLB, const int from, const int to ) {
538   if ( !theLB )
539     return;
540
541   // disconnect itemChanged - it leads to crash if there was only 1 item left
542   disconnect( theLB, SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
543
544   if ( from >= 0 && from < theLB->count() && to >=0 && to < theLB->count() ) {
545     QListBoxItem* item = theLB->item( from );
546     theLB->takeItem( item );
547     theLB->insertItem( item, to );
548     theLB->setCurrentItem( item );
549     theLB->setSelected( item, true );
550   }
551
552   // connect back..
553   connect( theLB, SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
554 }
555
556 /**
557  * move the selected item UP
558  */
559 void SUPERVGUI_ManagePortsDlg::moveUp( QListBox* theLB ) {
560   if ( !theLB )
561     return;
562   const int i = theLB->currentItem();
563   moveItem( theLB, i, i-1 );
564 }
565
566 /**
567  * move the selected item DOWN
568  */
569 void SUPERVGUI_ManagePortsDlg::moveDown( QListBox* theLB ) {
570   if ( !theLB )
571     return;
572   const int i = theLB->currentItem();
573   moveItem( theLB, i, i+1 );
574 }
575
576
577 /**
578  * returns true if there is a current and selected item in the given listbox and it
579  * equals to the given item.
580  */
581 bool isEditingItem( const QListBoxItem* item, const QListBox* theLB ) {
582   return item && item == theLB->item( theLB->currentItem() ) && theLB->isSelected( item );
583 }
584
585 /**
586  * called when name is changed.  Tries to change name of the item, which was
587  * the last selected by user item in myInList or myOutList (myLastItem)
588  */
589 void SUPERVGUI_ManagePortsDlg::nameChanged( const QString& name ) {
590   // mkr: IPAL12512
591   if ( isEditingItem( myLastItem, myInList ) && myInList->findItem( QString( "%1 (%2)" ).arg( name ).arg( ((PortListItem*)myLastItem)->PortType ))
592        ||
593        isEditingItem( myLastItem, myOutList ) && myOutList->findItem( QString( "%1 (%2)" ).arg( name ).arg( ((PortListItem*)myLastItem)->PortType ))) {
594     disconnect( myNameEdt, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
595     
596     myNameEdt->setText( ((PortListItem*)myLastItem)->PortName );
597     
598     connect( myNameEdt, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
599     QMessageBox::warning( this, tr("ERROR"), tr("MSG_PORT_EXIST") );
600     return;
601   }
602   
603   if ( isEditingItem( myLastItem, myInList ) || isEditingItem( myLastItem, myOutList ) ) {
604     ((PortListItem*)myLastItem)->PortName = name;
605     //myLastItem->listBox()->repaint( true );
606     // it would be much better to change the item and repaint it -- but -- repaint() 
607     // is done only after a while, which is not good..  so -- "cheating" around
608     const int i = myLastItem->listBox()->index( myLastItem );
609     moveItem( myLastItem->listBox(), i, i );
610   }
611 }
612
613 /**
614  * called when type item in myTypeCombo is changed.  Tries to change type
615  * of the last selected by user item in myInList or myOutList (myLastItem)
616  */
617 void SUPERVGUI_ManagePortsDlg::typeChanged( const QString& type ) {
618   if ( isEditingItem( myLastItem, myInList ) || isEditingItem( myLastItem, myOutList ) ) {
619     ((PortListItem*)myLastItem)->PortType = type;
620     //myLastItem->listBox()->repaint( true );
621     // it would be much better to change the item and repaint it -- but -- repaint() 
622     // is done only after a while, which is not good..  so -- "cheating" around
623     const int i = myLastItem->listBox()->index( myLastItem );
624     moveItem( myLastItem->listBox(), i, i );
625   }
626 }
627
628 /**
629  * called when new item became "currentItem" in any myInList or myOutList listboxes.
630  */
631 void SUPERVGUI_ManagePortsDlg::itemChanged( QListBoxItem * item ) {
632   if ( !item ) // after remove, etc..
633     return;
634
635   // disable nameChanged, typeChanged callbacks
636   disconnect( myNameEdt, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
637   disconnect( myTypeCombo, SIGNAL(activated(const QString&)), this, SLOT(typeChanged(const QString&)));
638   
639   myLastItem = item;
640   myNameEdt->setText( ((PortListItem*)item)->PortName );
641   for ( int i = 0; i < myTypeCombo->count(); i++ )
642     if ( myTypeCombo->text( i ) == ((PortListItem*)item)->PortType ) {
643       myTypeCombo->setCurrentItem( i );
644       break;
645     }
646
647   // connect back nameChanged, typeChanged
648   connect( myNameEdt, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
649   connect( myTypeCombo, SIGNAL(activated(const QString&)), this, SLOT(typeChanged(const QString&)));
650 }
651
652 /*!
653  * Deselect the current selected item
654  */
655 void SUPERVGUI_ManagePortsDlg::itemDeselect(QListBoxItem* item, const QPoint& point) {
656   // mkr: PAL12448
657   if ( item->isSelected() )
658     item->listBox()->setSelected(item, false);
659 }
660
661 /*!
662  * Port parameters dialog definition (taken from SUPERVGUI_Node.cxx without change)
663  */
664 SUPERVGUI_PortParamsDlg::SUPERVGUI_PortParamsDlg(const QStringList& thePortsNames)
665   : QDialog(SUIT_Session::session()->activeApplication()->desktop(), 0, true, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu  ),
666     myPortsNames( thePortsNames )
667 {
668   setSizeGripEnabled( true );
669   setCaption("Port parameters");
670
671   QGridLayout* aBaseLayout = new QGridLayout( this );
672   aBaseLayout->setMargin( 11 ); aBaseLayout->setSpacing( 6 );
673
674   QLabel* aNameLbl = new QLabel("Port Name", this );
675   aBaseLayout->addWidget(aNameLbl, 0, 0);
676
677   myNameTxt = new QLineEdit( this );
678   aNameLbl->setBuddy( myNameTxt );
679   aBaseLayout->addWidget(myNameTxt, 0, 1);
680   
681   QLabel* aTypeLbl = new QLabel("Value Type", this );
682   aBaseLayout->addWidget(aTypeLbl, 1, 0);
683  
684   myTypeTxt = new QComboBox( this );
685   aTypeLbl->setBuddy( myTypeTxt );
686   myTypeTxt->insertStrList( gTypes );
687   aBaseLayout->addWidget(myTypeTxt, 1, 1);
688  
689   QGroupBox* aBtnBox = new QGroupBox( this );
690   aBtnBox->setColumnLayout( 0, Qt::Vertical );
691   aBtnBox->layout()->setSpacing( 0 ); aBtnBox->layout()->setMargin( 0 );
692   QHBoxLayout* aBtnLayout = new QHBoxLayout( aBtnBox->layout() );
693   aBtnLayout->setAlignment( Qt::AlignTop );
694   aBtnLayout->setSpacing( 6 ); aBtnLayout->setMargin( 11 );
695
696   aBaseLayout->addMultiCellWidget( aBtnBox, 2, 2, 0, 1 );
697
698   QPushButton* aOKBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
699   connect( aOKBtn, SIGNAL( clicked() ), this, SLOT( clickOnOk() ) );
700   aBtnLayout->addWidget( aOKBtn );
701
702   aBtnLayout->addStretch();
703
704   QPushButton* aCancelBtn = new QPushButton( tr("BUT_CANCEL"), aBtnBox );
705   connect( aCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
706   aBtnLayout->addWidget( aCancelBtn );
707 }
708
709 void SUPERVGUI_PortParamsDlg::clickOnOk()
710 {
711   if (getName().isEmpty() || getType().isEmpty())
712     QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(),
713                          tr("ERROR"), tr("MSG_CANT_CREATE_PORT"));
714   else if (myPortsNames.contains(getName()))
715     QMessageBox::warning( this, tr("ERROR"), tr("MSG_PORT_EXIST") ); // mkr : IPAL10386
716   else {
717     accept();
718     close();
719   }
720 }