Salome HOME
A new dialog class for edition of Ports of an InLine nodes is introduced. This funct...
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_ManagePortsDlg.cxx
1 //  SUPERV SUPERVGUI : GUI for Supervisor component
2 //
3 //  Copyright (C) 2003  CEA/DEN, EDF R&D
4 //
5 //
6 //
7 //  File   : SUPERVGUI_ManagePortsDlg.cxx
8 //  Author : Alexander SLADKOV
9 //  Module : SUPERV
10
11 using namespace std;
12
13 #include "SUPERVGUI_ManagePortsDlg.h"
14 #include "SUPERVGUI_CanvasNode.h"
15 #include "SUPERVGUI_CanvasPort.h"
16 #include "SUPERVGUI.h"
17
18 #include <qlayout.h>
19 #include <qlabel.h>
20 #include <qlineedit.h>
21 #include <qpushbutton.h>
22 #include <qhbox.h>
23 #include <qgroupbox.h>
24
25 static const char* gTypes[] = 
26   {"string", "boolean", "char", "short", "int", "long", "float", "double", "objref"};
27
28 static const char* const add_pix_data[] = { 
29 "20 20 4 1",
30 ". c None",
31 "b c #084818",
32 "a c #186929",
33 "# c #208541",
34 "....................",
35 "....................",
36 "....................",
37 "....................",
38 "........##a.........",
39 "........##b.........",
40 "........##b.........",
41 "........##b.........",
42 "........##b.........",
43 "...############a....",
44 "...############b....",
45 "...abbbb##bbbbbb....",
46 "........##b.........",
47 "........##b.........",
48 "........##b.........",
49 "........##b.........",
50 "........abb.........",
51 "....................",
52 "....................",
53 "...................."};
54
55 static const char* const del_pix_data[] = { 
56 "16 16 3 1",
57 ". c None",
58 "# c #800000",
59 "a c #ffffff",
60 "................",
61 "................",
62 ".##a........##a.",
63 ".####a.....##a..",
64 "..####a...##a...",
65 "....###a.#a.....",
66 ".....#####a.....",
67 "......###a......",
68 ".....#####a.....",
69 "....###a.##a....",
70 "...###a...##a...",
71 "..###a.....#a...",
72 "..###a......#a..",
73 "...#a........#a.",
74 "................",
75 "................"};
76
77 static const char* const up_pix_data[] = { 
78 "16 16 5 1",
79 ". c None",
80 "# c #000000",
81 "a c #838183",
82 "c c #c5c2c5",
83 "b c #ffffff",
84 "................",
85 "................",
86 "........#.......",
87 "......a#b#......",
88 ".....a#bbb#.....",
89 "....a#bccbb#....",
90 "...a#bccccbb#...",
91 "..a####ccb####..",
92 ".aaaaa#ccb#.....",
93 ".....a#ccb#.....",
94 ".....a#ccb#.....",
95 ".....a#ccb#.....",
96 ".....a#ccb#.....",
97 ".....a#ccb#.....",
98 ".....a#####.....",
99 "................"};
100
101 static const char* const down_pix_data[] = { 
102 "16 16 5 1",
103 ". c None",
104 "# c #000000",
105 "a c #838183",
106 "c c #c5c2c5",
107 "b c #ffffff",
108 "................",
109 ".....#####a.....",
110 ".....#bcc#a.....",
111 ".....#bcc#a.....",
112 ".....#bcc#a.....",
113 ".....#bcc#a.....",
114 ".....#bcc#a.....",
115 ".....#bcc#aaaaa.",
116 "..####bcc####a..",
117 "...#bbccccb#a...",
118 "....#bbccb#a....",
119 ".....#bbb#a.....",
120 "......#b#a......",
121 ".......#........",
122 "................",
123 "................"};
124
125
126 /**
127  * Constructor
128  */
129 SUPERVGUI_ManagePortsDlg::SUPERVGUI_ManagePortsDlg( SUPERVGUI_CanvasNode* theNode )
130   : QDialog( QAD_Application::getDesktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu | WDestructiveClose )
131 {
132   myNode = theNode;
133   myLastItem = 0;
134   myFromItemChanged = false;
135   init();
136 }
137
138 void SUPERVGUI_ManagePortsDlg::init()
139 {
140   setName( "SUPERVGUI_ManagePortsDlg" );
141
142   SUPERV_CNode aCNode = myNode->getEngine();
143   setCaption( tr( "TIT_MANAGE_PORTS" ) + aCNode->Name() );
144
145   QGridLayout* aBaseLayout = new QGridLayout( this );
146   aBaseLayout->setMargin( 11 ); 
147   aBaseLayout->setSpacing( 6 );
148
149   // -- name and type upper line widgets --
150   QLabel* aNameLbl = new QLabel( tr( "NAME_LBL") , this );
151   myNameEdt = new QLineEdit( this );
152   QLabel* aTypeLbl = new QLabel( tr( "TYPE_LBL" ), this );
153   myTypeCombo = new QComboBox( false, this ); // input field not editable
154
155   aBaseLayout->addWidget( aNameLbl, 0, 0 );
156   aBaseLayout->addWidget( myNameEdt, 0, 1 );
157   aBaseLayout->addWidget( aTypeLbl, 0, 2 );  
158   aBaseLayout->addWidget( myTypeCombo, 0, 3 );
159   aBaseLayout->setColStretch( 1, 1 );
160   aBaseLayout->setColStretch( 3, 1 );
161
162   // -- common Input/Output variables --
163   QPixmap adPix( (const char**) add_pix_data );
164   QPixmap rmPix( (const char**) del_pix_data );
165   QPixmap upPix( (const char**) up_pix_data );
166   QPixmap dnPix( (const char**) down_pix_data );
167
168   // -- Input ports group box --
169   QGroupBox* anInputGr = new QGroupBox( 1, Qt::Vertical, tr( "INPUT" ), this );
170   anInputGr->layout()->setSpacing( 6 ); 
171   anInputGr->layout()->setMargin( 11 );
172
173   myInList = new QListBox( anInputGr );
174   myInList->setSelectionMode( QListBox::Single );
175
176   QGroupBox* anInputBtnGr = new QGroupBox( 0, Qt::Vertical, anInputGr );
177   anInputBtnGr->setFrameStyle( QFrame::NoFrame );
178   anInputBtnGr->layout()->setSpacing( 0 ); 
179   anInputBtnGr->layout()->setMargin( 0 );  
180
181   QVBoxLayout* anInputBtnLay = new QVBoxLayout( anInputBtnGr->layout() );
182   anInputBtnLay->layout()->setSpacing( 6 ); 
183   anInputBtnLay->layout()->setMargin( 0 );
184   
185   QPushButton* anAddInputBtn = new QPushButton( anInputBtnGr );
186   anAddInputBtn->setPixmap( adPix );
187   QPushButton* aDeleteInputBtn = new QPushButton( anInputBtnGr );
188   aDeleteInputBtn->setPixmap( rmPix );
189   QPushButton* anUpInputBtn = new QPushButton( anInputBtnGr );
190   anUpInputBtn->setPixmap( upPix );
191   QPushButton* aDownInputBtn = new QPushButton( anInputBtnGr );
192   aDownInputBtn->setPixmap( dnPix );
193
194   connect( anAddInputBtn, SIGNAL( clicked() ), this, SLOT( addInput() ) );
195   connect( aDeleteInputBtn, SIGNAL( clicked() ), this, SLOT( removeInput() ) );
196   connect( anUpInputBtn, SIGNAL( clicked() ), this, SLOT( upInput() ) );
197   connect( aDownInputBtn, SIGNAL( clicked() ), this, SLOT( downInput() ) );
198
199   anInputBtnLay->addWidget( anAddInputBtn );
200   anInputBtnLay->addWidget( aDeleteInputBtn );
201   anInputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
202   anInputBtnLay->addWidget( anUpInputBtn );
203   anInputBtnLay->addWidget( aDownInputBtn );
204   anInputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
205
206   aBaseLayout->addMultiCellWidget( anInputGr, 1, 1, 0, 1 );
207
208   // -- Output ports group box --
209   QGroupBox* anOutputGr = new QGroupBox( 1, Qt::Vertical, tr( "OUTPUT" ), this );
210   anOutputGr->layout()->setSpacing( 6 ); 
211   anOutputGr->layout()->setMargin( 11 );
212
213   myOutList = new QListBox( anOutputGr );
214   myOutList->setSelectionMode( QListBox::Single );
215
216   QGroupBox* anOutputBtnGr = new QGroupBox( 0, Qt::Vertical, anOutputGr );
217   anOutputBtnGr->setFrameStyle( QFrame::NoFrame );
218   anOutputBtnGr->layout()->setSpacing( 0 ); 
219   anOutputBtnGr->layout()->setMargin( 0 );  
220
221   QVBoxLayout* anOutputBtnLay = new QVBoxLayout( anOutputBtnGr->layout() );
222   anOutputBtnLay->layout()->setSpacing( 6 ); 
223   anOutputBtnLay->layout()->setMargin( 0 );
224   
225   QPushButton* anAddOutputBtn = new QPushButton( anOutputBtnGr );
226   anAddOutputBtn->setPixmap( adPix );
227   QPushButton* aDeleteOutputBtn = new QPushButton( anOutputBtnGr );
228   aDeleteOutputBtn->setPixmap( rmPix );
229   QPushButton* anUpOutputBtn = new QPushButton( anOutputBtnGr );
230   anUpOutputBtn->setPixmap( upPix );
231   QPushButton* aDownOutputBtn = new QPushButton( anOutputBtnGr );
232   aDownOutputBtn->setPixmap( dnPix );
233
234   connect( anAddOutputBtn, SIGNAL( clicked() ), this, SLOT( addOutput() ) );
235   connect( aDeleteOutputBtn, SIGNAL( clicked() ), this, SLOT( removeOutput() ) );
236   connect( anUpOutputBtn, SIGNAL( clicked() ), this, SLOT( upOutput() ) );
237   connect( aDownOutputBtn, SIGNAL( clicked() ), this, SLOT( downOutput() ) );
238
239   anOutputBtnLay->addWidget( anAddOutputBtn );
240   anOutputBtnLay->addWidget( aDeleteOutputBtn );
241   anOutputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
242   anOutputBtnLay->addWidget( anUpOutputBtn );
243   anOutputBtnLay->addWidget( aDownOutputBtn );
244   anOutputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
245
246   aBaseLayout->addMultiCellWidget( anOutputGr, 1, 1, 2, 3 );
247
248   // -- Ok / Cancel buttons line at the bottom of dialog -- 
249   QGroupBox* aBtnBox = new QGroupBox( this );
250   aBtnBox->setColumnLayout( 0, Qt::Vertical );
251   aBtnBox->layout()->setSpacing( 0 ); 
252   aBtnBox->layout()->setMargin( 0 );
253   
254   QHBoxLayout* aBtnLayout = new QHBoxLayout( aBtnBox->layout() );
255   aBtnLayout->setAlignment( Qt::AlignTop );
256   aBtnLayout->setSpacing( 6 ); 
257   aBtnLayout->setMargin( 11 );
258
259   QPushButton* aOkBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
260   QPushButton* aCancelBtn = new QPushButton( tr( "BUT_CANCEL" ), aBtnBox );
261   connect( aOkBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
262   connect( aCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
263
264   aBtnLayout->addWidget( aOkBtn );
265   aBtnLayout->addStretch();
266   aBtnLayout->addWidget( aCancelBtn );
267   
268   aBaseLayout->addMultiCellWidget( aBtnBox, 2, 2, 0, 3 );
269   // -----------
270
271   connect( myInList,SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
272   connect( myOutList, SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
273   connect( myNameEdt, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
274   connect( myTypeCombo, SIGNAL(activated(const QString&)), this, SLOT(typeChanged(const QString&)));
275
276   myNode->getMain()->lockedGraph( true );
277 }
278
279 /**
280  * Destructor
281  */
282 SUPERVGUI_ManagePortsDlg::~SUPERVGUI_ManagePortsDlg() {
283 }
284
285 /** 
286  * Set the ports as entered by user (order, name/type, etc.) and close the dialog
287  */
288 void SUPERVGUI_ManagePortsDlg::accept() {
289   // 1. set the ports to Engine's CNode
290   SUPERV_INode aINode = myNode->getInlineNode();
291   if ( !SUPERV_isNull( aINode ) ) {
292     int i; 
293
294     // 1.1 delete all ports (delete CanvasPorts, they delete SUPERV_Ports) 
295     QObjectList* oldPorts = myNode->queryList("SUPERVGUI_CanvasPort");
296     QObjectListIt it( *oldPorts ); // iterate over the old ports
297     QObject *obj;
298
299     while ( (obj = it.current()) != 0 ) {
300       ++it;
301       if ( !((SUPERVGUI_CanvasPort*)obj)->getEngine()->IsGate() ) // never do anything with Gate ports
302         ((SUPERVGUI_CanvasPort*)obj)->remove();
303     }
304     delete oldPorts; // delete the list, not the objects
305
306     // 1.2 create new ports in INode and CanvasPort in myNode
307     PortListItem* item;
308     SUPERV_Port aPort;
309     for ( i = 0; i < myInList->count(); i++ ) {
310       item = (PortListItem*)myInList->item( i );
311       aPort = aINode->InPort( item->PortName.latin1(), item->PortType.latin1() );
312       myNode->createPort( aPort.in() );
313     }
314     for ( i = 0; i < myOutList->count(); i++ ) {
315       item = (PortListItem*)myOutList->item( i );
316       aPort = aINode->OutPort( item->PortName.latin1(), item->PortType.latin1() );
317       myNode->createPort( aPort.in() );
318     }  
319
320     // 2. update the node's presentation
321     myNode->getMain()->getCanvas()->update();
322   }
323   
324   // 3. close the dialog
325   myNode->getMain()->lockedGraph( false );
326   QDialog::accept();
327   close();
328 }
329
330 /** 
331  * Simply close the dialog
332  */
333 void SUPERVGUI_ManagePortsDlg::reject() {
334   myNode->getMain()->lockedGraph( false );
335   QDialog::reject();
336   close();
337 }
338
339 /**
340  * Update current values on show event
341  */
342 void SUPERVGUI_ManagePortsDlg::showEvent( QShowEvent* theEvent ) {
343   init( myNode );
344   QDialog::showEvent( theEvent );
345 }
346
347 /**
348  * Initialize In/Out tables with values from the given node
349  */
350 void SUPERVGUI_ManagePortsDlg::init( const SUPERVGUI_CanvasNode* theNode ) {
351   if ( !theNode ) {
352     MESSAGE("ERROR: SUPERVGUI_ManagePortsDlg: the CanvasNode is nil!");
353     return;
354   }
355
356   SUPERV_INode aINode = myNode->getInlineNode();
357   if ( SUPERV_isNull( aINode ) ) {
358     MESSAGE("ERROR: SUPERVGUI_ManagePortsDlg: the node of wrong type is found (not InLine node)!");
359     return;
360   }
361   
362   // 1. fill myTypeCombo with all available types
363   myTypeCombo->insertStrList( gTypes );
364
365   // 2. fill Input and Output listboxes with Ports' names/types
366   QStringList aTypes;
367   SUPERV_Ports aPorts = aINode->Ports();
368   for ( int i=0; i < aPorts->length(); i++ ) {
369     if ( aPorts[i]->IsGate() )
370       continue;
371     if ( aPorts[i]->IsInput() )
372       new PortListItem( myInList, aPorts[i]->Name(), aPorts[i]->Type() );
373     else 
374       new PortListItem( myOutList, aPorts[i]->Name(), aPorts[i]->Type() );
375   }
376 }
377
378 void SUPERVGUI_ManagePortsDlg::addPort( QListBox* theLB ) {
379   if ( !theLB )
380     return;
381   QString name = myNameEdt->text();
382   if ( !name.isNull() && name.length() ) {
383     bool found = false; // check if already exists -- and don't allow if yes
384     for ( int i = 0; i < theLB->count(); i++ ) {
385       if ( ((PortListItem*)theLB->item(i))->PortName == name ) {
386         found = true;
387         break;
388       }
389     }
390     if ( found )
391       QMessageBox::warning( QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_PORT_EXIST") );
392     else
393       new PortListItem( theLB, name, myTypeCombo->currentText() );
394   }
395 }
396
397 void SUPERVGUI_ManagePortsDlg::removePort( QListBox* theLB ) {
398   if ( !theLB )
399     return;
400
401   const int i = theLB->currentItem();
402   if ( i >=0 )
403     delete theLB->item( i );    
404 }
405
406 void moveItem( QListBox* theLB, const int from, const int to ) {
407   if ( !theLB )
408     return;
409   if ( from >= 0 && from < theLB->count() && to >=0 && to < theLB->count() ) {
410     QListBoxItem* item = theLB->item( from );
411     theLB->takeItem( item );
412     theLB->insertItem( item, to );
413     theLB->setCurrentItem( item );
414     theLB->setSelected( item, true );
415   }
416 }
417
418 void SUPERVGUI_ManagePortsDlg::moveUp( QListBox* theLB ) {
419   if ( !theLB )
420     return;
421   const int i = theLB->currentItem();
422   moveItem( theLB, i, i-1 );
423 }
424
425 void SUPERVGUI_ManagePortsDlg::moveDown( QListBox* theLB ) {
426   if ( !theLB )
427     return;
428   const int i = theLB->currentItem();
429   moveItem( theLB, i, i+1 );
430 }
431
432
433 /**
434  * returns true if there is a current and selected item in the given listbox and it
435  * equals to the given item.
436  */
437 bool isEditingItem( const QListBoxItem* item, const QListBox* theLB ) {
438   return item && item == theLB->item( theLB->currentItem() ) && theLB->isSelected( item );
439 }
440
441 /**
442  * called when name is changed.  Tries to change name of the item, which was
443  * the last selected by user item in myInList or myOutList (myLastItem)
444  */
445 void SUPERVGUI_ManagePortsDlg::nameChanged( const QString& name ) {
446   if ( myFromItemChanged ) return;
447   if ( isEditingItem( myLastItem, myInList ) || isEditingItem( myLastItem, myOutList ) ) {
448     ((PortListItem*)myLastItem)->PortName = name;
449     //myLastItem->listBox()->repaint( true );
450     // it would be much better to change the item and repaint it -- but -- repaint() 
451     // is done only after a while, which is not good..  so -- "cheating" around
452     const int i = myLastItem->listBox()->index( myLastItem );
453     moveItem( myLastItem->listBox(), i, i );
454   }
455 }
456
457 /**
458  * called when type item in myTypeCombo is changed.  Tries to change type
459  * of the last selected by user item in myInList or myOutList (myLastItem)
460  */
461 void SUPERVGUI_ManagePortsDlg::typeChanged( const QString& type ) {
462   if ( myFromItemChanged ) return;
463   if ( isEditingItem( myLastItem, myInList ) || isEditingItem( myLastItem, myOutList ) ) {
464     ((PortListItem*)myLastItem)->PortType = type;
465     //myLastItem->listBox()->repaint( true );
466     // it would be much better to change the item and repaint it -- but -- repaint() 
467     // is done only after a while, which is not good..  so -- "cheating" around
468     const int i = myLastItem->listBox()->index( myLastItem );
469     moveItem( myLastItem->listBox(), i, i );
470   }
471 }
472
473 /**
474  * called when new item became "currentItem" in any myInList or myOutList listboxes.
475  */
476 void SUPERVGUI_ManagePortsDlg::itemChanged( QListBoxItem * item ) {
477   myFromItemChanged = true; // to disable nameChanged, typeChanged callbacks
478   myLastItem = item;
479   myNameEdt->setText( ((PortListItem*)item)->PortName );
480   for ( int i = 0; i < myTypeCombo->count(); i++ )
481     if ( myTypeCombo->text( i ) == ((PortListItem*)item)->PortType ) {
482       myTypeCombo->setCurrentItem( i );
483       break;
484     }
485   myFromItemChanged = false; // to enable nameChanged, typeChanged callbacks
486 }