1 // SUPERV SUPERVGUI : GUI for Supervisor component
3 // Copyright (C) 2003 CEA/DEN, EDF R&D
7 // File : SUPERVGUI_ManagePortsDlg.cxx
8 // Author : Alexander SLADKOV
13 #include "SUPERVGUI_ManagePortsDlg.h"
14 #include "SUPERVGUI_CanvasNode.h"
15 #include "SUPERVGUI_CanvasPort.h"
16 #include "SUPERVGUI.h"
20 #include <qpushbutton.h>
22 #include <qgroupbox.h>
24 static const char* gTypes[] =
25 {"string", "boolean", "char", "short", "int", "long", "float", "double", "objref"};
27 static const char* const add_pix_data[] = {
33 "....................",
34 "....................",
35 "....................",
36 "....................",
37 "........##a.........",
38 "........##b.........",
39 "........##b.........",
40 "........##b.........",
41 "........##b.........",
42 "...############a....",
43 "...############b....",
44 "...abbbb##bbbbbb....",
45 "........##b.........",
46 "........##b.........",
47 "........##b.........",
48 "........##b.........",
49 "........abb.........",
50 "....................",
51 "....................",
52 "...................."};
54 static const char* const del_pix_data[] = {
76 static const char* const up_pix_data[] = {
100 static const char* const down_pix_data[] = {
128 SUPERVGUI_ManagePortsDlg::SUPERVGUI_ManagePortsDlg( SUPERVGUI_CanvasNode* theNode )
129 : QDialog( QAD_Application::getDesktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu | WDestructiveClose )
136 void SUPERVGUI_ManagePortsDlg::init()
138 setName( "SUPERVGUI_ManagePortsDlg" );
140 SUPERV_CNode aCNode = myNode->getEngine();
141 setCaption( tr( "TIT_MANAGE_PORTS" ) + aCNode->Name() );
143 QGridLayout* aBaseLayout = new QGridLayout( this );
144 aBaseLayout->setMargin( 11 );
145 aBaseLayout->setSpacing( 6 );
147 // -- name and type upper line widgets --
148 QLabel* aNameLbl = new QLabel( tr( "NAME_LBL") , this );
149 myNameEdt = new QLineEdit( this );
150 QLabel* aTypeLbl = new QLabel( tr( "TYPE_LBL" ), this );
151 myTypeCombo = new QComboBox( false, this ); // input field not editable
153 aBaseLayout->addWidget( aNameLbl, 0, 0 );
154 aBaseLayout->addWidget( myNameEdt, 0, 1 );
155 aBaseLayout->addWidget( aTypeLbl, 0, 2 );
156 aBaseLayout->addWidget( myTypeCombo, 0, 3 );
157 aBaseLayout->setColStretch( 1, 1 );
158 aBaseLayout->setColStretch( 3, 1 );
160 // -- common Input/Output variables --
161 QPixmap adPix( (const char**) add_pix_data );
162 QPixmap rmPix( (const char**) del_pix_data );
163 QPixmap upPix( (const char**) up_pix_data );
164 QPixmap dnPix( (const char**) down_pix_data );
166 // -- Input ports group box --
167 QGroupBox* anInputGr = new QGroupBox( 1, Qt::Vertical, tr( "INPUT" ), this );
168 anInputGr->layout()->setSpacing( 6 );
169 anInputGr->layout()->setMargin( 11 );
171 myInList = new QListBox( anInputGr );
172 myInList->setSelectionMode( QListBox::Single );
174 QGroupBox* anInputBtnGr = new QGroupBox( 0, Qt::Vertical, anInputGr );
175 anInputBtnGr->setFrameStyle( QFrame::NoFrame );
176 anInputBtnGr->layout()->setSpacing( 0 );
177 anInputBtnGr->layout()->setMargin( 0 );
179 QVBoxLayout* anInputBtnLay = new QVBoxLayout( anInputBtnGr->layout() );
180 anInputBtnLay->layout()->setSpacing( 6 );
181 anInputBtnLay->layout()->setMargin( 0 );
183 QPushButton* anAddInputBtn = new QPushButton( anInputBtnGr );
184 anAddInputBtn->setPixmap( adPix );
185 QPushButton* aDeleteInputBtn = new QPushButton( anInputBtnGr );
186 aDeleteInputBtn->setPixmap( rmPix );
187 QPushButton* anUpInputBtn = new QPushButton( anInputBtnGr );
188 anUpInputBtn->setPixmap( upPix );
189 QPushButton* aDownInputBtn = new QPushButton( anInputBtnGr );
190 aDownInputBtn->setPixmap( dnPix );
192 connect( anAddInputBtn, SIGNAL( clicked() ), this, SLOT( addInput() ) );
193 connect( aDeleteInputBtn, SIGNAL( clicked() ), this, SLOT( removeInput() ) );
194 connect( anUpInputBtn, SIGNAL( clicked() ), this, SLOT( upInput() ) );
195 connect( aDownInputBtn, SIGNAL( clicked() ), this, SLOT( downInput() ) );
197 anInputBtnLay->addWidget( anAddInputBtn );
198 anInputBtnLay->addWidget( aDeleteInputBtn );
199 anInputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
200 anInputBtnLay->addWidget( anUpInputBtn );
201 anInputBtnLay->addWidget( aDownInputBtn );
202 anInputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
204 aBaseLayout->addMultiCellWidget( anInputGr, 1, 1, 0, 1 );
206 // -- Output ports group box --
207 QGroupBox* anOutputGr = new QGroupBox( 1, Qt::Vertical, tr( "OUTPUT" ), this );
208 anOutputGr->layout()->setSpacing( 6 );
209 anOutputGr->layout()->setMargin( 11 );
211 myOutList = new QListBox( anOutputGr );
212 myOutList->setSelectionMode( QListBox::Single );
214 QGroupBox* anOutputBtnGr = new QGroupBox( 0, Qt::Vertical, anOutputGr );
215 anOutputBtnGr->setFrameStyle( QFrame::NoFrame );
216 anOutputBtnGr->layout()->setSpacing( 0 );
217 anOutputBtnGr->layout()->setMargin( 0 );
219 QVBoxLayout* anOutputBtnLay = new QVBoxLayout( anOutputBtnGr->layout() );
220 anOutputBtnLay->layout()->setSpacing( 6 );
221 anOutputBtnLay->layout()->setMargin( 0 );
223 QPushButton* anAddOutputBtn = new QPushButton( anOutputBtnGr );
224 anAddOutputBtn->setPixmap( adPix );
225 QPushButton* aDeleteOutputBtn = new QPushButton( anOutputBtnGr );
226 aDeleteOutputBtn->setPixmap( rmPix );
227 QPushButton* anUpOutputBtn = new QPushButton( anOutputBtnGr );
228 anUpOutputBtn->setPixmap( upPix );
229 QPushButton* aDownOutputBtn = new QPushButton( anOutputBtnGr );
230 aDownOutputBtn->setPixmap( dnPix );
232 connect( anAddOutputBtn, SIGNAL( clicked() ), this, SLOT( addOutput() ) );
233 connect( aDeleteOutputBtn, SIGNAL( clicked() ), this, SLOT( removeOutput() ) );
234 connect( anUpOutputBtn, SIGNAL( clicked() ), this, SLOT( upOutput() ) );
235 connect( aDownOutputBtn, SIGNAL( clicked() ), this, SLOT( downOutput() ) );
237 anOutputBtnLay->addWidget( anAddOutputBtn );
238 anOutputBtnLay->addWidget( aDeleteOutputBtn );
239 anOutputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
240 anOutputBtnLay->addWidget( anUpOutputBtn );
241 anOutputBtnLay->addWidget( aDownOutputBtn );
242 anOutputBtnLay->addItem( new QSpacerItem( 1, 16, QSizePolicy::Maximum, QSizePolicy::MinimumExpanding ) );
244 aBaseLayout->addMultiCellWidget( anOutputGr, 1, 1, 2, 3 );
246 // -- Ok / Cancel buttons line at the bottom of dialog --
247 QGroupBox* aBtnBox = new QGroupBox( this );
248 aBtnBox->setColumnLayout( 0, Qt::Vertical );
249 aBtnBox->layout()->setSpacing( 0 );
250 aBtnBox->layout()->setMargin( 0 );
252 QHBoxLayout* aBtnLayout = new QHBoxLayout( aBtnBox->layout() );
253 aBtnLayout->setAlignment( Qt::AlignTop );
254 aBtnLayout->setSpacing( 6 );
255 aBtnLayout->setMargin( 11 );
257 QPushButton* aOkBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
258 QPushButton* aCancelBtn = new QPushButton( tr( "BUT_CANCEL" ), aBtnBox );
259 connect( aOkBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
260 connect( aCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
262 aBtnLayout->addWidget( aOkBtn );
263 aBtnLayout->addStretch();
264 aBtnLayout->addWidget( aCancelBtn );
266 aBaseLayout->addMultiCellWidget( aBtnBox, 2, 2, 0, 3 );
269 connect( myInList,SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
270 connect( myOutList, SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
271 connect( myNameEdt, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
272 connect( myTypeCombo, SIGNAL(activated(const QString&)), this, SLOT(typeChanged(const QString&)));
274 myNode->getMain()->lockedGraph( true );
280 SUPERVGUI_ManagePortsDlg::~SUPERVGUI_ManagePortsDlg() {
284 * Set the ports as entered by user (order, name/type, etc.) and close the dialog
286 void SUPERVGUI_ManagePortsDlg::accept() {
287 // 1. set the ports to Engine's CNode
288 SUPERV_INode aINode = myNode->getInlineNode();
289 if ( !SUPERV_isNull( aINode ) ) {
292 // 1.1 delete all ports (delete CanvasPorts, they delete SUPERV_Ports)
293 QObjectList* oldPorts = myNode->queryList("SUPERVGUI_CanvasPort");
294 QObjectListIt it( *oldPorts ); // iterate over the old ports
297 while ( (obj = it.current()) != 0 ) {
299 if ( !((SUPERVGUI_CanvasPort*)obj)->getEngine()->IsGate() ) // never do anything with Gate ports
300 ((SUPERVGUI_CanvasPort*)obj)->remove();
302 delete oldPorts; // delete the list, not the objects
304 // 1.2 create new ports in INode and CanvasPort in myNode
307 for ( i = 0; i < myInList->count(); i++ ) {
308 item = (PortListItem*)myInList->item( i );
309 aPort = aINode->InPort( item->PortName.latin1(), item->PortType.latin1() );
310 myNode->createPort( aPort.in() );
312 for ( i = 0; i < myOutList->count(); i++ ) {
313 item = (PortListItem*)myOutList->item( i );
314 aPort = aINode->OutPort( item->PortName.latin1(), item->PortType.latin1() );
315 myNode->createPort( aPort.in() );
318 // 2. update the node's presentation
319 myNode->getMain()->getCanvas()->update();
322 // 3. close the dialog
323 myNode->getMain()->lockedGraph( false );
329 * Simply close the dialog
331 void SUPERVGUI_ManagePortsDlg::reject() {
332 myNode->getMain()->lockedGraph( false );
338 * Update current values on show event
340 void SUPERVGUI_ManagePortsDlg::showEvent( QShowEvent* theEvent ) {
342 QDialog::showEvent( theEvent );
346 * Initialize In/Out tables with values from the given node
348 void SUPERVGUI_ManagePortsDlg::init( const SUPERVGUI_CanvasNode* theNode ) {
350 MESSAGE("ERROR: SUPERVGUI_ManagePortsDlg: the CanvasNode is nil!");
354 SUPERV_INode aINode = myNode->getInlineNode();
355 if ( SUPERV_isNull( aINode ) ) {
356 MESSAGE("ERROR: SUPERVGUI_ManagePortsDlg: the node of wrong type is found (not InLine node)!");
360 // 1. fill myTypeCombo with all available types
361 myTypeCombo->insertStrList( gTypes );
363 // 2. fill Input and Output listboxes with Ports' names/types
365 SUPERV_Ports aPorts = aINode->Ports();
366 for ( int i=0; i < aPorts->length(); i++ ) {
367 if ( aPorts[i]->IsGate() )
369 if ( aPorts[i]->IsInput() )
370 new PortListItem( myInList, aPorts[i]->Name(), aPorts[i]->Type() );
372 new PortListItem( myOutList, aPorts[i]->Name(), aPorts[i]->Type() );
376 void SUPERVGUI_ManagePortsDlg::addPort( QListBox* theLB ) {
379 QString name = myNameEdt->text();
380 if ( !name.isNull() && name.length() ) {
381 bool found = false; // check if already exists -- and don't allow if yes
382 for ( int i = 0; i < theLB->count(); i++ ) {
383 if ( ((PortListItem*)theLB->item(i))->PortName == name ) {
389 QMessageBox::warning( QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_PORT_EXIST") );
391 new PortListItem( theLB, name, myTypeCombo->currentText() );
395 void SUPERVGUI_ManagePortsDlg::removePort( QListBox* theLB ) {
399 const int i = theLB->currentItem();
401 delete theLB->item( i );
404 void SUPERVGUI_ManagePortsDlg::moveItem( QListBox* theLB, const int from, const int to ) {
408 // disconnect itemChanged - it leads to crash if there was only 1 item left
409 disconnect( theLB, SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
411 if ( from >= 0 && from < theLB->count() && to >=0 && to < theLB->count() ) {
412 QListBoxItem* item = theLB->item( from );
413 theLB->takeItem( item );
414 theLB->insertItem( item, to );
415 theLB->setCurrentItem( item );
416 theLB->setSelected( item, true );
420 connect( theLB, SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(itemChanged(QListBoxItem*)));
423 void SUPERVGUI_ManagePortsDlg::moveUp( QListBox* theLB ) {
426 const int i = theLB->currentItem();
427 moveItem( theLB, i, i-1 );
430 void SUPERVGUI_ManagePortsDlg::moveDown( QListBox* theLB ) {
433 const int i = theLB->currentItem();
434 moveItem( theLB, i, i+1 );
439 * returns true if there is a current and selected item in the given listbox and it
440 * equals to the given item.
442 bool isEditingItem( const QListBoxItem* item, const QListBox* theLB ) {
443 return item && item == theLB->item( theLB->currentItem() ) && theLB->isSelected( item );
447 * called when name is changed. Tries to change name of the item, which was
448 * the last selected by user item in myInList or myOutList (myLastItem)
450 void SUPERVGUI_ManagePortsDlg::nameChanged( const QString& name ) {
451 if ( isEditingItem( myLastItem, myInList ) || isEditingItem( myLastItem, myOutList ) ) {
452 ((PortListItem*)myLastItem)->PortName = name;
453 //myLastItem->listBox()->repaint( true );
454 // it would be much better to change the item and repaint it -- but -- repaint()
455 // is done only after a while, which is not good.. so -- "cheating" around
456 const int i = myLastItem->listBox()->index( myLastItem );
457 moveItem( myLastItem->listBox(), i, i );
462 * called when type item in myTypeCombo is changed. Tries to change type
463 * of the last selected by user item in myInList or myOutList (myLastItem)
465 void SUPERVGUI_ManagePortsDlg::typeChanged( const QString& type ) {
466 if ( isEditingItem( myLastItem, myInList ) || isEditingItem( myLastItem, myOutList ) ) {
467 ((PortListItem*)myLastItem)->PortType = type;
468 //myLastItem->listBox()->repaint( true );
469 // it would be much better to change the item and repaint it -- but -- repaint()
470 // is done only after a while, which is not good.. so -- "cheating" around
471 const int i = myLastItem->listBox()->index( myLastItem );
472 moveItem( myLastItem->listBox(), i, i );
477 * called when new item became "currentItem" in any myInList or myOutList listboxes.
479 void SUPERVGUI_ManagePortsDlg::itemChanged( QListBoxItem * item ) {
480 if ( !item ) // after remove, etc..
483 // disable nameChanged, typeChanged callbacks
484 disconnect( myNameEdt, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
485 disconnect( myTypeCombo, SIGNAL(activated(const QString&)), this, SLOT(typeChanged(const QString&)));
488 myNameEdt->setText( ((PortListItem*)item)->PortName );
489 for ( int i = 0; i < myTypeCombo->count(); i++ )
490 if ( myTypeCombo->text( i ) == ((PortListItem*)item)->PortType ) {
491 myTypeCombo->setCurrentItem( i );
495 // connect back nameChanged, typeChanged
496 connect( myNameEdt, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
497 connect( myTypeCombo, SIGNAL(activated(const QString&)), this, SLOT(typeChanged(const QString&)));
504 * Port parameters dialog definition (taken from SUPERVGUI_Node.cxx without change)
507 SUPERVGUI_PortParamsDlg::SUPERVGUI_PortParamsDlg(const QStringList& thePortsNames)
508 : QDialog(QAD_Application::getDesktop(), 0, true, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu ),
509 myPortsNames( thePortsNames )
511 setSizeGripEnabled( true );
512 setCaption("Port parameters");
514 QGridLayout* aBaseLayout = new QGridLayout( this );
515 aBaseLayout->setMargin( 11 ); aBaseLayout->setSpacing( 6 );
517 QLabel* aNameLbl = new QLabel("Port Name", this );
518 aBaseLayout->addWidget(aNameLbl, 0, 0);
520 myNameTxt = new QLineEdit( this );
521 aNameLbl->setBuddy( myNameTxt );
522 aBaseLayout->addWidget(myNameTxt, 0, 1);
524 QLabel* aTypeLbl = new QLabel("Value Type", this );
525 aBaseLayout->addWidget(aTypeLbl, 1, 0);
527 myTypeTxt = new QComboBox( this );
528 aTypeLbl->setBuddy( myTypeTxt );
529 myTypeTxt->insertStrList( gTypes );
530 aBaseLayout->addWidget(myTypeTxt, 1, 1);
532 QGroupBox* aBtnBox = new QGroupBox( this );
533 aBtnBox->setColumnLayout( 0, Qt::Vertical );
534 aBtnBox->layout()->setSpacing( 0 ); aBtnBox->layout()->setMargin( 0 );
535 QHBoxLayout* aBtnLayout = new QHBoxLayout( aBtnBox->layout() );
536 aBtnLayout->setAlignment( Qt::AlignTop );
537 aBtnLayout->setSpacing( 6 ); aBtnLayout->setMargin( 11 );
539 aBaseLayout->addMultiCellWidget( aBtnBox, 2, 2, 0, 1 );
541 QPushButton* aOKBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
542 connect( aOKBtn, SIGNAL( clicked() ), this, SLOT( clickOnOk() ) );
543 aBtnLayout->addWidget( aOKBtn );
545 aBtnLayout->addStretch();
547 QPushButton* aCancelBtn = new QPushButton( tr("BUT_CANCEL"), aBtnBox );
548 connect( aCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
549 aBtnLayout->addWidget( aCancelBtn );
552 void SUPERVGUI_PortParamsDlg::clickOnOk()
554 if (getName().isEmpty() || getType().isEmpty())
555 QMessageBox::warning( QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_CANT_CREATE_PORT" ) );
556 else if (myPortsNames.contains(getName()))
557 QMessageBox::warning( QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_PORT_EXIST") );