Salome HOME
Replace med 2.2.2 by med 2.2.3
[tools/install.git] / src / SALOME_InstallWizard.cxx
1 //  File      : SALOME_InstallWizard.cxx 
2 //  Created   : Thu Dec 18 12:01:00 2002
3 //  Author    : Vadim SANDLER
4 //  Project   : SALOME
5 //  Module    : Installation Wizard
6 //  Copyright : 2004-2005 CEA
7
8 #include "globals.h"
9
10 #include "SALOME_InstallWizard.hxx"
11 #include "SALOME_ProductsView.hxx"
12 #include "SALOME_ProgressView.hxx"
13 #include "SALOME_XmlHandler.hxx"
14 #include "SALOME_HelpWindow.hxx"
15
16 #include "icons.h"
17
18 #include <qlineedit.h>
19 #include <qpushbutton.h>
20 #include <qlistview.h>
21 #include <qlabel.h>
22 #include <qtextedit.h>
23 #include <qtextbrowser.h>
24 #include <qprocess.h>
25 #include <qcheckbox.h>
26 #include <qsplitter.h>
27 #include <qlayout.h>
28 #include <qfiledialog.h> 
29 #include <qapplication.h>
30 #include <qfileinfo.h> 
31 #include <qmessagebox.h> 
32 #include <qtimer.h> 
33 #include <qvbox.h>
34 #include <qwhatsthis.h> 
35 #include <qtooltip.h>
36 #include <qfile.h>
37 #include <qthread.h>
38 #include <qwaitcondition.h>
39 #include <qmutex.h>
40 #include <qstringlist.h>
41 #include <qpopupmenu.h>
42
43 #ifdef WNT
44 #include <iostream.h>
45 #include <process.h>
46 #else
47 #include <unistd.h>
48 #include <algo.h>
49 #endif
50
51 #ifdef WNT
52 #define max( x, y ) ( x ) > ( y ) ? ( x ) : ( y )
53 #endif
54
55 QString tmpDirName() { return QString(  "/INSTALLWORK" ) + QString::number( getpid() ); }
56 #define TEMPDIRNAME tmpDirName()
57
58 // ================================================================
59 /*!
60  *  ProcessThread
61  *  Class for executing systen commands
62  */
63 // ================================================================
64 static QMutex myMutex(false);
65 static QWaitCondition myWC;
66 class ProcessThread: public QThread
67 {
68   typedef QPtrList<QCheckListItem> ItemList;
69 public:
70   ProcessThread( SALOME_InstallWizard* iw ) : QThread(), myWizard( iw ) { myItems.setAutoDelete( false ); }
71
72   void addCommand( QCheckListItem* item, const QString& cmd ) {
73     myItems.append( item );
74     myCommands.push_back( cmd );
75   }
76
77   bool hasCommands() const { return myCommands.count() > 0; }
78   void clearCommands()     { myCommands.clear(); myItems.clear(); }
79
80   virtual void run() {
81     while ( hasCommands() ) {
82       ___MESSAGE___( "ProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() );
83       int result = system( myCommands[ 0 ] ) / 256; // return code is <errno> * 256 
84       ___MESSAGE___( "ProcessThread::run - Result : " << result );
85       QCheckListItem* item = myItems.first();
86       myCommands.pop_front();
87       myItems.removeFirst();
88       myMutex.lock();
89       SALOME_InstallWizard::postValidateEvent( myWizard, result, (void*)item );
90       if ( hasCommands() )
91         myWC.wait(&myMutex);
92       myMutex.unlock();
93     };
94   }
95
96 private:
97   QStringList           myCommands;
98   ItemList              myItems;
99   SALOME_InstallWizard* myWizard;
100 };
101
102 // ================================================================
103 /*!
104  *  WarnDialog
105  *  Warning dialog box
106  */
107 // ================================================================
108 class WarnDialog: public QDialog
109 {
110   static WarnDialog* myDlg;
111   bool myCloseFlag;
112
113   WarnDialog( QWidget* parent ) 
114   : QDialog( parent, "WarnDialog", true, WDestructiveClose ) {
115     setCaption( tr( "Information" ) );
116     myCloseFlag = false;
117     QLabel* lab = new QLabel( tr( "Please, wait while checking native products configuration ..." ), this );
118     lab->setAlignment( AlignCenter );
119     lab->setFrameStyle( QFrame::Box | QFrame::Plain ); 
120     QVBoxLayout* l = new QVBoxLayout( this );
121     l->setMargin( 0 );
122     l->add( lab );
123     this->setFixedSize( lab->sizeHint().width()  + 50, 
124                         lab->sizeHint().height() * 5 );
125   }
126   void accept() { return; }
127   void reject() { return; }
128   void closeEvent( QCloseEvent* e )
129   { if ( !myCloseFlag ) return; 
130     e->accept();
131     QDialog::closeEvent( e );
132   }
133   ~WarnDialog() { myDlg = 0; }
134 public:
135   static void showWarnDlg( QWidget* parent, bool show ) {
136     if ( show ) {
137       if ( !myDlg ) {
138         myDlg = new WarnDialog( parent );
139         QSize sh = myDlg->size();
140         myDlg->move( parent->x() + (parent->width()-sh.width())/2, 
141                      parent->y() + (parent->height()-sh.height())/2 );
142         myDlg->show();
143       }
144       myDlg->raise();
145       myDlg->setFocus();
146     }
147     else {
148       if ( myDlg ) {
149         myDlg->myCloseFlag = true;
150         myDlg->close();
151       }
152     }
153   }
154   static bool isWarnDlgShown() { return myDlg != 0; }
155 };
156 WarnDialog* WarnDialog::myDlg = 0;
157
158 // ================================================================
159 /*!
160  *  InstallInfo
161  *  Installation progress info window class
162  */
163 // ================================================================
164 class InstallInfo : public QTextEdit
165 {
166 public:
167   InstallInfo( QWidget* parent ) : QTextEdit( parent ), finished( false ) {}
168   void setFinished( const bool f ) { finished = f; }
169 protected:
170   QPopupMenu* createPopupMenu( const QPoint& )
171   {
172     int para1, col1, para2, col2;
173     getSelection(&para1, &col1, &para2, &col2);
174     bool allSelected = hasSelectedText() &&
175       para1 == 0 && para2 == paragraphs()-1 && col1 == 0 && col2 == paragraphLength(para2);
176     QPopupMenu* popup = new QPopupMenu( this );
177     int id = popup->insertItem( tr( "&Copy" ) );
178     popup->setItemEnabled( id, hasSelectedText() );
179     popup->connectItem ( id, this, SLOT( copy() ) );
180     id = popup->insertItem( tr( "Select &All" ) );
181     popup->setItemEnabled( id, (bool)text().length() && !allSelected );
182     popup->connectItem ( id, this, SLOT( selectAll() ) );
183     if ( finished ) {
184       QWidget* p = parentWidget();
185       while ( p && !p->inherits( "SALOME_InstallWizard" ) )
186         p = p->parentWidget();
187       if ( p && p->inherits( "SALOME_InstallWizard" ) ) {
188         popup->insertSeparator();
189         id = popup->insertItem( tr( "&Save Log" ) );
190         popup->setItemEnabled( id, (bool)text().length() );
191         popup->connectItem ( id, (SALOME_InstallWizard*)p, SLOT( saveLog() ) );
192       }
193     }
194     return popup;
195   }
196 private:
197   bool finished;
198 };
199
200 // ================================================================
201 /*!
202  *  DefineDependeces [ static ]
203  *  Defines list of dependancies as string separated by space symbols
204  */
205 // ================================================================
206 static QString DefineDependeces(MapProducts& theProductsMap) 
207 {
208   QStringList aProducts;
209   for ( MapProducts::Iterator mapIter = theProductsMap.begin(); mapIter != theProductsMap.end(); ++mapIter ) {
210     QCheckListItem* item = mapIter.key();
211     Dependancies dep = mapIter.data();
212     QStringList deps = dep.getDependancies();
213     for (int i = 0; i<(int)deps.count(); i++ ) {
214       if ( !aProducts.contains( deps[i] ) )
215         aProducts.append( deps[i] );
216     }
217     if ( !aProducts.contains( item->text(0) ) )
218       aProducts.append( item->text(0) );
219   }
220   return aProducts.join(" ");
221 }
222
223 #define QUOTE(arg) QString("'") + QString(arg) + QString("'")
224
225 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
226                T H E   O L D   I M P L E M E N T A T I O N 
227 static QString DefineDependeces(MapProducts& theProductsMap, QCheckListItem* product ){
228   QStringList aProducts;
229   if ( theProductsMap.contains( product ) ) {
230     Dependancies dep = theProductsMap[ product ];
231     QStringList deps = dep.getDependancies();
232     for (int i = 0; i<(int)deps.count(); i++ ) {
233       aProducts.append( deps[i] );
234     }
235   }
236   return QString("\"") + aProducts.join(" ") + QString("\"");
237 }
238 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
239
240 // ================================================================
241 /*!
242  *  makeDir [ static ]
243  *  Makes directory recursively, returns false if not succedes
244  */
245 // ================================================================
246 static bool makeDir( const QString& theDir, QString& theCreated )
247 {
248   if ( theDir.isEmpty() )
249     return false;
250   QString aDir = QDir::cleanDirPath( QFileInfo( theDir ).absFilePath() );
251   int start = 1;
252   while ( start > 0 ) {
253     start = aDir.find( QDir::separator(), start );
254     if ( start > 0 ) {
255       QFileInfo fi( aDir.left( start ) );
256       if ( !fi.exists() ) {
257         // VSR: Create directory and set permissions to allow other users to remove it
258         QString script = "mkdir " + fi.absFilePath();
259         script += "; chmod 777 " + fi.absFilePath();
260         script += " > /dev/null";
261         if ( system( script.latin1() ) )
262           return false;
263         // VSR: Remember the top of the created directory (to remove it in the end of the installation)
264         if ( theCreated.isNull() )
265           theCreated = fi.absFilePath();
266       }
267     }
268     start++;
269   }
270   if ( !QFileInfo( aDir ).exists() ) {
271     // VSR: Create directory, other users should NOT have possibility to remove it!!!
272     QString script = "mkdir " + aDir;
273     script += " > /dev/null";
274     if ( system( script.latin1() ) )
275       return false;
276     // VSR: Remember the top of the created directory (to remove it in the end of the installation)
277     if ( theCreated.isNull() )
278       theCreated = aDir;
279   }
280   return true;
281 }
282 // ================================================================
283 /*!
284  *  readFile [ static ]
285  *  Reads the file, returns false if can't open it
286  */
287 // ================================================================
288 static bool readFile( const QString& fileName, QString& text )
289 {
290   if ( QFile::exists( fileName ) ) {
291     QFile file( fileName );
292     if ( file.open( IO_ReadOnly ) ) {
293       QTextStream stream( &file );
294       QString line;
295       while ( !stream.eof() ) {
296         line = stream.readLine(); // line of text excluding '\n'
297         text += line + "\n";
298       }
299       file.close();
300       return true;
301     }
302   }
303   return false;
304 }
305 // ================================================================
306 /*!
307  *  hasSpace [ static ]
308  *  Checks if string contains spaces; used to check directory paths
309  */
310 // ================================================================
311 static bool hasSpace( const QString& dir )
312 {
313   for ( int i = 0; i < (int)dir.length(); i++ ) {
314     if ( dir[ i ].isSpace() )
315       return true;
316   }
317   return false;
318 }
319
320 // ================================================================
321 /*!
322  *  makeTitle
323  *  Creates HTML-wrapped title text
324  */
325 // ================================================================
326 QString makeTitle( const QString& text, const QString& separator = " ", bool fl = true )
327 {
328   QStringList words = QStringList::split( separator, text );
329   if ( fl ) {
330     for ( uint i = 0; i < words.count(); i++ )
331       words[i] = QString( "<font color=red>%1</font>" ).arg( words[i].left(1) ) + words[i].mid(1);
332   }
333   else {
334     if ( words.count() > 0 )
335       words[0] = QString( "<font color=red>%1</font>" ).arg( words[0] );
336     if ( words.count() > 1 )
337       words[words.count()-1] = QString( "<font color=red>%1</font>" ).arg( words[words.count()-1] );
338   }
339   QString res = words.join( separator );
340   if ( !res.isEmpty() )
341     res = QString( "<b>%1</b>" ).arg( res );
342   return res;
343 }
344
345 // ================================================================
346 /*!
347  *  QMyCheckBox class : custom check box
348  *  The only goal is to give access to the protected setState() method
349  */
350 // ================================================================
351 class QMyCheckBox: public QCheckBox
352 {
353 public:
354   QMyCheckBox( const QString& text, QWidget* parent, const char* name = 0 ) : QCheckBox ( text, parent, name ) {}
355   void setState ( ToggleState s ) { QCheckBox::setState( s ); }
356 };
357
358 // ================================================================
359 /*!
360  *  AboutDlg
361  *  "About dialog box.
362  */
363 // ================================================================
364 class AboutDlg: public QDialog
365 {
366 public:
367   AboutDlg( SALOME_InstallWizard* parent ) : QDialog( parent, "About dialog box", true )
368   {
369     // caption
370     setCaption( QString( "About %1" ).arg( parent->getIWName() ) );
371     // palette
372     QPalette pal = palette();
373     QColorGroup cg = pal.active();
374     cg.setColor( QColorGroup::Foreground, Qt::darkBlue );
375     cg.setColor( QColorGroup::Background, Qt::white );
376     pal.setActive( cg ); pal.setInactive( cg ); pal.setDisabled( cg );
377     setPalette( pal );
378     // layout
379     QGridLayout* main = new QGridLayout( this, 1, 1, 11, 6 );
380     // image
381     QLabel* logo = new QLabel( this, "logo" );
382     logo->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
383     logo->setMinimumSize( 32, 32 ); logo->setMaximumSize( 32, 32 );
384     logo->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
385     logo->setFrameStyle( QLabel::NoFrame | QLabel::Plain );
386     logo->setPixmap( pixmap( pxAbout ) );
387     logo->setScaledContents( false );
388     logo->setAlignment( QLabel::AlignCenter );
389     // decoration
390     QLabel* decorLeft = new QLabel( this, "decorLeft" );
391     decorLeft->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding ) );
392     decorLeft->setMinimumWidth( 32 ); decorLeft->setMaximumWidth( 32 );
393     decorLeft->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
394     decorLeft->setScaledContents( false );
395     QLabel* decorTop = new QLabel( this, "decorTop" );
396     decorTop->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
397     decorTop->setMinimumHeight( 32 ); decorTop->setMaximumHeight( 32 );
398     decorTop->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
399     decorTop->setScaledContents( false );
400     // contents
401     QLabel* title = new QLabel( this, "title" );
402     QString tlt = parent->getIWName();
403     title->setText( makeTitle( tlt ) );
404     QLabel* version = new QLabel( this, "version" );
405     version->setText( QString( "<b>Version</b>: %1.%1.%1" ).arg( __IW_VERSION_MAJOR__ ) \
406                       .arg( __IW_VERSION_MINOR__ ) \
407                       .arg( __IW_VERSION_PATCH__ ) );
408     QLabel* copyright = new QLabel( this, "copyright" );
409     copyright->setText( "<b>Copyright</b> &copy; 2004-2006 CEA" );
410     QFont font = title->font();
411     font.setPointSize( (int)( font.pointSize() * 1.8 ) );
412     title->setFont( font );
413     QFrame* line = new QFrame( this, "line" );
414     line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
415     QLabel* url = new QLabel( this, "url" );
416     url->setText( makeTitle( "www.salome-platform.org", ".", false ) );
417     url->setAlignment( AlignRight );
418     font = version->font();
419     font.setPointSize( (int)( font.pointSize() / 1.2 ) );
420     version->setFont( font );
421     copyright->setFont( font );
422     url->setFont( font );
423     // layout
424     main->addWidget( logo, 0, 0 );
425     main->addMultiCellWidget( decorLeft, 1, 5, 0, 0 );
426     main->addWidget( decorTop, 0, 1 );
427     main->addWidget( title, 1, 1 );
428     main->addWidget( version, 2, 1 );
429     main->addWidget( copyright, 3, 1 );
430     main->addWidget( line, 4, 1 );
431     main->addWidget( url, 5, 1 );
432     // resize
433     QFontMetrics fm( title->font() );
434     int width = (int)( fm.width( tlt ) * 1.5 );
435     title->setMinimumWidth( width );
436     setMaximumSize( minimumSize() );
437   }
438   void mousePressEvent( QMouseEvent* )
439   {
440     accept();
441   }
442 };
443
444 // ================================================================
445 /*!
446  *  SALOME_InstallWizard::SALOME_InstallWizard
447  *  Constructor
448  */
449 // ================================================================
450 SALOME_InstallWizard::SALOME_InstallWizard(const QString& aXmlFileName,
451                                            const QString& aTargetDir,
452                                            const QString& aTmpDir)
453      : InstallWizard( qApp->desktop(), "SALOME_InstallWizard", false, 0 ), 
454        helpWindow( NULL ), 
455        moreMode( false ), 
456        previousPage( 0 ), 
457        exitConfirmed( false )
458 {
459   myIWName      = tr( "Installation Wizard" );
460   tmpCreated    = QString::null;
461   xmlFileName   = aXmlFileName;
462   targetDirPath = aTargetDir;
463   tmpDirPath    = aTmpDir;
464
465   // set application font
466   QFont fnt = font();
467   fnt.setPointSize( 14 );
468   fnt.setBold( true );
469   setTitleFont( fnt );
470
471   // set icon
472   setIcon( pixmap( pxIcon ) );
473   // enable sizegrip
474   setSizeGripEnabled( true );
475   
476   // add logo
477   addLogo( pixmap( pxLogo ) );
478   
479   // set defaults
480   setVersion( "1.2" );
481   setCaption( tr( "PAL/SALOME %1" ).arg( myVersion ) );
482   setCopyright( tr( "Copyright (C) 2004 CEA" ) );
483   setLicense( tr( "All right reserved" ) );
484   setOS( "" );
485
486   ___MESSAGE___( "Configuration file : " << xmlFileName );
487   ___MESSAGE___( "Target directory   : " << targetDirPath );
488   ___MESSAGE___( "Temporary directory: " << tmpDirPath );
489
490   // xml reader
491   QFile xmlfile(xmlFileName);
492   if ( xmlfile.exists() ) {
493     QXmlInputSource source( &xmlfile );
494     QXmlSimpleReader reader;
495
496     StructureParser* handler = new StructureParser( this );
497     reader.setContentHandler( handler );
498     reader.parse( source );  
499   }
500
501   // create instance of class for starting shell install script
502   shellProcess = new QProcess( this, "shellProcess" );
503
504   // create introduction page
505   setupIntroPage();
506   // create products page
507   setupProductsPage();
508   // create prestart page
509   setupCheckPage();
510   // create progress page
511   setupProgressPage();
512   // create readme page
513   setupReadmePage();
514   
515   // common buttons
516   QWhatsThis::add( backButton(),   tr( "Returns to the previous step of the installation procedure" ) );
517   QToolTip::add  ( backButton(),   tr( "Returns to the previous step of the installation procedure" ) );
518   QWhatsThis::add( nextButton(),   tr( "Moves to the next step of the installation procedure" ) );
519   QToolTip::add  ( nextButton(),   tr( "Moves to the next step of the installation procedure" ) );
520   QWhatsThis::add( finishButton(), tr( "Finishes installation and quits program" ) );
521   QToolTip::add  ( finishButton(), tr( "Finishes installation and quits program" ) );
522   QWhatsThis::add( cancelButton(), tr( "Cancels installation and quits program" ) );
523   QToolTip::add  ( cancelButton(), tr( "Cancels installation and quits program" ) );
524   QWhatsThis::add( helpButton(),   tr( "Displays help information window" ) );
525   QToolTip::add  ( helpButton(),   tr( "Displays help information window" ) );
526   
527   // common signals connections
528   connect( this, SIGNAL( selected( const QString& ) ),
529                                            this, SLOT( pageChanged( const QString& ) ) );
530   connect( this, SIGNAL( helpClicked() ),  this, SLOT( helpClicked() ) );
531   connect( this, SIGNAL( aboutClicked() ), this, SLOT( onAbout() ) );
532
533   // catch signals from launched script
534   connect(shellProcess, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout() ) );
535   connect(shellProcess, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr() ) );
536   connect(shellProcess, SIGNAL( processExited() ),   this, SLOT( productInstalled() ) );
537   connect(shellProcess, SIGNAL( wroteToStdin() ),    this, SLOT( wroteToStdin() ) );
538
539   // create validation thread
540   myThread = new ProcessThread( this );
541
542   // show about button
543   setAboutIcon( pixmap( pxAbout ) );
544   showAboutBtn( true );
545 }
546 // ================================================================
547 /*!
548  *  SALOME_InstallWizard::~SALOME_InstallWizard
549  *  Destructor
550  */
551 // ================================================================
552 SALOME_InstallWizard::~SALOME_InstallWizard()
553 {
554   shellProcess->kill(); // kill it for sure
555   QString script = "kill -9 ";
556   int PID = (int)shellProcess->processIdentifier();
557   if ( PID > 0 ) {
558     script += QString::number( PID );
559     script += " > /dev/null";
560     ___MESSAGE___( "script: " << script.latin1() );
561     if ( system( script.latin1() ) ) { 
562     }
563   }
564   delete myThread;
565 }
566 // ================================================================
567 /*!
568  *  SALOME_InstallWizard::eventFilter
569  *  Event filter, spies for Help window closing
570  */
571 // ================================================================
572 bool SALOME_InstallWizard::eventFilter( QObject* object, QEvent* event )
573 {
574   if ( object && object == helpWindow && event->type() == QEvent::Close )
575     helpWindow = NULL;
576   return InstallWizard::eventFilter( object, event );
577 }
578 // ================================================================
579 /*!
580  *  SALOME_InstallWizard::closeEvent
581  *  Close event handler
582  */
583 // ================================================================
584 void SALOME_InstallWizard::closeEvent( QCloseEvent* ce )
585 {
586   if ( WarnDialog::isWarnDlgShown() ) {
587     ce->ignore();
588     return;
589   }
590   if ( !exitConfirmed ) {
591     if ( QMessageBox::information( this, 
592                                    tr( "Exit" ), 
593                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
594                                    tr( "&Yes" ), 
595                                    tr( "&No" ),
596                                    QString::null,
597                                    0,
598                                    1 ) == 1 ) {
599       ce->ignore();
600     }
601     else {
602       ce->accept();
603       exitConfirmed = true;
604       reject();
605     }
606   }
607 }
608 // ================================================================
609 /*!
610  *  SALOME_InstallWizard::setupIntroPage
611  *  Creates introduction page
612  */
613 // ================================================================
614 void SALOME_InstallWizard::setupIntroPage()
615 {
616   // create page
617   introPage = new QWidget( this, "IntroPage" );
618   QGridLayout* pageLayout = new QGridLayout( introPage ); 
619   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
620   // create logo picture
621   logoLab = new QLabel( introPage );
622   logoLab->setPixmap( pixmap( pxBigLogo ) );
623   logoLab->setScaledContents( false );
624   logoLab->setFrameStyle( QLabel::Plain | QLabel::NoFrame );
625   logoLab->setAlignment( AlignCenter );
626   // create version box
627   QVBox* versionBox = new QVBox( introPage ); versionBox->setSpacing( 6 );
628   versionBox->setFrameStyle( QVBox::Panel | QVBox::Sunken );
629   QWidget* stretch1 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch1, 5 );
630   versionLab = new QLabel( QString("%1 %2").arg( tr( "Version" ) ).arg(myVersion), versionBox );
631   versionLab->setAlignment( AlignCenter );
632   copyrightLab = new QLabel( myCopyright, versionBox );
633   copyrightLab->setAlignment( AlignCenter );
634   licenseLab = new QLabel( myLicense, versionBox );
635   licenseLab->setAlignment( AlignCenter );
636   QWidget* stretch2 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch2, 5 );
637   // create info box
638   info = new QLabel( introPage );
639   info->setText( tr( "This program will install <b>%1</b>."
640                      "<br><br>The wizard will also help you to install all products "
641                      "which are necessary for <b>%2</b> and setup "
642                      "your environment.<br><br>Click <code>Cancel</code> button to abort "
643                      "installation and quit. Click <code>Next</code> button to continue with the "
644                      "installation program." ).arg( myCaption ).arg( myCaption ) );
645   info->setFrameStyle( QLabel::WinPanel | QLabel::Sunken );
646   info->setMargin( 6 );
647   info->setAlignment( WordBreak );
648   info->setMinimumWidth( 250 );
649   QPalette pal = info->palette();
650   pal.setColor( QColorGroup::Background, QApplication::palette().active().base() );
651   info->setPalette( pal );
652   info->setLineWidth( 2 );
653   // layouting
654   pageLayout->addWidget( logoLab, 0, 0 );
655   pageLayout->addWidget( versionBox, 1, 0 );
656   pageLayout->addMultiCellWidget( info, 0, 1, 1, 1 );
657   pageLayout->setColStretch( 1, 5 );
658   pageLayout->setRowStretch( 1, 5 );
659   // adding page
660   addPage( introPage, tr( "Introduction" ) );
661 }
662 // ================================================================
663 /*!
664  *  SALOME_InstallWizard::setupProductsPage
665  *  Creates products page
666  */
667 // ================================================================
668 void SALOME_InstallWizard::setupProductsPage()
669 {
670   // create page
671   productsPage = new QWidget( this, "ProductsPage" );
672   QGridLayout* pageLayout = new QGridLayout( productsPage ); 
673   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
674   // target directory
675   QLabel* targetLab = new QLabel( tr( "Type the target directory:" ), productsPage );
676   targetFolder = new QLineEdit( productsPage );
677   QWhatsThis::add( targetFolder, tr( "Enter target root directory where products will be installed" ) );
678   QToolTip::add  ( targetFolder, tr( "Enter target root directory where products will be installed" ) );
679   targetBtn = new QPushButton( tr( "Browse..." ), productsPage );
680   QWhatsThis::add( targetBtn, tr( "Click this to browse target directory" ) );
681   QToolTip::add  ( targetBtn, tr( "Click this to browse target directory" ) );
682   // create advanced mode widgets container
683   moreBox = new QWidget( productsPage );
684   QGridLayout* moreBoxLayout = new QGridLayout( moreBox );
685   moreBoxLayout->setMargin( 0 ); moreBoxLayout->setSpacing( 6 );
686   // temp directory
687   QLabel* tempLab = new QLabel( tr( "Type the directory for the temporary files:" ), moreBox );
688   tempFolder = new QLineEdit( moreBox );
689   //  tempFolder->setText( "/tmp" ); // default is /tmp directory
690   QWhatsThis::add( tempFolder, tr( "Enter directory where to put temporary files" ) );
691   QToolTip::add  ( tempFolder, tr( "Enter directory where to put temporary files" ) );
692   tempBtn = new QPushButton( tr( "Browse..." ), moreBox );
693   tempBtn->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
694   QWhatsThis::add( tempBtn, tr( "Click this to browse temporary directory" ) );
695   QToolTip::add  ( tempBtn, tr( "Click this to browse temporary directory" ) );
696   // create products list
697   productsView = new ProductsView( moreBox );
698   productsView->setMinimumSize( 250, 180 );
699   QWhatsThis::add( productsView, tr( "This view lists the products you wish to be installed" ) );
700   QToolTip::add  ( productsView, tr( "This view lists the products you wish to be installed" ) );
701   // products info box
702   productsInfo = new QTextBrowser( moreBox );
703   productsInfo->setMinimumSize( 270, 135 );
704   QWhatsThis::add( productsInfo, tr( "Shows info about the product: required disk space and prerequisites" ) );
705   QToolTip::add  ( productsInfo, tr( "Shows info about the product: required disk space and prerequisites" ) );
706   // disk space labels
707   QLabel* reqLab1 = new QLabel( tr( "Total disk space required:" ), moreBox );
708   QWhatsThis::add( reqLab1, tr( "Shows total disk space required for installing selected products" ) );
709   QToolTip::add  ( reqLab1, tr( "Shows total disk space required for installing selected products" ) );
710   requiredSize = new QLabel( moreBox );
711   requiredSize->setMinimumWidth( 100 );
712   QWhatsThis::add( requiredSize, tr( "Shows total disk space required for installing selected products" ) );
713   QToolTip::add  ( requiredSize, tr( "Shows total disk space required for installing selected products" ) );
714   QLabel* reqLab2 = new QLabel( tr( "Space for temporary files:" ), moreBox );
715   QWhatsThis::add( reqLab2, tr( "Shows additional disk space which is required for temporary files" ) );
716   QToolTip::add  ( reqLab2, tr( "Shows additional disk space which is required for temporary files" ) );
717   requiredTemp = new QLabel( moreBox );
718   requiredTemp->setMinimumWidth( 100 );
719   QWhatsThis::add( requiredTemp, tr( "Shows additional disk space which is required for temporary files" ) );
720   QToolTip::add  ( requiredTemp, tr( "Shows additional disk space which is required for temporary files" ) );
721   QFont fnt = reqLab1->font();
722   fnt.setBold( true );
723   reqLab1->setFont( fnt );
724   requiredSize->setFont( fnt );
725   reqLab2->setFont( fnt );
726   requiredTemp->setFont( fnt );
727   QGridLayout* sizeLayout = new QGridLayout; sizeLayout->setMargin( 0 ); sizeLayout->setSpacing( 6 );
728   sizeLayout->addWidget( reqLab1,      0, 0 );
729   sizeLayout->addWidget( requiredSize, 0, 1 );
730   sizeLayout->addWidget( reqLab2,      1, 0 );
731   sizeLayout->addWidget( requiredTemp, 1, 1 );
732   // prerequisites checkbox
733   prerequisites = new QCheckBox( tr( "Auto set prerequisites products" ), moreBox );
734   prerequisites->setChecked( true );
735   QWhatsThis::add( prerequisites, tr( "Check this if you want prerequisites products to be set on automatically" ) );
736   QToolTip::add  ( prerequisites, tr( "Check this if you want prerequisites products to be set on automatically" ) );
737   // <Unselect All> button
738   unselectBtn  = new QPushButton( tr( "&Unselect All" ), moreBox );
739   QWhatsThis::add( unselectBtn, tr( "Unselects all products" ) );
740   QToolTip::add  ( unselectBtn, tr( "Unselects all products" ) );
741   // <SALOME sources> / <SALOME binaries> tri-state checkboxes
742   selectSrcBtn  = new QMyCheckBox( tr( "SALOME sources" ), moreBox );
743   selectSrcBtn->setTristate( true );
744   QWhatsThis::add( selectSrcBtn, tr( "Selects/unselects SALOME sources" ) );
745   QToolTip::add  ( selectSrcBtn, tr( "Selects/unselects SALOME sources" ) );
746   selectBinBtn  = new QMyCheckBox( tr( "SALOME binaries" ), moreBox );
747   selectBinBtn->setTristate( true );
748   QWhatsThis::add( selectBinBtn, tr( "Selects/unselects SALOME binaries" ) );
749   QToolTip::add  ( selectBinBtn, tr( "Selects/unselects SALOME binaries" ) );
750   QVBoxLayout* btnLayout = new QVBoxLayout; btnLayout->setMargin( 0 ); btnLayout->setSpacing( 6 );
751   btnLayout->addWidget( unselectBtn );
752   btnLayout->addWidget( selectSrcBtn );
753   btnLayout->addWidget( selectBinBtn );
754   // layouting advancet mode widgets
755   moreBoxLayout->addMultiCellWidget( tempLab,      0, 0, 0, 2 );
756   moreBoxLayout->addMultiCellWidget( tempFolder,   1, 1, 0, 1 );
757   moreBoxLayout->addWidget         ( tempBtn,      1,    2    );
758   moreBoxLayout->addMultiCellWidget( productsView, 2, 5, 0, 0 );
759   moreBoxLayout->addMultiCellWidget( productsInfo, 2, 2, 1, 2 );
760   moreBoxLayout->addMultiCellWidget( prerequisites,3, 3, 1, 2 );
761   moreBoxLayout->addMultiCellLayout( btnLayout,    4, 4, 1, 2 );
762   moreBoxLayout->addMultiCellLayout( sizeLayout,   5, 5, 1, 2 );
763   // <More...> button
764   moreBtn = new QPushButton( tr( "More..." ), productsPage );
765   // layouting
766   pageLayout->addMultiCellWidget( targetLab,    0, 0, 0, 1 );
767   pageLayout->addWidget         ( targetFolder, 1,    0    );
768   pageLayout->addWidget         ( targetBtn,    1,    1    );
769   pageLayout->addMultiCellWidget( moreBox,      2, 2, 0, 1 );
770   pageLayout->addWidget         ( moreBtn,      3,    1    );
771   pageLayout->setRowStretch( 2, 5 );
772   //pageLayout->addRowSpacing( 6, 10 );
773   // xml reader
774   QFile xmlfile(xmlFileName);
775   if ( xmlfile.exists() ) {
776     QXmlInputSource source( &xmlfile );
777     QXmlSimpleReader reader;
778
779     StructureParser* handler = new StructureParser( this );
780     handler->setProductsList(productsView);
781     handler->setTargetDir(targetFolder);
782     handler->setTempDir(tempFolder);
783     reader.setContentHandler( handler );
784     reader.parse( source );  
785   }
786   // take into account command line parameters
787   if ( !targetDirPath.isEmpty() )
788     targetFolder->setText( targetDirPath );
789   if ( !tmpDirPath.isEmpty() )
790     tempFolder->setText( tmpDirPath );
791
792   // set first item to be selected
793   if ( productsView->childCount() > 0 ) {
794     productsView->setSelected( productsView->firstChild(), true );
795     onSelectionChanged();
796   }
797   // adding page
798   addPage( productsPage, tr( "Installation settings" ) );
799   // connecting signals
800   connect( productsView, SIGNAL( selectionChanged() ), 
801                                               this, SLOT( onSelectionChanged() ) );
802   connect( productsView, SIGNAL( itemToggled( QCheckListItem* ) ), 
803                                               this, SLOT( onItemToggled( QCheckListItem* ) ) );
804   connect( unselectBtn,  SIGNAL( clicked() ), this, SLOT( onProdBtn() ) );
805   connect( selectSrcBtn, SIGNAL( stateChanged(int) ), 
806                                               this, SLOT( onProdBtn() ) );
807   connect( selectBinBtn, SIGNAL( stateChanged(int) ), 
808                                               this, SLOT( onProdBtn() ) );
809   // connecting signals
810   connect( targetFolder, SIGNAL( textChanged( const QString& ) ),
811                                               this, SLOT( directoryChanged( const QString& ) ) );
812   connect( targetBtn,    SIGNAL( clicked() ), this, SLOT( browseDirectory() ) );
813   connect( tempFolder,   SIGNAL( textChanged( const QString& ) ),
814                                               this, SLOT( directoryChanged( const QString& ) ) );
815   connect( tempBtn,      SIGNAL( clicked() ), this, SLOT( browseDirectory() ) );
816   connect( moreBtn,      SIGNAL( clicked() ), this, SLOT( onMoreBtn() ) );
817   // start on default - non-advanced - mode
818   moreBox->hide();
819 }
820 // ================================================================
821 /*!
822  *  SALOME_InstallWizard::setupCheckPage
823  *  Creates prestart page
824  */
825 // ================================================================
826 void SALOME_InstallWizard::setupCheckPage()
827 {
828   // create page
829   prestartPage = new QWidget( this, "PrestartPage" );
830   QVBoxLayout* pageLayout = new QVBoxLayout( prestartPage ); 
831   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
832   // choice text view
833   choices = new QTextEdit( prestartPage );
834   choices->setReadOnly( true );
835   choices->setTextFormat( RichText );
836   choices->setUndoRedoEnabled ( false );
837   QWhatsThis::add( choices, tr( "Displays information about installation settings you made" ) );
838   QToolTip::add  ( choices, tr( "Displays information about installation settings you made" ) );
839   QPalette pal = choices->palette();
840   pal.setColor( QColorGroup::Base, QApplication::palette().active().background() );
841   choices->setPalette( pal );
842   choices->setMinimumHeight( 10 );
843   // layouting
844   pageLayout->addWidget( choices );
845   pageLayout->setStretchFactor( choices, 5 );
846   // adding page
847   addPage( prestartPage, tr( "Check your choice" ) );
848 }
849 // ================================================================
850 /*!
851  *  SALOME_InstallWizard::setupProgressPage
852  *  Creates progress page
853  */
854 // ================================================================
855 void SALOME_InstallWizard::setupProgressPage()
856 {
857   // create page
858   progressPage = new QWidget( this, "progressPage" );
859   QGridLayout* pageLayout = new QGridLayout( progressPage ); 
860   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
861   // top splitter
862   splitter = new QSplitter( Vertical, progressPage );
863   splitter->setOpaqueResize( true );
864   // the parent for the widgets
865   QWidget* widget = new QWidget( splitter );
866   QGridLayout* layout = new QGridLayout( widget ); 
867   layout->setMargin( 0 ); layout->setSpacing( 6 );
868   // installation progress view box
869   installInfo = new InstallInfo( widget );
870   installInfo->setReadOnly( true );
871   installInfo->setTextFormat( RichText );
872   installInfo->setUndoRedoEnabled ( false );
873   installInfo->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
874   installInfo->setMinimumSize( 100, 10 );
875   QWhatsThis::add( installInfo, tr( "Displays installation process" ) );
876   QToolTip::add  ( installInfo, tr( "Displays installation process" ) );
877   // parameters for the script
878   parametersLab = new QLabel( tr( "Enter your answer here:" ), widget );
879   passedParams = new QLineEdit ( widget );
880   QWhatsThis::add( passedParams, tr( "Use this field to enter answer for the running script when it is necessary") );
881   QToolTip::add  ( passedParams, tr( "Use this field to enter answer for the running script when it is necessary") );
882   // VSR: 10/11/05 - disable answer mode ==>
883   parametersLab->hide();
884   passedParams->hide();
885   // VSR: 10/11/05 - disable answer mode <==
886   // layouting
887   layout->addWidget( installInfo,   0, 0 );
888   layout->addWidget( parametersLab, 1, 0 );
889   layout->addWidget( passedParams,  2, 0 );
890   layout->addRowSpacing( 3, 6 );
891   // the parent for the widgets
892   widget = new QWidget( splitter );
893   layout = new QGridLayout( widget ); 
894   layout->setMargin( 0 ); layout->setSpacing( 6 );
895   // installation results view box
896   QLabel* resultLab = new QLabel( tr( "Installation Status:" ), widget );
897   progressView = new ProgressView( widget );
898   progressView->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
899   progressView->setMinimumSize( 100, 10 );
900   QWhatsThis::add( progressView, tr( "Displays installation status" ) );
901   QToolTip::add  ( progressView, tr( "Displays installation status" ) );
902   // layouting
903   layout->addRowSpacing( 0, 6 );
904   layout->addWidget( resultLab,    1, 0 );
905   layout->addWidget( progressView, 2, 0 );
906   // layouting
907   pageLayout->addWidget( splitter, 0, 0 );
908   // adding page
909   addPage( progressPage, tr( "Installation progress" ) );
910   // connect signals
911   connect( passedParams, SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) ) ;
912 }
913 // ================================================================
914 /*!
915  *  SALOME_InstallWizard::setupReadmePage
916  *  Creates readme page
917  */
918 // ================================================================
919 void SALOME_InstallWizard::setupReadmePage()
920 {
921   // create page
922   readmePage = new QWidget( this, "ReadmePage" );
923   QVBoxLayout* pageLayout = new QVBoxLayout( readmePage ); 
924   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
925   // README info text box
926   readme = new QTextEdit( readmePage );
927   readme->setReadOnly( true );
928   readme->setTextFormat( PlainText );
929   readme->setFont( QFont( "Fixed", 12 ) );
930   readme->setUndoRedoEnabled ( false );
931   QWhatsThis::add( readme, tr( "Displays README information" ) );
932   QToolTip::add  ( readme, tr( "Displays README information" ) );
933   QPalette pal = readme->palette();
934   pal.setColor( QColorGroup::Base, QApplication::palette().active().background() );
935   readme->setPalette( pal );
936   readme->setMinimumHeight( 10 );
937   // <Launch SALOME> button
938   runSalomeBtn = new QPushButton( tr( "Launch SALOME" ), readmePage );
939   QWhatsThis::add( runSalomeBtn, tr( "Click this button to run SALOME desktop" ) );
940   QToolTip::add  ( runSalomeBtn, tr( "Click this button to run SALOME desktop" ) );
941   QHBoxLayout* hLayout = new QHBoxLayout;
942   hLayout->addWidget( runSalomeBtn ); hLayout->addStretch();
943   // layouting
944   pageLayout->addWidget( readme );
945   pageLayout->setStretchFactor( readme, 5 );
946   pageLayout->addLayout( hLayout );
947   // connecting signals
948   connect( runSalomeBtn, SIGNAL( clicked() ), this, SLOT( onLaunchSalome() ) );
949   // loading README file
950   QString readmeFile = QDir::currentDirPath() + "/README";
951   QString text;
952   if ( readFile( readmeFile, text ) )
953     readme->setText( text );
954   else
955     readme->setText( tr( "README file has not been found" ) );
956   // adding page
957   addPage( readmePage, tr( "Finish installation" ) );
958 }
959 // ================================================================
960 /*!
961  *  SALOME_InstallWizard::showChoiceInfo
962  *  Displays choice info
963  */
964 // ================================================================
965 void SALOME_InstallWizard::showChoiceInfo()
966 {
967   choices->clear();
968
969   long totSize, tempSize;
970   checkSize( &totSize, &tempSize );
971   int nbProd = 0;
972   QString text;
973
974   if ( !xmlFileName.isEmpty() ) {
975     text += tr( "Configuration file" )+ ": <b>" + xmlFileName + "</b><br>";
976     text += "<br>";
977   }
978   if ( !myOS.isEmpty() ) {
979     text += tr( "Reference Linux platform" ) + ": <b>" + myOS + "</b><br>";
980     text += "<br>";
981   }
982   text += tr( "Native products to be used" ) + ":<ul>";
983   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
984   while( item ) {
985     if ( productsMap.contains( item ) ) {
986       if ( item->childCount() > 0 ) {
987         if ( productsView->isNative( item ) ) {
988           text += "<li><b>" + item->text() + "</b><br>";
989           nbProd++;
990         }
991       }
992     }
993     item = (QCheckListItem*)( item->nextSibling() );
994   }
995   if ( nbProd == 0 ) {
996     text += "<li><b>" + tr( "none" ) + "</b><br>";
997   }
998   text += "</ul>";
999   nbProd = 0;
1000   text += tr( "Products to be installed" ) + ":<ul>";
1001   item = (QCheckListItem*)( productsView->firstChild() );
1002   while( item ) {
1003     if ( productsMap.contains( item ) ) {
1004       if ( item->childCount() > 0 ) {
1005         if ( productsView->isBinaries( item ) ) {
1006           text += "<li><b>" + item->text() + " " + item->text(1) + "</b> " + tr( "as binaries" ) + "<br>";
1007           nbProd++;
1008         }
1009         else if ( productsView->isSources( item ) ) {
1010           text+= "<li><b>" + item->text() + " " + item->text(1) + "</b> " + tr( "as sources" ) + "<br>";
1011           nbProd++;
1012         }
1013       }
1014       else if ( item->isOn() ) {
1015         text+= "<li><b>" + item->text() + "</b><br>";
1016         nbProd++;
1017       }
1018     }
1019     item = (QCheckListItem*)( item->nextSibling() );
1020   }
1021   if ( nbProd == 0 ) {
1022     text += "<li><b>" + tr( "none" ) + "</b><br>";
1023   }
1024   text += "</ul>";
1025   text += tr( "Total disk space required:" ) + " <b>" + QString::number( totSize ) + " Kb</b><br>" ;
1026   text += tr( "Space for temporary files required:" ) + " <b>" + QString::number( tempSize ) + " Kb</b><br>" ;
1027   text += "<br>";
1028   text += tr( "Target directory:" ) + " <b>" + QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) + "</b><br>";
1029   // VSR: Temporary folder is used always now and it is not necessary to disable it -->
1030   // if ( tempSize > 0 )
1031   // VSR: <----------------------------------------------------------------------------
1032   text += tr( "Temporary directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
1033   text += "<br>";
1034   choices->setText( text );
1035 }
1036 // ================================================================
1037 /*!
1038  *  SALOME_InstallWizard::acceptData
1039  *  Validates page when <Next> button is clicked
1040  */
1041 // ================================================================
1042 bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
1043 {
1044   QString tmpstr;
1045   QWidget* aPage = InstallWizard::page( pageTitle );
1046   if ( aPage == productsPage ) {
1047     // ########## check if any products are selected to be installed
1048     long totSize, tempSize;
1049     bool anySelected = checkSize( &totSize, &tempSize );
1050     if ( !anySelected ) {
1051       QMessageBox::warning( this, 
1052                             tr( "Warning" ), 
1053                             tr( "Select one or more products to install" ), 
1054                             QMessageBox::Ok, 
1055                             QMessageBox::NoButton,
1056                             QMessageBox::NoButton );
1057       return false;
1058     }
1059     // ########## check target and temp directories (existence and available disk space)
1060     // get dirs
1061     QString targetDir = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1062     QString tempDir   = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() );
1063     // directories should differ
1064 //    if (!targetDir.isEmpty() && tempDir == targetDir) {
1065 //      QMessageBox::warning( this, 
1066 //                          tr( "Warning" ), 
1067 //                          tr( "Target and temporary directories must be different"), 
1068 //                          QMessageBox::Ok, 
1069 //                          QMessageBox::NoButton, 
1070 //                          QMessageBox::NoButton );
1071 //      return false;
1072 //    }
1073     // check target directory
1074     if ( targetDir.isEmpty() ) {
1075       QMessageBox::warning( this, 
1076                             tr( "Warning" ), 
1077                             tr( "Please, enter valid target directory path" ), 
1078                             QMessageBox::Ok, 
1079                             QMessageBox::NoButton,
1080                             QMessageBox::NoButton );
1081       return false;
1082     }
1083     QFileInfo fi( QDir::cleanDirPath( targetDir ) );
1084     if ( !fi.exists() ) {
1085       bool toCreate = 
1086         QMessageBox::warning( this, 
1087                               tr( "Warning" ), 
1088                               tr( "The directory %1 doesn't exist.\n"
1089                                   "Create directory?" ).arg( fi.absFilePath() ), 
1090                               QMessageBox::Yes, 
1091                               QMessageBox::No,
1092                               QMessageBox::NoButton ) == QMessageBox::Yes;
1093       if ( !toCreate) 
1094         return false;
1095       if ( !makeDir( fi.absFilePath(), tmpstr ) ) {
1096         QMessageBox::critical( this, 
1097                                tr( "Error" ), 
1098                                tr( "Can't create the directory\n%1").arg( fi.absFilePath() ), 
1099                                QMessageBox::Ok, 
1100                                QMessageBox::NoButton, 
1101                                QMessageBox::NoButton );
1102         return false;
1103       }
1104     }
1105     if ( !fi.isDir() ) {
1106       QMessageBox::warning( this, 
1107                             tr( "Warning" ), 
1108                             tr( "%1 is not a directory.\n"
1109                                 "Please, enter valid target directory path" ).arg( fi.absFilePath() ), 
1110                             QMessageBox::Ok, 
1111                             QMessageBox::NoButton,
1112                             QMessageBox::NoButton );
1113       return false;
1114     }
1115     if ( !fi.isWritable() ) {
1116       QMessageBox::warning( this, 
1117                             tr( "Warning" ), 
1118                             tr( "The directory %1 is not writeable.\n"
1119                                 "Please, enter valid target directory path or change permissions" ).arg( fi.absFilePath() ), 
1120                             QMessageBox::Ok, 
1121                             QMessageBox::NoButton,
1122                             QMessageBox::NoButton );
1123       return false;
1124     }
1125     if ( hasSpace( fi.absFilePath() ) &&
1126          QMessageBox::warning( this,
1127                                tr( "Warning" ),
1128                                tr( "The target directory contains space symbols.\n"
1129                                    "This may cause problems with compiling or installing of products.\n\n"
1130                                    "Do you want to continue?"),
1131                                QMessageBox::Yes,
1132                                QMessageBox::No,
1133                                QMessageBox::NoButton ) == QMessageBox::No ) {
1134       return false;
1135     }
1136     QString binDir = "./Products/BINARIES";
1137     if ( !myOS.isEmpty() )
1138       binDir += "/" + myOS;
1139     QFileInfo fib( QDir::cleanDirPath( binDir ) );
1140     if ( !fib.exists() ) {
1141       QMessageBox::warning( this, 
1142                             tr( "Warning" ), 
1143                             tr( "The directory %1 doesn't exist.\n"
1144                                 "This directory must contain binaries archives." ).arg( fib.absFilePath() ));
1145     }
1146     // run script that checks available disk space for installing of products    // returns 1 in case of error
1147     QString script = "./config_files/checkSize.sh '";
1148     script += fi.absFilePath();
1149     script += "' ";
1150     script += QString( "%1" ).arg( totSize );
1151     ___MESSAGE___( "script = " << script );
1152     if ( system( script ) ) {
1153       QMessageBox::critical( this, 
1154                              tr( "Out of space" ), 
1155                              tr( "There is no available disk space for installing of selected products" ), 
1156                              QMessageBox::Ok, 
1157                              QMessageBox::NoButton, 
1158                              QMessageBox::NoButton );
1159       return false;
1160     }
1161     // check temp directory
1162     if ( tempDir.isEmpty() ) {
1163       if ( moreMode ) {
1164         QMessageBox::warning( this, 
1165                               tr( "Warning" ), 
1166                               tr( "Please, enter valid temporary directory path" ), 
1167                               QMessageBox::Ok, 
1168                               QMessageBox::NoButton,
1169                               QMessageBox::NoButton );
1170         return false; 
1171       }
1172       else {
1173         tempDir = "/tmp";
1174         tempFolder->setText( tempDir );
1175       }
1176     }
1177     QFileInfo fit( QDir::cleanDirPath( tempDir ) );
1178     if ( !makeDir( fit.absFilePath() + TEMPDIRNAME, tmpCreated ) ) {
1179       QMessageBox::critical( this, 
1180                              tr( "Error" ), 
1181                              tr( "Can't use temporary directory.\nCheck permissions for the %1 directory.").arg( fit.absFilePath() ), 
1182                              QMessageBox::Ok, 
1183                              QMessageBox::NoButton, 
1184                              QMessageBox::NoButton );
1185       return false;
1186     }
1187     // run script that check available disk space for temporary files
1188     // returns 1 in case of error
1189     QString tscript = "./config_files/checkSize.sh '";
1190     tscript += fit.absFilePath();
1191     tscript += "' ";
1192     tscript += QString( "%1" ).arg( tempSize );
1193     ___MESSAGE___( "script = " << tscript );
1194     if ( system( tscript ) ) {
1195       QMessageBox::critical( this, 
1196                              tr( "Out of space" ), 
1197                              tr( "There is no available disk space for the temporary files" ), 
1198                              QMessageBox::Ok, 
1199                              QMessageBox::NoButton, 
1200                              QMessageBox::NoButton );
1201       return false;
1202     }
1203 // VSR: <------------------------------------------------------------------------------
1204     // ########## check native products
1205     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1206     QStringList natives;
1207     while( item ) {
1208       if ( productsMap.contains( item ) ) {
1209         if ( item->childCount() > 0 ) {
1210           // VSR : 29/01/05 : Check installation script even if product is not being installed
1211           //      if ( !productsView->isNone( item ) ) {
1212             if ( item->text(2).isEmpty() || item->text(2).isNull() ) {
1213               QMessageBox::warning( this, 
1214                                     tr( "Error" ), 
1215                                     tr( "The installation script for %1 is not defined.").arg(item->text(0)), 
1216                                     QMessageBox::Ok, 
1217                                     QMessageBox::NoButton, 
1218                                     QMessageBox::NoButton );
1219               if ( !moreMode )
1220                 onMoreBtn();
1221               productsView->setCurrentItem( item );
1222               productsView->setSelected( item, true );
1223               productsView->ensureItemVisible( item );
1224               //productsView->setNone( item );
1225               return false;
1226             } else {
1227               QFileInfo fi( QString("./config_files/") + item->text(2) );
1228               if ( !fi.exists() || !fi.isExecutable() ) {
1229                 QMessageBox::warning( this, 
1230                                       tr( "Error" ),  
1231                                       tr( "The script %1 required for %2 doesn't exist or doesn't have execute permissions.").arg("./config_files/" + item->text(2)).arg(item->text(0)),  
1232                                       QMessageBox::Ok, 
1233                                       QMessageBox::NoButton, 
1234                                       QMessageBox::NoButton );
1235                 if ( !moreMode )
1236                   onMoreBtn();
1237                 productsView->setCurrentItem( item );
1238                 productsView->setSelected( item, true );
1239                 productsView->ensureItemVisible( item );
1240                 //productsView->setNone( item );
1241                 return false;
1242               }       
1243             }
1244             //    }
1245           // collect native products
1246           if ( productsView->isNative( item ) ) {
1247             if ( natives.find( item->text(0) ) == natives.end() )
1248               natives.append( item->text(0) );
1249           } 
1250           else if ( productsView->isBinaries( item ) || productsView->isSources( item ) ) {
1251             QStringList dependOn = productsMap[ item ].getDependancies();
1252             for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1253               QCheckListItem* depitem = findItem( dependOn[ i ] );
1254               if ( depitem ) {
1255                 if ( productsView->isNative( depitem ) && natives.find( depitem->text(0) ) == natives.end() )
1256                   natives.append( depitem->text(0) );
1257               } 
1258               else {
1259                 QMessageBox::warning( this, 
1260                                       tr( "Error" ), 
1261                                       tr( "%1 is required for %2 %3 installation.\n"
1262                                           "This product is missing in the configuration file %4.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)).arg(xmlFileName), 
1263                                       QMessageBox::Ok, 
1264                                       QMessageBox::NoButton, 
1265                                       QMessageBox::NoButton );
1266                 return false;
1267               }
1268             }
1269           }
1270         }
1271       }
1272       item = (QCheckListItem*)( item->nextSibling() );
1273     }
1274     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1275     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1276     myThread->clearCommands();
1277     if ( natives.count() > 0 ) {
1278       for ( unsigned i = 0; i < natives.count(); i++ ) {
1279         item = findItem( natives[ i ] );
1280         if ( item ) {
1281           QString dependOn = productsMap[ item ].getDependancies().join(" ");
1282           QString script = "cd ./config_files/;" + item->text(2) + " try_native " +
1283                   QFileInfo( tmpFolder ).absFilePath() + " " + QDir::currentDirPath() + "/Products " + QFileInfo( tgtFolder ).absFilePath() + " " +
1284                   QUOTE(dependOn) + " " + item->text(0);
1285
1286           myThread->addCommand( item, script );
1287         }
1288         else {
1289           QMessageBox::warning( this, 
1290                                 tr( "Warning" ), 
1291                                 tr( "%The product %1 %2 required for installation.\n"
1292                                     "This product is missing in the configuration file %4.").arg(item->text(0)).arg(item->text(1)).arg(xmlFileName),
1293                                 QMessageBox::Ok, 
1294                                 QMessageBox::NoButton, 
1295                                 QMessageBox::NoButton );
1296           return false;
1297         }
1298       }
1299       WarnDialog::showWarnDlg( this, true );
1300       myThread->start();
1301       return true; // return in order to avoid default postValidateEvent() action
1302     }
1303   }
1304   return InstallWizard::acceptData( pageTitle );
1305 }
1306 // ================================================================
1307 /*!
1308  *  SALOME_InstallWizard::checkSize
1309  *  Calculates disk space required for the installation
1310  */
1311 // ================================================================
1312 bool SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
1313 {
1314   long tots = 0, temps = 0;
1315   int nbSelected = 0;
1316
1317   MapProducts::Iterator mapIter;
1318   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1319     QCheckListItem* item = mapIter.key();
1320     Dependancies dep = mapIter.data();
1321     if ( productsView->isBinaries( item ) ) {
1322       tots += dep.getSize();
1323     }
1324     else if ( productsView->isSources( item ) ) {
1325       tots += dep.getSize(true);
1326       temps = max( temps, dep.getTempSize() );
1327     }
1328     if ( !productsView->isNone( item ) )
1329       nbSelected++;
1330   }
1331  
1332   if ( totSize )
1333     *totSize = tots;
1334   if ( tempSize )
1335     *tempSize = temps;
1336   return ( nbSelected > 0 );
1337 }
1338 // ================================================================
1339 /*!
1340  *  SALOME_InstallWizard::checkProductPage
1341  *  Checks products page validity (directories and products selection) and
1342  *  enabled/disables "Next" button for the Products page
1343  */
1344 // ================================================================
1345 void SALOME_InstallWizard::checkProductPage()
1346 {
1347   long tots = 0, temps = 0;
1348
1349   // check if any product is selected;
1350   bool isAnyProductSelected = checkSize( &tots, &temps );
1351   // check if target directory is valid
1352   bool isTargetDirValid = !targetFolder->text().stripWhiteSpace().isEmpty();
1353   // check if temp directory is valid
1354   bool isTempDirValid = !moreMode || !tempFolder->text().stripWhiteSpace().isEmpty();
1355
1356   // update required size information
1357   requiredSize->setText( QString::number( tots )  + " Kb");
1358   requiredTemp->setText( QString::number( temps ) + " Kb");
1359   
1360   // update <SALOME sources>, <SALOME binaries> check boxes state
1361   int totSrc = 0, selSrc = 0;
1362   int totBin = 0, selBin = 0;
1363   MapProducts::Iterator itProd;
1364   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1365     bool srcctx = itProd.data().hasContext( "salome sources" );
1366     bool binctx = itProd.data().hasContext( "salome binaries" );
1367     if ( srcctx && !binctx ) {
1368       totSrc++;
1369       if ( productsView->isSources( itProd.key() ) )
1370         selSrc++;
1371     }
1372     if ( binctx && !srcctx ) {
1373       totBin++;
1374       if ( productsView->isBinaries( itProd.key() ) )
1375         selBin++;
1376     }
1377   }
1378   selectSrcBtn->blockSignals( true );
1379   selectBinBtn->blockSignals( true );
1380   selectSrcBtn->setState( selSrc == 0 ? QButton::Off : ( selSrc == totSrc ? QButton::On : QButton::NoChange  ) );
1381   selectBinBtn->setState( selBin == 0 ? QButton::Off : ( selBin == totBin ? QButton::On : QButton::NoChange  ) );
1382   selectSrcBtn->blockSignals( false );
1383   selectBinBtn->blockSignals( false );
1384
1385   // enable/disable "Next" button
1386   setNextEnabled( productsPage, isAnyProductSelected && isTargetDirValid && isTempDirValid );
1387 }
1388 // ================================================================
1389 /*!
1390  *  SALOME_InstallWizard::setPrerequisites
1391  *  Sets the product and all products this one depends on to be checked ( recursively )
1392  */
1393 // ================================================================
1394 void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
1395 {
1396   if ( !productsMap.contains( item ) )
1397     return;
1398   if ( productsView->isNone( item ) )
1399     return;
1400   // get all prerequisites
1401   QStringList dependOn = productsMap[ item ].getDependancies();
1402   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1403     MapProducts::Iterator itProd;
1404     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1405       if ( itProd.data().getName() == dependOn[ i ] ) {
1406         if ( productsView->isNone( itProd.key() ) ) {
1407           QString defMode = itProd.data().getDefault();
1408           if ( defMode.isEmpty() )
1409             defMode = tr( "install binaries" );
1410           if ( defMode == tr( "install binaries" ) )
1411             productsView->setBinaries( itProd.key() );
1412           else if ( defMode == tr( "install sources" ) )
1413             productsView->setSources( itProd.key() );
1414           else if ( defMode == tr( "use native" ) )
1415             productsView->setNative( itProd.key() );
1416           setPrerequisites( itProd.key() );
1417         }
1418       }
1419     }
1420   }
1421 }
1422 // ================================================================
1423 /*!
1424  *  SALOME_InstallWizard::launchScript
1425  *  Runs installation script
1426  */
1427 // ================================================================
1428 void SALOME_InstallWizard::launchScript()
1429 {
1430   // try to find product being processed now
1431   QString prodProc = progressView->findStatus( Processing );
1432   if ( !prodProc.isNull() ) {
1433     ___MESSAGE___( "Found <Processing>: " );
1434
1435     // if found - set status to "completed"
1436     progressView->setStatus( prodProc, Completed );
1437     // ... and call this method again
1438     launchScript();
1439     return;
1440   }
1441   // else try to find next product which is not processed yet
1442   prodProc = progressView->findStatus( Waiting );
1443   if ( !prodProc.isNull() ) {
1444     ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
1445     // if found - set status to "processed" and run script
1446     progressView->setStatus( prodProc, Processing );
1447     progressView->ensureVisible( prodProc );
1448
1449     QCheckListItem* item = findItem( prodProc );
1450     // fill in script parameters
1451     shellProcess->clearArguments();
1452     // ... script name
1453     shellProcess->setWorkingDirectory( QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() ) );
1454     shellProcess->addArgument( item->text(2) );
1455
1456     // ... temp folder
1457     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1458     //if( !tempFolder->isEnabled() )
1459     //tmpFolder = "/tmp";
1460
1461     // ... binaries ?
1462     if ( productsView->isBinaries( item ) ) {
1463       shellProcess->addArgument( "install_binary" );
1464       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1465       QString binDir = QDir::currentDirPath() + "/Products/BINARIES";
1466       if ( !myOS.isEmpty() )
1467         binDir += "/" + myOS;
1468       shellProcess->addArgument( binDir );
1469     }
1470     // ... sources ?
1471     else if ( productsView->isSources( item ) ) {
1472       shellProcess->addArgument( "install_source" );
1473       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1474       shellProcess->addArgument( QDir::currentDirPath() + "/Products/SOURCES" );
1475     }
1476     // ... native ?
1477     else if ( productsView->isNative( item ) ) {
1478       shellProcess->addArgument( "try_native" );
1479       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1480       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1481     }
1482     // ... not install : try to find preinstalled
1483     else {
1484       shellProcess->addArgument( "try_preinstalled" );
1485       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1486       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1487     }
1488     // ... target folder
1489     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1490     shellProcess->addArgument( QFileInfo( tgtFolder ).absFilePath() );
1491     
1492
1493     QString depproducts = DefineDependeces(productsMap); 
1494     ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
1495
1496     shellProcess->addArgument( depproducts );
1497     // ... product name - currently instaled product
1498     shellProcess->addArgument( item->text(0) );
1499
1500     // run script
1501     if ( !shellProcess->start() ) {
1502       // error handling can be here
1503       ___MESSAGE___( "error" );
1504     }
1505     return;
1506   }
1507   ___MESSAGE___( "All products have been installed successfully" );
1508   // all products are installed successfully
1509   QString workDir = QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() );
1510   MapProducts::Iterator mapIter;
1511   ___MESSAGE___( "starting pick-up environment" );
1512   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1513     QCheckListItem* item = mapIter.key();
1514     Dependancies dep = mapIter.data();
1515     QString depproducts = QUOTE( DefineDependeces(productsMap) ); 
1516     if ( dep.pickUpEnvironment() ) {
1517       ___MESSAGE___( "... for " << dep.getName() );
1518       QString script;
1519       script += "cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
1520       script += item->text(2) + " ";
1521       script += "pickup_env ";
1522       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
1523       script += QUOTE( QFileInfo( QDir::cleanDirPath( QDir::currentDirPath() + "/Products" ) ).absFilePath() ) + " ";
1524       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
1525       script += depproducts + " ";
1526       script += item->text(0);
1527       ___MESSAGE___( "... --> " << script.latin1() );
1528       if ( system( script.latin1() ) ) { 
1529         ___MESSAGE___( "ERROR" ); 
1530       }
1531     }
1532   }
1533   // <Next> button
1534   setNextEnabled( true );
1535   nextButton()->setText( tr( "&Next >" ) );
1536   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1537   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1538   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1539   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1540   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1541   // <Back> button
1542   setBackEnabled( true );
1543   // script parameters
1544   passedParams->clear();
1545   passedParams->setEnabled( false );
1546   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1547   installInfo->setFinished( true );
1548   if ( isMinimized() )
1549     showNormal();
1550   raise();
1551 }
1552 // ================================================================
1553 /*!
1554  *  SALOME_InstallWizard::onMoreBtn
1555  *  <More...> button slot
1556  */
1557 // ================================================================
1558 void SALOME_InstallWizard::onMoreBtn()
1559 {
1560   if ( moreMode ) {
1561     moreBox->hide();
1562     moreBtn->setText( tr( "More..." ) );
1563   }
1564   else {
1565     moreBox->show();
1566     moreBtn->setText( tr( "Less..." ) );
1567   }
1568   qApp->processEvents();
1569   moreMode = !moreMode;
1570   InstallWizard::layOut();
1571   qApp->processEvents();
1572   if ( !isMaximized() ) {
1573     //setGeometry( geometry().x(), geometry().y(), geometry().width(), 0 );
1574     resize( geometry().width(), 0 );
1575     qApp->processEvents();
1576   }
1577   checkProductPage();
1578 }
1579 // ================================================================
1580 /*!
1581  *  SALOME_InstallWizard::onLaunchSalome
1582  *  <Launch Salome> button slot
1583  */
1584 // ================================================================
1585 void SALOME_InstallWizard::onLaunchSalome()
1586 {
1587   QString msg = tr( "You don't have SALOME binaries installed in the %1 directory!" ).arg( targetFolder->text() );
1588
1589   QCheckListItem* item = findItem( "KERNEL-Bin" );
1590   if ( item ) {
1591     QFileInfo fi( targetFolder->text() + "/KERNEL_" + item->text(1) + "/bin/salome/runSalome" );
1592     QFileInfo fienv( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.sh" );
1593     if ( fienv.exists() ) {
1594       if ( fi.exists() ) {
1595         QString script;
1596         script += "cd " + targetFolder->text() + "/KERNEL_" + item->text(1) + "; ";
1597         script += "source salome.sh; ";
1598         script += "cd bin/salome; ";
1599         script += "runSalome > /dev/null";
1600         script = "(bash -c '" + script + "')";
1601         ___MESSAGE___( "script: " << script.latin1() );
1602         if ( !system( script.latin1() ) )
1603           return;
1604         else
1605           msg = tr( "Can't launch SALOME." );
1606       }
1607       else
1608         msg = tr( "Can't launch SALOME." ) + "\n" + tr( "runSalome file can not be found." );
1609     }
1610     else
1611       msg = tr( "Can't launch SALOME." ) + "\n" + tr( "Can't find environment file." );
1612   }
1613   QMessageBox::warning( this, 
1614                         tr( "Error" ), 
1615                         msg,
1616                         QMessageBox::Ok, 
1617                         QMessageBox::NoButton,
1618                         QMessageBox::NoButton );
1619 }
1620
1621 // ================================================================
1622 /*!
1623  *  SALOME_InstallWizard::onAbout
1624  *  <About> button slot: shows <About> dialog box
1625  */
1626 // ================================================================
1627 void SALOME_InstallWizard::onAbout()
1628 {
1629   AboutDlg d( this );
1630   d.exec();
1631 }
1632
1633 // ================================================================
1634 /*!
1635  *  SALOME_InstallWizard::findItem
1636  *  Searches product listview item with given symbolic name 
1637  */
1638 // ================================================================
1639 QCheckListItem* SALOME_InstallWizard::findItem( const QString& sName )
1640 {
1641   MapProducts::Iterator mapIter;
1642   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1643     if ( mapIter.data().getName() == sName )
1644       return mapIter.key();
1645   }
1646   return 0;
1647 }
1648 // ================================================================
1649 /*!
1650  *  SALOME_InstallWizard::abort
1651  *  Sets progress state to Aborted
1652  */
1653 // ================================================================
1654 void SALOME_InstallWizard::abort()
1655 {
1656   QString prod = progressView->findStatus( Processing );
1657   while ( !prod.isNull() ) {
1658     progressView->setStatus( prod, Aborted );
1659     prod = progressView->findStatus( Processing );
1660   }
1661   prod = progressView->findStatus( Waiting );
1662   while ( !prod.isNull() ) {
1663     progressView->setStatus( prod, Aborted );
1664     prod = progressView->findStatus( Waiting );
1665   }
1666 }
1667 // ================================================================
1668 /*!
1669  *  SALOME_InstallWizard::reject
1670  *  Reject slot, clears temporary directory and closes application
1671  */
1672 // ================================================================
1673 void SALOME_InstallWizard::reject()
1674 {
1675   ___MESSAGE___( "REJECTED" );
1676   if ( !exitConfirmed ) {
1677     if ( QMessageBox::information( this, 
1678                                    tr( "Exit" ), 
1679                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
1680                                    tr( "&Yes" ), 
1681                                    tr( "&No" ),
1682                                    QString::null,
1683                                    0,
1684                                    1 ) == 1 ) {
1685       return;
1686     }
1687     exitConfirmed = true;
1688   }
1689   clean(true);
1690   InstallWizard::reject();
1691 }
1692 // ================================================================
1693 /*!
1694  *  SALOME_InstallWizard::accept
1695  *  Accept slot, clears temporary directory and closes application
1696  */
1697 // ================================================================
1698 void SALOME_InstallWizard::accept()
1699 {
1700   ___MESSAGE___( "ACCEPTED" );
1701   clean(true);
1702   InstallWizard::accept();
1703 }
1704 // ================================================================
1705 /*!
1706  *  SALOME_InstallWizard::clean
1707  *  Clears and (optionally) removes temporary directory
1708  */
1709 // ================================================================
1710 void SALOME_InstallWizard::clean(bool rmDir)
1711 {
1712   WarnDialog::showWarnDlg( 0, false );
1713   myThread->clearCommands();
1714   myWC.wakeAll();
1715   while ( myThread->running() );
1716   // VSR: first remove temporary files
1717   QString script = "cd ./config_files/; remove_tmp.sh '";
1718   script += tempFolder->text().stripWhiteSpace() + TEMPDIRNAME;
1719   script += "' ";
1720   script += QUOTE(DefineDependeces(productsMap));
1721   script += " > /dev/null";
1722   ___MESSAGE___( "script = " << script );
1723   if ( system( script.latin1() ) ) {
1724   }
1725   // VSR: then try to remove created temporary directory
1726   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1727   if ( rmDir && !tmpCreated.isNull() ) {
1728     script = "rm -rf " + tmpCreated;
1729     script += " > /dev/null";
1730     if ( system( script.latin1() ) ) {
1731     }
1732     ___MESSAGE___( "script = " << script );
1733   }
1734 }
1735 // ================================================================
1736 /*!
1737  *  SALOME_InstallWizard::pageChanged
1738  *  Called when user moves from page to page
1739  */
1740 // ================================================================
1741 void SALOME_InstallWizard::pageChanged( const QString & mytitle)
1742 {
1743   nextButton()->setText( tr( "&Next >" ) );
1744   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1745   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1746   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1747   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1748   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1749   cancelButton()->disconnect();
1750   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
1751
1752   QWidget* aPage = InstallWizard::page( mytitle );
1753   if ( !aPage )
1754     return;
1755   updateCaption();
1756   if ( aPage == productsPage ) {
1757     // products page
1758     onSelectionChanged();
1759     checkProductPage();
1760   }
1761   else if ( aPage == prestartPage ) {
1762     // prestart page
1763     showChoiceInfo();
1764   }
1765   else if ( aPage == progressPage ) {
1766     if ( previousPage == prestartPage ) {
1767       // progress page
1768       progressView->clear();
1769       installInfo->clear();
1770       installInfo->setFinished( false );
1771       passedParams->clear();
1772       passedParams->setEnabled( false );
1773       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1774       nextButton()->setText( tr( "&Start" ) );
1775       QWhatsThis::add( nextButton(), tr( "Starts installation process" ) );
1776       QToolTip::add  ( nextButton(), tr( "Starts installation process" ) );
1777       // reconnect Next button - to use it as Start button
1778       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1779       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1780       connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1781       setNextEnabled( true );
1782       // reconnect Cancel button to terminate process
1783       cancelButton()->disconnect();
1784       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
1785     }
1786   }
1787   else if ( aPage == readmePage ) {
1788     QCheckListItem* item = findItem( "KERNEL-Bin" );
1789     runSalomeBtn->setEnabled( item &&
1790                               QFileInfo( targetFolder->text() + "/KERNEL_" + item->text(1) + "/bin/salome/runSalome" ).exists() &&
1791                               QFileInfo( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.csh" ).exists() );
1792     finishButton()->setEnabled( true );
1793   }
1794   previousPage = aPage;
1795   ___MESSAGE___( "previousPage = " << previousPage );
1796 }
1797 // ================================================================
1798 /*!
1799  *  SALOME_InstallWizard::helpClicked
1800  *  Shows help window
1801  */
1802 // ================================================================
1803 void SALOME_InstallWizard::helpClicked()
1804 {
1805   if ( helpWindow == NULL ) {
1806     helpWindow = HelpWindow::openHelp( this );
1807     if ( helpWindow ) {
1808       helpWindow->show();
1809       helpWindow->installEventFilter( this );
1810     }
1811     else {
1812       QMessageBox::warning( this, 
1813                             tr( "Help file not found" ), 
1814                             tr( "Sorry, help is unavailable" ) );
1815     }
1816   }
1817   else {
1818     helpWindow->raise();
1819     helpWindow->setActiveWindow();
1820   }
1821 }
1822 // ================================================================
1823 /*!
1824  *  SALOME_InstallWizard::browseDirectory
1825  *  Shows directory selection dialog
1826  */
1827 // ================================================================
1828 void SALOME_InstallWizard::browseDirectory()
1829 {
1830   const QObject* theSender = sender();
1831   QLineEdit* theFolder;
1832   if ( theSender == targetBtn )
1833     theFolder = targetFolder;
1834   else if (theSender == tempBtn)
1835     theFolder = tempFolder;
1836   else
1837     return;
1838   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
1839   if ( !typedDir.isNull() ) {
1840     theFolder->setText( typedDir );
1841     theFolder->end( false );
1842   }
1843   checkProductPage();
1844 }
1845 // ================================================================
1846 /*!
1847  *  SALOME_InstallWizard::directoryChanged
1848  *  Called when directory path (target or temp) is changed
1849  */
1850 // ================================================================
1851 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
1852 {
1853   checkProductPage();
1854 }
1855 // ================================================================
1856 /*!
1857  *  SALOME_InstallWizard::onStart
1858  *  <Start> button's slot - runs installation
1859  */
1860 // ================================================================
1861 void SALOME_InstallWizard::onStart()
1862 {
1863   if ( nextButton()->text() == tr( "&Stop" ) ) {
1864     shellProcess->kill();
1865     while( shellProcess->isRunning() );
1866     return;
1867   }
1868   progressView->clear();
1869   installInfo->clear();
1870   installInfo->setFinished( false );
1871   passedParams->clear();
1872   passedParams->setEnabled( false );
1873   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1874   // clear list of products to install ...
1875   toInstall.clear();
1876   // ... and fill it for new process
1877   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1878   while( item ) {
1879 //    if ( productsView->isBinaries( item ) || productsView->isSources( item ) || productsView->isNative( item ) ) {
1880       if ( productsMap.contains( item ) )
1881         toInstall.append( productsMap[item].getName() );
1882 //    }
1883     item = (QCheckListItem*)( item->nextSibling() );
1884   }
1885   // if something at all is selected
1886   if ( !toInstall.isEmpty() ) {
1887     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
1888     // disable <Next> button
1889     //setNextEnabled( false );
1890     nextButton()->setText( tr( "&Stop" ) );
1891     QWhatsThis::add( nextButton(), tr( "Aborts installation process" ) );
1892     QToolTip::add  ( nextButton(), tr( "Aborts installation process" ) );
1893     // disable <Back> button
1894     setBackEnabled( false );
1895     // enable script parameters line edit
1896     // VSR commented: 18/09/03: passedParams->setEnabled( true );
1897     // VSR commented: 18/09/03: passedParams->setFocus();
1898     // set status for all products
1899     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
1900       item = findItem( toInstall[ i ] );
1901       QString type = "";
1902       if ( productsView->isBinaries( item ) )
1903         type = tr( "binaries" );
1904       else if ( productsView->isSources( item ) )
1905         type = tr( "sources" );
1906       else if ( productsView->isNative( item ) )
1907         type = tr( "native" );
1908       else 
1909         type = tr( "not install" );
1910       progressView->addProduct( item->text(0), type, item->text(2) );
1911     }
1912     // launch install script
1913     launchScript();
1914   }
1915 }
1916 // ================================================================
1917 /*!
1918  *  SALOME_InstallWizard::onReturnPressed
1919  *  Called when users tries to pass parameters for the script
1920  */
1921 // ================================================================
1922 void SALOME_InstallWizard::onReturnPressed()
1923 {
1924   QString txt = passedParams->text();
1925   installInfo->append( txt );
1926   txt += "\n";
1927   shellProcess->writeToStdin( txt );
1928   passedParams->clear();
1929   progressView->setFocus();
1930   passedParams->setEnabled( false );
1931   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1932 }
1933 /*!
1934   Callback function - as response for the script finishing
1935 */
1936 void SALOME_InstallWizard::productInstalled( )
1937 {
1938   ___MESSAGE___( "process exited" );
1939   if ( shellProcess->normalExit() ) {
1940     ___MESSAGE___( "...normal exit" );
1941     // normal exit - try to proceed installation further
1942     launchScript();
1943   }
1944   else {
1945     ___MESSAGE___( "...abnormal exit" );
1946     // installation aborted
1947     abort();
1948     // clear script passed parameters lineedit
1949     passedParams->clear();
1950     passedParams->setEnabled( false );
1951     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1952     installInfo->setFinished( true );
1953     // enable <Next> button
1954     setNextEnabled( true );
1955     nextButton()->setText( tr( "&Start" ) );
1956     QWhatsThis::add( nextButton(), tr( "Starts installation process" ) );
1957     QToolTip::add  ( nextButton(), tr( "Starts installation process" ) );
1958     // reconnect Next button - to use it as Start button
1959     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1960     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1961     connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1962     //nextButton()->setText( tr( "&Next >" ) );
1963     //QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1964     //QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1965     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1966     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1967     //connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1968     // enable <Back> button
1969     setBackEnabled( true );
1970   }
1971 }
1972 // ================================================================
1973 /*!
1974  *  SALOME_InstallWizard::tryTerminate
1975  *  Slot, called when <Cancel> button is clicked during installation script running
1976  */
1977 // ================================================================
1978 void SALOME_InstallWizard::tryTerminate()
1979 {
1980   if ( shellProcess->isRunning() ) {
1981     if ( QMessageBox::information( this, 
1982                                    tr( "Exit" ), 
1983                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
1984                                    tr( "&Yes" ), 
1985                                    tr( "&No" ),
1986                                    QString::null,
1987                                    0,
1988                                    1 ) == 1 ) {
1989       return;
1990     }
1991     exitConfirmed = true;
1992     // if process still running try to terminate it first
1993     shellProcess->tryTerminate();
1994     abort();
1995     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
1996     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
1997   }
1998   else {
1999     // else just quit install wizard
2000     reject();
2001   }
2002 }
2003 // ================================================================
2004 /*!
2005  *  SALOME_InstallWizard::onCancel
2006  *  Kills installation process and quits application
2007  */
2008 // ================================================================
2009 void SALOME_InstallWizard::onCancel()
2010 {
2011   shellProcess->kill();
2012   reject();
2013 }
2014 // ================================================================
2015 /*!
2016  *  SALOME_InstallWizard::onSelectionChanged
2017  *  Called when selection is changed in the products list view
2018  */
2019 // ================================================================
2020 void SALOME_InstallWizard::onSelectionChanged()
2021 {
2022   productsInfo->clear();
2023   QListViewItem* item = productsView->selectedItem();
2024   if ( !item )
2025     return;
2026   if ( item->parent() )
2027     item = item->parent();
2028   QCheckListItem* aItem = (QCheckListItem*)item;
2029   if ( !productsMap.contains( aItem ) )
2030     return;
2031   Dependancies dep = productsMap[ aItem ];
2032   QString text = "<b>" + aItem->text(0) + "</b>" + "<br>";
2033   if ( !aItem->text(1).stripWhiteSpace().isEmpty() )
2034     text += tr( "Version" ) + ": " + aItem->text(1) + "<br>";
2035   text += "<br>";
2036   if ( !dep.getDescription().isEmpty() ) {
2037     text += "<i>" + dep.getDescription() + "</i><br><br>";
2038   }
2039   text += tr( "User choice" ) + ": ";
2040   long totSize = 0, tempSize = 0;
2041   if ( productsView->isBinaries( aItem ) ) {
2042     text += "<b>" + tr( "install binaries" ) + "</b>" + "<br>";
2043     totSize = dep.getSize();
2044   }
2045   else if ( productsView->isSources( aItem ) ) {
2046     text += "<b>" + tr( "install sources" ) + "</b>" + "<br>";
2047     totSize = dep.getSize( true );
2048     tempSize = dep.getTempSize();
2049   }
2050   else if ( productsView->isNative( aItem ) ) {
2051     text += "<b>" + tr( "use native" ) + "</b>" + "<br>";
2052   }
2053   else {
2054     text += "<b>" + tr( "not install" ) + "</b>" + "<br>";
2055   }
2056   
2057   text += tr( "Disk space required" ) + ": " + QString::number( totSize ) + " Kb<br>";
2058   text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " Kb<br>";
2059   text += "<br>";
2060   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
2061   text +=  tr( "Prerequisites" ) + ": " + req;
2062   productsInfo->setText( text );
2063 }
2064 // ================================================================
2065 /*!
2066  *  SALOME_InstallWizard::onItemToggled
2067  *  Called when user checks/unchecks any product item
2068  *  Recursively sets all prerequisites and updates "Next" button state
2069  */
2070 // ================================================================
2071 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
2072 {
2073   if ( prerequisites->isChecked() ) {
2074     if ( item->parent() )
2075       item = (QCheckListItem*)( item->parent() );
2076     if ( productsMap.contains( item ) ) {
2077       productsView->blockSignals( true );
2078       setPrerequisites( item );
2079       productsView->blockSignals( false );
2080     }
2081   }
2082   onSelectionChanged();
2083   checkProductPage();
2084 }
2085 // ================================================================
2086 /*!
2087  *  SALOME_InstallWizard::onProdBtn
2088  *  This slot is called when user clicks one of <Select Sources>,
2089  *  <Select Binaries>, <Unselect All> buttons ( products page )
2090  */
2091 // ================================================================
2092 void SALOME_InstallWizard::onProdBtn()
2093 {
2094   const QObject* snd = sender();
2095   productsView->blockSignals( true );
2096   selectSrcBtn->blockSignals( true );
2097   selectBinBtn->blockSignals( true );
2098   if ( snd == unselectBtn ) {
2099     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
2100     while( item ) {
2101       productsView->setNone( item );
2102       item = (QCheckListItem*)( item->nextSibling() );
2103     }
2104   }
2105   else if ( snd == selectSrcBtn )  {
2106     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
2107     if ( checkBox->state() == QButton::NoChange )
2108       checkBox->setState( QButton::On );
2109     MapProducts::Iterator itProd;
2110     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2111       if ( itProd.data().hasContext( "salome sources" ) ) {
2112         if ( checkBox->state() == QButton::Off ) {
2113           int selBin = 0;
2114           MapProducts::Iterator itProd1;
2115           for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
2116             if (  itProd1.data().hasContext( "salome binaries" ) && 
2117                  !itProd1.data().hasContext( "salome sources" ) &&
2118                   productsView->isBinaries( itProd1.key() ) )
2119               selBin++;
2120           }
2121           if ( !itProd.data().hasContext( "salome binaries" ) || !selBin )
2122             productsView->setNone( itProd.key() );
2123         }
2124         else {
2125           productsView->setSources( itProd.key() );
2126           if ( prerequisites->isChecked() )
2127             setPrerequisites( itProd.key() );
2128         }
2129       }
2130     }
2131   }
2132   else if ( snd == selectBinBtn )  {
2133     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
2134     if ( checkBox->state() == QButton::NoChange )
2135       checkBox->setState( QButton::On );
2136     MapProducts::Iterator itProd;
2137     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2138       if ( itProd.data().hasContext( "salome binaries" ) ) {
2139         if ( checkBox->state() == QButton::Off ) {
2140           int selSrc = 0;
2141           MapProducts::Iterator itProd1;
2142           for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
2143             if (  itProd1.data().hasContext( "salome sources" ) && 
2144                  !itProd1.data().hasContext( "salome binaries" ) &&
2145                   productsView->isSources( itProd1.key() ) )
2146               selSrc++;
2147           }
2148           if ( !itProd.data().hasContext( "salome sources" ) || !selSrc )
2149             productsView->setNone( itProd.key() );
2150         }
2151         else {
2152           productsView->setBinaries( itProd.key() );
2153           if ( prerequisites->isChecked() )
2154             setPrerequisites( itProd.key() );
2155         }
2156       }
2157     }
2158   }
2159   selectSrcBtn->blockSignals( false );
2160   selectBinBtn->blockSignals( false );
2161   productsView->blockSignals( false );
2162   onSelectionChanged();
2163   checkProductPage();
2164 }
2165 // ================================================================
2166 /*!
2167  *  SALOME_InstallWizard::wroteToStdin
2168  *  QProcess slot: -->something was written to stdin
2169  */
2170 // ================================================================
2171 void SALOME_InstallWizard::wroteToStdin( )
2172 {
2173   ___MESSAGE___( "Something was sent to stdin" );
2174 }
2175 // ================================================================
2176 /*!
2177  *  SALOME_InstallWizard::readFromStdout
2178  *  QProcess slot: -->something was written to stdout
2179  */
2180 // ================================================================
2181 void SALOME_InstallWizard::readFromStdout( )
2182 {
2183   ___MESSAGE___( "Something was sent to stdout" );
2184   while ( shellProcess->canReadLineStdout() ) {
2185     installInfo->append( QString( shellProcess->readLineStdout() ) );
2186     installInfo->scrollToBottom();
2187   }
2188   QString str( shellProcess->readStdout() );
2189   if ( !str.isEmpty() ) {
2190     installInfo->append( str );
2191     installInfo->scrollToBottom();
2192   }
2193 }
2194
2195 #define OUTLINE_TEXT(x) QString( "<font color=#FF0000><b>" ) + QString( x ) + QString( "</b></font>" )
2196
2197 // ================================================================
2198 /*!
2199  *  SALOME_InstallWizard::readFromStderr
2200  *  QProcess slot: -->something was written to stderr
2201  */
2202 // ================================================================
2203 void SALOME_InstallWizard::readFromStderr( )
2204 {
2205   ___MESSAGE___( "Something was sent to stderr" );
2206   while ( shellProcess->canReadLineStderr() ) {
2207     installInfo->append( OUTLINE_TEXT( QString( shellProcess->readLineStderr() ) ) );
2208     installInfo->scrollToBottom();
2209   }
2210   QString str( shellProcess->readStderr() );
2211   if ( !str.isEmpty() ) {
2212     installInfo->append( OUTLINE_TEXT( str ) );
2213     installInfo->scrollToBottom();
2214   }
2215   // VSR: 10/11/05 - disable answer mode ==>
2216   // passedParams->setEnabled( true );
2217   // passedParams->setFocus();
2218   // QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
2219   // VSR: 10/11/05 - disable answer mode <==
2220 }
2221 // ================================================================
2222 /*!
2223  *  SALOME_InstallWizard::setDependancies
2224  *  Sets dependancies for the product item
2225  */
2226 // ================================================================
2227 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
2228 {
2229   productsMap[item] = dep;
2230 }
2231 // ================================================================
2232 /*!
2233  *  SALOME_InstallWizard::polish
2234  *  Polishing of the widget - to set right initial size
2235  */
2236 // ================================================================
2237 void SALOME_InstallWizard::polish()
2238 {
2239   resize( 0, 0 );
2240   InstallWizard::polish();
2241 }
2242 // ================================================================
2243 /*!
2244  *  SALOME_InstallWizard::saveLog
2245  *  Save installation log to file
2246  */
2247 // ================================================================
2248 void SALOME_InstallWizard::saveLog()
2249 {
2250   QString txt = installInfo->text();
2251   if ( txt.length() <= 0 )
2252     return;
2253   QDateTime dt = QDateTime::currentDateTime();
2254   QString fileName = dt.toString("ddMMyy-hhmm");
2255   fileName.prepend("install-"); fileName.append(".html");
2256   fileName = QFileDialog::getSaveFileName( fileName,
2257                                            QString( "HTML files (*.htm *.html)" ),
2258                                            this, 0,
2259                                            tr( "Save Log file" ) );
2260   if ( !fileName.isEmpty() ) {
2261     QFile f( fileName );
2262     if ( f.open( IO_WriteOnly ) ) {
2263       QTextStream stream( &f );
2264       stream << txt;
2265       f.close();
2266     }
2267     else {
2268       QMessageBox::critical( this, 
2269                              tr( "Error" ), 
2270                              tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ), 
2271                              QMessageBox::Ok, 
2272                              QMessageBox::NoButton, 
2273                              QMessageBox::NoButton );
2274     }
2275   }
2276 }
2277 // ================================================================
2278 /*!
2279  *  SALOME_InstallWizard::updateCaption
2280  *  Updates caption according to the current page number
2281  */
2282 // ================================================================
2283 void SALOME_InstallWizard::updateCaption()
2284 {
2285   QWidget* aPage = InstallWizard::currentPage();
2286   if ( !aPage ) 
2287     return;
2288   InstallWizard::setCaption( tr( myCaption ) + " " +
2289                              tr( getIWName() ) + " - " +
2290                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
2291 }
2292
2293 // ================================================================
2294 /*!
2295  *  SALOME_InstallWizard::processValidateEvent
2296  *  Processes validation event (<val> is validation code)
2297  */
2298 // ================================================================
2299 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
2300 {
2301   QWidget* aPage = InstallWizard::currentPage();
2302   if ( aPage != productsPage ) {
2303     InstallWizard::processValidateEvent( val, data );
2304     return;
2305   }
2306   myMutex.lock();
2307   myMutex.unlock();
2308   QCheckListItem* item = (QCheckListItem*)data;
2309   if ( val > 0 ) {
2310     if ( val == 2 ) {
2311       WarnDialog::showWarnDlg( 0, false );
2312       // when try_native returns 2 it means that native product version is higher than that is prerequisited
2313       if ( QMessageBox::warning( this, 
2314                                  tr( "Warning" ), 
2315                                  tr( "You have newer version of %1 installed on your computer than that is required (%2).\nContinue?").arg(item->text(0)).arg(item->text(1)),
2316                                 QMessageBox::Yes, 
2317                                 QMessageBox::No, 
2318                                 QMessageBox::NoButton ) == QMessageBox::No ) {
2319         myThread->clearCommands();
2320         myWC.wakeAll();
2321         setNextEnabled( true );
2322         setBackEnabled( true );
2323         return;
2324       }
2325       WarnDialog::showWarnDlg( this, true );
2326     }
2327     else {
2328       WarnDialog::showWarnDlg( 0, false );
2329       bool binMode = productsView->hasBinaries( item );
2330       bool srcMode = productsView->hasSources( item );
2331       QStringList buttons;
2332       buttons.append( binMode ? tr( "Install binaries" ) : ( srcMode ? tr( "Install sources" ) : 
2333                                                                        tr( "Select manually" ) ) );
2334       buttons.append( binMode ? ( srcMode ? tr( "Install sources" ) : tr( "Select manually" ) ) :
2335                                 ( srcMode ? tr( "Select manually" ) : QString::null ) );
2336       buttons.append( binMode && srcMode ? tr( "Select manually" ) : QString::null );
2337       int answer = QMessageBox::warning( this, 
2338                                          tr( "Warning" ), 
2339                                          tr( "You don't have native %1 %2 on your computer.\nPlease, change your installation settings.").arg(item->text(0)).arg(item->text(1)), 
2340                                          buttons[0],
2341                                          buttons[1],
2342                                          buttons[2] );
2343       if ( buttons[ answer ] == tr( "Install binaries" ) )
2344         productsView->setBinaries( item );
2345       else if ( buttons[ answer ] == tr( "Install sources" ) )
2346         productsView->setSources( item );
2347       else {
2348         if ( !moreMode )
2349           onMoreBtn();
2350         productsView->setCurrentItem( item );
2351         productsView->setSelected( item, true );
2352         productsView->ensureItemVisible( item );
2353         myThread->clearCommands();
2354         myWC.wakeAll();
2355         setNextEnabled( true );
2356         setBackEnabled( true );
2357         return;
2358       }
2359       WarnDialog::showWarnDlg( this, true );
2360     }
2361   }
2362   if ( myThread->hasCommands() )
2363     myWC.wakeAll();
2364   else {
2365     WarnDialog::showWarnDlg( 0, false );
2366     InstallWizard::processValidateEvent( val, data );
2367   }
2368 }