1 // Copyright (C) 2005-2022 OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 ///////////////////////////////////////////////////////////
21 // File : SierpinskyGUI_RunDlg.cxx
22 // Author : Vadim SANDLER (OCN)
24 ///////////////////////////////////////////////////////////
26 #include "SierpinskyGUI_RunDlg.h"
27 #include "SierpinskyGUI.h"
28 #include "SALOME_LifeCycleCORBA.hxx"
29 #include "SalomeApp_Application.h"
34 #include <QPushButton>
39 #include <QProgressBar>
40 #include <QApplication>
42 #include <SUIT_Application.h>
43 #include <SUIT_Desktop.h>
44 #include <SUIT_FileDlg.h>
45 #include <QtxDoubleSpinBox.h>
46 #include <SUIT_MessageBox.h>
48 #include <SALOMEconfig.h>
49 #include CORBA_SERVER_HEADER(Sierpinsky)
50 #include CORBA_CLIENT_HEADER(Randomizer)
51 #include CORBA_CLIENT_HEADER(SALOMEDS)
53 #include CORBA_CLIENT_HEADER(VISU_Gen)
56 #include <utilities.h>
59 * Get Randomizer component engine
61 static RANDOMIZER_ORB::RANDOMIZER_var getRandomizerEngine()
63 static RANDOMIZER_ORB::RANDOMIZER_var aGen;
64 if( CORBA::is_nil( aGen ) ) {
66 SALOME_LifeCycleCORBA aLCC(SalomeApp_Application::namingService());
67 Engines::EngineComponent_var aComponent = aLCC.FindOrLoad_Component("FactoryServerPy","RANDOMIZER");
68 aGen = RANDOMIZER_ORB::RANDOMIZER::_narrow( aComponent );
70 catch (CORBA::Exception&){
71 MESSAGE("Caught CORBA::Exception.");
74 MESSAGE("Caught unknown exception.");
81 * Get Sierpinsky component engine
83 static SIERPINSKY_ORB::SIERPINSKY_var getSierpinskyEngine()
85 static SIERPINSKY_ORB::SIERPINSKY_var aGen;
86 if( CORBA::is_nil( aGen ) ) {
88 SALOME_LifeCycleCORBA aLCC(SalomeApp_Application::namingService());
89 Engines::EngineComponent_var aComponent = aLCC.FindOrLoad_Component("FactoryServer","SIERPINSKY");
90 aGen = SIERPINSKY_ORB::SIERPINSKY::_narrow( aComponent );
92 catch (CORBA::Exception&){
93 MESSAGE("Caught CORBA::Exception.");
96 MESSAGE("Caught unknown exception.");
104 * Get VISU component engine
106 static VISU::VISU_Gen_var getVisuEngine()
108 static VISU::VISU_Gen_var aGen;
109 if( CORBA::is_nil( aGen ) ) {
111 SALOME_LifeCycleCORBA aLCC(SalomeApp_Application::namingService());
112 Engines::EngineComponent_var aComponent = aLCC.FindOrLoad_Component("FactoryServer","VISU");
113 aGen = VISU::VISU_Gen::_narrow( aComponent );
115 catch (CORBA::Exception&){
116 MESSAGE("Caught CORBA::Exception.");
119 MESSAGE("Caught unknown exception.");
127 #define MY_EVENT QEvent::User + 555
128 class MyEvent : public QEvent
131 MyEvent( const int iter ) : QEvent( (QEvent::Type)(MY_EVENT) ), myIter( iter ) {}
132 int iter() const { return myIter; }
139 * Progress thread class
141 class MyThread : public QThread
144 MyThread( SierpinskyGUI_RunDlg* parent, const double x, const double y, const int nbIter ) :
145 myParent( parent ), myStopped( false ), myX( x ), myY( y ), myNbIter( nbIter ) { start(); }
147 void init( const double x, const double y, const int nbIter )
154 void stop() { myStopped = true; }
159 while ( !myStopped && myNbIter-- ) {
160 int ni = getRandomizerEngine()->NextIteration();
161 getSierpinskyEngine()->NextPoint( myX, myY, ni, myX, myY );
162 QApplication::postEvent( myParent, new MyEvent( myNbIter ) );
168 SierpinskyGUI_RunDlg* myParent;
175 #define MARGIN_SIZE 11
176 #define SPACING_SIZE 6
181 SierpinskyGUI_RunDlg::SierpinskyGUI_RunDlg( QWidget* parent, SierpinskyGUI* module )
182 : QDialog( parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint ),
183 myThread( 0 ), myModule( module )
185 setAttribute( Qt::WA_DeleteOnClose );
187 setObjectName("SierpinskyGUI_RunDlg");
190 setWindowTitle( tr( "CAPTION" ) );
191 setSizeGripEnabled( true );
193 QGridLayout* topLayout = new QGridLayout( this );
194 topLayout->setMargin( MARGIN_SIZE ); topLayout->setSpacing( SPACING_SIZE );
197 box1 = new QGroupBox( tr( "START_POINT" ), this );
198 QGridLayout* box1Layout = new QGridLayout( box1 );
199 box1Layout->setAlignment( Qt::AlignTop );
200 box1Layout->setMargin( MARGIN_SIZE );
201 box1Layout->setSpacing( SPACING_SIZE );
203 QLabel* labX = new QLabel( "X:", box1 );
204 myStartX = new QtxDoubleSpinBox( 0.0, 1.0, 0.1 ,box1);
205 myStartX->setMinimumWidth( 150 );
207 QLabel* labY = new QLabel( "Y:", box1 );
208 myStartY = new QtxDoubleSpinBox( 0.0, 1.0, 0.1 ,box1);
209 myStartY->setMinimumWidth( 150 );
211 myStartRandom = new QCheckBox( tr( "RANDOM" ), box1 );
213 box1Layout->addWidget( labX, 0, 0 );
214 box1Layout->addWidget( myStartX, 0, 1 );
215 box1Layout->addWidget( labY, 0, 2 );
216 box1Layout->addWidget( myStartY, 0, 3 );
217 box1Layout->addWidget( myStartRandom, 1, 1 );
220 box2 = new QGroupBox( tr( "BASE_POINTS" ), this );
221 QGridLayout* box2Layout = new QGridLayout( box2 );
222 box2Layout->setAlignment( Qt::AlignTop );
223 box2Layout->setMargin( MARGIN_SIZE );
224 box2Layout->setSpacing( SPACING_SIZE );
226 QLabel* labX1 = new QLabel( "X1:", box2 );
227 myX1 = new QtxDoubleSpinBox( 0.0, 1.0, 0.1 , box2);
228 myX1->setMinimumWidth( 150 );
230 QLabel* labY1 = new QLabel( "Y1:", box2 );
231 myY1 = new QtxDoubleSpinBox( 0.0, 1.0, 0.1 , box2);
232 myY1->setMinimumWidth( 150 );
234 QLabel* labX2 = new QLabel( "X2:", box2 );
235 myX2 = new QtxDoubleSpinBox( 0.0, 1.0, 0.1 , box2);
236 myX2->setMinimumWidth( 150 );
238 QLabel* labY2 = new QLabel( "Y2:", box2 );
239 myY2 = new QtxDoubleSpinBox( 0.0, 1.0, 0.1, box2);
240 myY2->setMinimumWidth( 150 );
242 QLabel* labX3 = new QLabel( "X3:", box2 );
243 myX3 = new QtxDoubleSpinBox( 0.0, 1.0, 0.1, box2);
244 myX3->setMinimumWidth( 150 );
246 QLabel* labY3 = new QLabel( "Y3:", box2 );
247 myY3 = new QtxDoubleSpinBox( 0.0, 1.0, 0.1, box2);
248 myY3->setMinimumWidth( 150 );
250 myBaseRandom = new QCheckBox( tr( "RANDOM" ), box2 );
251 myBaseDefault = new QCheckBox( tr( "DEFAULT" ), box2 );
253 box2Layout->addWidget( labX1, 0, 0 );
254 box2Layout->addWidget( myX1, 0, 1 );
255 box2Layout->addWidget( labY1, 0, 2 );
256 box2Layout->addWidget( myY1, 0, 3 );
257 box2Layout->addWidget( labX2, 1, 0 );
258 box2Layout->addWidget( myX2, 1, 1 );
259 box2Layout->addWidget( labY2, 1, 2 );
260 box2Layout->addWidget( myY2, 1, 3 );
261 box2Layout->addWidget( labX3, 2, 0 );
262 box2Layout->addWidget( myX3, 2, 1 );
263 box2Layout->addWidget( labY3, 2, 2 );
264 box2Layout->addWidget( myY3, 2, 3 );
265 box2Layout->addWidget( myBaseRandom, 3, 1 );
266 box2Layout->addWidget( myBaseDefault, 3, 3 );
268 // number of iterations
269 QLabel* labIter = new QLabel( tr( "NB_ITERATIONS" ), this );
270 myIter = new QSpinBox( this );
271 myIter->setMinimum(1);
272 myIter->setMaximum(100000);
273 myIter->setSingleStep(1);
276 box3 = new QGroupBox( tr( "RESULTS" ), this );
277 QGridLayout* box3Layout = new QGridLayout( box3 );
278 box3Layout->setAlignment( Qt::AlignTop );
279 box3Layout->setMargin( MARGIN_SIZE );
280 box3Layout->setSpacing( SPACING_SIZE );
282 myJpegCheck = new QCheckBox( tr( "EXPORT_2_JPEG" ), box3 );
283 myJpegFile = new QLineEdit( box3 );
284 myJpegFile->setMinimumWidth( 300 );
286 myJpegBtn = new QPushButton( "...", box3 );
287 myJpegBtn->setFixedSize( 20, 20 );
289 QLabel* labJpeg = new QLabel( tr( "IMAGE_SIZE" ), box3 );
290 myJpegSize = new QSpinBox( box3 );
291 myJpegSize->setMinimum(0);
292 myJpegSize->setMaximum(1280);
293 myJpegSize->setSingleStep(10);
294 myJpegSize->setMinimumWidth( 150 );
296 QFrame* line = new QFrame( box3 );
297 line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
299 myMedCheck = new QCheckBox( tr( "EXPORT_2_MED" ), box3 );
300 myMedFile = new QLineEdit( box3 );
301 myMedFile->setMinimumWidth( 300 );
303 myMedBtn = new QPushButton( "...", box3 );
304 myMedBtn->setFixedSize( 20, 20 );
306 QLabel* labMed = new QLabel( tr( "MESH_SIZE" ), box3 );
307 myMedSize = new QtxDoubleSpinBox( 0.0, 1000, 1.0, box3);
308 myMedSize->setMinimumWidth( 150 );
310 myVisuCheck = new QCheckBox( tr( "IMPORT_MED_2_VISU" ), box3 );
312 box3Layout->addWidget( myJpegCheck, 0, 0, 1, 4 );
313 box3Layout->addWidget( myJpegFile, 1, 0, 1, 3 );
314 box3Layout->addWidget( myJpegBtn, 1, 3 );
315 box3Layout->addWidget( labJpeg, 2, 0 );
316 box3Layout->addWidget( myJpegSize, 2, 1 );
317 box3Layout->addWidget( line, 3, 0, 1, 4 );
318 box3Layout->addWidget( myMedCheck, 4, 0, 1, 4 );
319 box3Layout->addWidget( myMedFile, 5, 0, 1, 3 );
320 box3Layout->addWidget( myMedBtn, 5, 3 );
321 box3Layout->addWidget( labMed, 6, 0 );
322 box3Layout->addWidget( myMedSize, 6, 1 );
323 box3Layout->addWidget( myVisuCheck, 7, 0, 1, 4 );
326 myProgress = new QProgressBar( this );
327 myProgress->setTextVisible( false );
328 myProgress->setFixedHeight( 10 );
331 myStartBtn = new QPushButton( tr( "START_BTN" ), this );
332 myCancelBtn = new QPushButton( tr( "CANCEL_BTN" ), this );
333 QHBoxLayout* btnLayout = new QHBoxLayout;
334 btnLayout->addWidget( myStartBtn );
335 btnLayout->addStretch();
336 btnLayout->addWidget( myCancelBtn );
338 topLayout->addWidget( box1, 0, 0, 1, 2 );
339 topLayout->addWidget( box2, 1, 0, 1, 2 );
340 topLayout->addWidget( labIter, 2, 0 );
341 topLayout->addWidget( myIter, 2, 1 );
342 topLayout->addWidget( box3, 3, 0, 1, 2 );
343 topLayout->addWidget( myProgress, 4, 0, 1, 2 );
344 topLayout->addLayout( btnLayout, 5, 0, 1, 2 );
346 // signals and slots connections
347 connect( myJpegBtn, SIGNAL( clicked() ), this, SLOT( onBrowse() ) );
348 connect( myMedBtn, SIGNAL( clicked() ), this, SLOT( onBrowse() ) );
349 connect( myStartRandom, SIGNAL( clicked() ), this, SLOT( updateState() ) );
350 connect( myBaseRandom, SIGNAL( clicked() ), this, SLOT( toggled() ) );
351 connect( myBaseDefault, SIGNAL( clicked() ), this, SLOT( toggled() ) );
352 connect( myJpegCheck, SIGNAL( clicked() ), this, SLOT( updateState() ) );
353 connect( myMedCheck, SIGNAL( clicked() ), this, SLOT( updateState() ) );
354 connect( myStartBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
355 connect( myCancelBtn, SIGNAL( clicked() ), this, SLOT( close() ) );
358 myStartX->setValue( 0.0 ); myStartY->setValue( 0.0 );
359 myStartRandom->setChecked( true );
360 myX1->setValue( 0.5 ); myY1->setValue( 1.0 );
361 myX2->setValue( 0.0 ); myY2->setValue( 0.0 );
362 myX3->setValue( 1.0 ); myY3->setValue( 0.0 );
363 myBaseRandom->setChecked( false );
364 myBaseDefault->setChecked( true );
365 myIter->setValue( 1000 );
366 myJpegCheck->setChecked( false );
367 myJpegSize->setValue( 200 );
368 myMedCheck->setChecked( false );
369 myMedSize->setValue( 100 );
370 myVisuCheck->setChecked( true );
372 myVisuCheck->setVisible( false );
380 SierpinskyGUI_RunDlg::~SierpinskyGUI_RunDlg()
392 void SierpinskyGUI_RunDlg::onBrowse()
394 const QObject* snd = sender();
395 bool jpg = snd == myJpegBtn;
396 QString aFileName = SUIT_FileDlg::getFileName( this,
397 jpg ? myJpegFile->text() : myMedFile->text(),
398 (jpg ? tr( "JPEG_FILES") : tr( "MED_FILES" )).split( ":", QString::SkipEmptyParts ),
399 jpg ? tr( "EXPORT_JPEG_FILE" ) : tr( "EXPORT_MED_FILE" ),
401 if ( !aFileName.isEmpty() ) {
402 jpg ? myJpegFile->setText( aFileName ) : myMedFile->setText( aFileName );
407 * Update widgets state
409 void SierpinskyGUI_RunDlg::updateState()
411 myStartX->setEnabled( !myStartRandom->isChecked() );
412 myStartY->setEnabled( !myStartRandom->isChecked() );
414 myX1->setEnabled( !myBaseRandom->isChecked() && !myBaseDefault->isChecked() );
415 myY1->setEnabled( !myBaseRandom->isChecked() && !myBaseDefault->isChecked() );
416 myX2->setEnabled( !myBaseRandom->isChecked() && !myBaseDefault->isChecked() );
417 myY2->setEnabled( !myBaseRandom->isChecked() && !myBaseDefault->isChecked() );
418 myX3->setEnabled( !myBaseRandom->isChecked() && !myBaseDefault->isChecked() );
419 myY3->setEnabled( !myBaseRandom->isChecked() && !myBaseDefault->isChecked() );
421 myJpegFile->setEnabled( myJpegCheck->isChecked() );
422 myJpegBtn->setEnabled( myJpegCheck->isChecked() );
423 myJpegSize->setEnabled( myJpegCheck->isChecked() );
425 myMedFile->setEnabled( myMedCheck->isChecked() );
426 myMedBtn->setEnabled( myMedCheck->isChecked() );
427 myMedSize->setEnabled( myMedCheck->isChecked() );
428 myVisuCheck->setEnabled( myMedCheck->isChecked() );
432 * Toggle 'Base points' mode
434 void SierpinskyGUI_RunDlg::toggled()
436 const QObject* snd = sender();
437 if ( snd == myBaseRandom && myBaseRandom->isChecked() ) myBaseDefault->setChecked( false );
438 if ( snd == myBaseDefault && myBaseDefault->isChecked() ) myBaseRandom->setChecked( false );
443 * Called when user presses 'Start' button
445 void SierpinskyGUI_RunDlg::accept()
447 RANDOMIZER_ORB::RANDOMIZER_var aRandGen = getRandomizerEngine();
448 SIERPINSKY_ORB::SIERPINSKY_var aSierpGen = getSierpinskyEngine();
450 if( CORBA::is_nil( aRandGen ) || CORBA::is_nil( aSierpGen ) ) {
451 SUIT_MessageBox::critical( this,
461 if ( myJpegCheck->isChecked() ) {
462 aJPEGFile = myJpegFile->text().trimmed();
463 aJPEGSize = myJpegSize->value();
464 if ( aJPEGFile.isEmpty() || aJPEGSize <= 0 ) {
465 int res = SUIT_MessageBox::warning( this,
467 tr( "JPEG_PARAMETERS_ERROR" ),
468 tr( "YES_BTN"), tr( "NO_BTN" ), 0, 1, 0 );
476 if ( myMedCheck->isChecked() ) {
477 aMEDFile = myMedFile->text().trimmed();
478 aMEDSize = myMedSize->value();
479 if ( aMEDFile.isEmpty() || aMEDSize <= 0 ) {
480 int res = SUIT_MessageBox::warning( this,
482 tr( "MED_PARAMETERS_ERROR" ),
483 tr( "YES_BTN"), tr( "NO_BTN" ), 0, 1, 0 );
489 double x = myStartX->value();
490 double y = myStartY->value();
491 if ( myStartRandom->isChecked() )
492 aRandGen->InitPoint( x, y );
495 if ( myBaseDefault->isChecked() ) {
496 aSierpGen->Reset(); // use default values from engine
499 double x1 = myX1->value();
500 double y1 = myY1->value();
501 double x2 = myX2->value();
502 double y2 = myY2->value();
503 double x3 = myX3->value();
504 double y3 = myY3->value();
505 if ( myBaseRandom->isChecked() ) {
506 aRandGen->InitPoint( x1, y1 );
507 aRandGen->InitPoint( x2, y2 );
508 aRandGen->InitPoint( x3, y3 );
510 aSierpGen->Init( x1, y1, x2, y2, x3, y3 );
514 int iter = myIter->value();
517 myProgress->setMaximum( iter );
518 myProgress->setValue( 0 );
520 myThread = new MyThread( this, x, y, iter );
522 myThread->init( x, y, iter );
523 disconnect( myStartBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
524 connect( myStartBtn, SIGNAL( clicked() ), this, SLOT( stop() ) );
525 myStartBtn->setText( tr( "STOP_BTN" ) );
526 box1->setEnabled( false );
527 box2->setEnabled( false );
528 box3->setEnabled( false );
529 myIter->setEnabled( false );
533 * Called when user presses 'Stop' button
535 void SierpinskyGUI_RunDlg::stop()
538 disconnect( myStartBtn, SIGNAL( clicked() ), this, SLOT( stop() ) );
539 connect( myStartBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
540 myStartBtn->setText( tr( "START_BTN" ) );
541 myProgress->setValue( 0 );
542 box1->setEnabled( true );
543 box2->setEnabled( true );
544 box3->setEnabled( true );
545 myIter->setEnabled( true );
549 * Progress thread calls this method to update progress bar state
551 void SierpinskyGUI_RunDlg::nextStep( const int step )
554 disconnect( myStartBtn, SIGNAL( clicked() ), this, SLOT( stop() ) );
555 connect( myStartBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
556 myStartBtn->setText( tr( "START_BTN" ) );
557 myProgress->setValue( 0 );
558 box1->setEnabled( true );
559 box2->setEnabled( true );
560 box3->setEnabled( true );
561 myIter->setEnabled( true );
564 if ( myJpegCheck->isChecked() ) {
565 QString aJPEGFile = myJpegFile->text().trimmed();
566 int aJPEGSize = myJpegSize->value();
567 if ( !aJPEGFile.isEmpty() && aJPEGSize > 0 ) {
568 bool res = getSierpinskyEngine()->ExportToJPEG( aJPEGFile.toLatin1().data(), aJPEGSize );
570 // error: can't create JPEG image
575 if ( myMedCheck->isChecked() ) {
576 QString aMEDFile = myMedFile->text().trimmed();
577 double aMEDSize = myMedSize->value();
578 if ( !aMEDFile.isEmpty() && aMEDSize > 0 ) {
579 bool res = getSierpinskyEngine()->ExportToMED( aMEDFile.toLatin1().data(), aMEDSize );
581 if ( res && myVisuCheck->isChecked() ) {
582 VISU::VISU_Gen_var aVisuGen = getVisuEngine();
583 if ( !CORBA::is_nil( aVisuGen ) ) {
584 VISU::Result_var aResult = aVisuGen->ImportFile( aMEDFile.toLatin1().data() );
585 if ( !CORBA::is_nil( aResult ) )
586 aVisuGen->MeshOnEntity( aResult, "Sierpinsky", VISU::NODE );
587 myModule->getApp()->updateObjectBrowser( true );
595 myProgress->setValue( myProgress->maximum() - step );
600 * Process progress event
602 void SierpinskyGUI_RunDlg::customEvent( QEvent* e )
604 if ( e->type() == MY_EVENT ) {
605 MyEvent* me = (MyEvent*)e;
606 nextStep( me->iter() );