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