Salome HOME
Update for Salome 5.1.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, Open CASCADE SAS (vadim.sandler@opencascade.com)
4 //  Project   : SALOME
5 //  Module    : Installation Wizard
6 //  Copyright : 2002-2009 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 #include <qregexp.h>
43 #include <qradiobutton.h>
44 #include <qbuttongroup.h>
45 #include <qregexp.h>
46 #include <qdir.h>
47
48 #ifdef WNT
49 #include <iostream.h>
50 #include <process.h>
51 #else
52 #include <unistd.h>
53 #include <algo.h>
54 #include <sys/utsname.h>
55 #endif
56
57 #ifdef WNT
58 #define max( x, y ) ( x ) > ( y ) ? ( x ) : ( y )
59 #endif
60
61 QString tmpDirName() { return QString(  "/INSTALLWORK" ) + QString::number( getpid() ); }
62 #define TEMPDIRNAME tmpDirName()
63
64 // ================================================================
65 /*!
66  *  Script
67  *  Helper class to generate shell command
68  */
69 // ================================================================
70 class Script
71 {
72 public:
73   Script( const QString& cmd = QString::null, const QString& sep = " " ) : mySeparator( sep )
74   {
75     append( cmd );
76   }
77   void append( const QString& cmd )
78   {
79     if ( !cmd.isEmpty() ) myList.append( cmd );
80   }
81   Script& operator<<( const QString& cmd )
82   {
83     append( cmd );
84     return *this;
85   }
86   QString script() const
87   {
88     return myList.join( mySeparator );
89   }
90   void clear()
91   {
92     myList.clear();
93   }
94 private:
95   QStringList myList;
96   QString     mySeparator;
97 };
98
99 // ================================================================
100 /*!
101  *  ProcessThread
102  *  Class for executing system commands
103  */
104 // ================================================================
105 static QMutex myMutex(false);
106 static QWaitCondition myWC;
107 class ProcessThread: public QThread
108 {
109   typedef QPtrList<QCheckListItem> ItemList;
110 public:
111   ProcessThread( SALOME_InstallWizard* iw ) : QThread(), myWizard( iw ) { myItems.setAutoDelete( false ); }
112
113   void addCommand( QCheckListItem* item, const QString& cmd ) {
114     myItems.append( item );
115     myCommands.push_back( cmd );
116   }
117
118   bool hasCommands() const { return myCommands.count() > 0; }
119   void clearCommands()     { myCommands.clear(); myItems.clear(); }
120
121   virtual void run() {
122     while ( hasCommands() ) {
123       ___MESSAGE___( "ProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() );
124       int result = system( myCommands[ 0 ] ) / 256; // return code is <errno> * 256
125       ___MESSAGE___( "ProcessThread::run - Result : " << result );
126       QCheckListItem* item = myItems.first();
127       myCommands.pop_front();
128       myItems.removeFirst();
129       myMutex.lock();
130       SALOME_InstallWizard::postValidateEvent( myWizard, result, (void*)item );
131       if ( hasCommands() )
132         myWC.wait(&myMutex);
133       myMutex.unlock();
134     };
135   }
136
137 private:
138   QStringList           myCommands;
139   ItemList              myItems;
140   SALOME_InstallWizard* myWizard;
141 };
142
143 // ================================================================
144 /*!
145  *  WarnDialog
146  *  Warning dialog box
147  */
148 // ================================================================
149 class WarnDialog: public QDialog
150 {
151   static WarnDialog* myDlg;
152   bool myCloseFlag;
153
154   WarnDialog( QWidget* parent )
155   : QDialog( parent, "WarnDialog", true, WDestructiveClose ) {
156     setCaption( tr( "Information" ) );
157     myCloseFlag = false;
158     QLabel* lab = new QLabel( tr( "Please, wait while checking native products configuration ..." ), this );
159     lab->setAlignment( AlignCenter );
160     lab->setFrameStyle( QFrame::Box | QFrame::Plain );
161     QVBoxLayout* l = new QVBoxLayout( this );
162     l->setMargin( 0 );
163     l->add( lab );
164     this->setFixedSize( lab->sizeHint().width()  + 50,
165                         lab->sizeHint().height() * 5 );
166   }
167   void accept() { return; }
168   void reject() { return; }
169   void closeEvent( QCloseEvent* e )
170   { if ( !myCloseFlag ) return;
171     e->accept();
172     QDialog::closeEvent( e );
173   }
174   ~WarnDialog() { myDlg = 0; }
175 public:
176   static void showWarnDlg( QWidget* parent, bool show ) {
177     if ( show ) {
178       if ( !myDlg ) {
179         myDlg = new WarnDialog( parent );
180         QSize sh = myDlg->size();
181         myDlg->move( parent->x() + (parent->width()-sh.width())/2,
182                      parent->y() + (parent->height()-sh.height())/2 );
183         myDlg->show();
184       }
185       myDlg->raise();
186       myDlg->setFocus();
187     }
188     else {
189       if ( myDlg ) {
190         myDlg->myCloseFlag = true;
191         myDlg->close();
192       }
193     }
194   }
195   static bool isWarnDlgShown() { return myDlg != 0; }
196 };
197 WarnDialog* WarnDialog::myDlg = 0;
198
199 // ================================================================
200 /*!
201  *  InstallInfo
202  *  Installation progress info window class
203  */
204 // ================================================================
205 class InstallInfo : public QTextEdit
206 {
207 public:
208   InstallInfo( QWidget* parent ) : QTextEdit( parent ), finished( false ) {}
209   void setFinished( const bool f ) { finished = f; }
210 protected:
211   QPopupMenu* createPopupMenu( const QPoint& )
212   {
213     int para1, col1, para2, col2;
214     getSelection(&para1, &col1, &para2, &col2);
215     bool allSelected = hasSelectedText() &&
216       para1 == 0 && para2 == paragraphs()-1 && col1 == 0 && col2 == paragraphLength(para2);
217     QPopupMenu* popup = new QPopupMenu( this );
218     int id = popup->insertItem( tr( "&Copy" ) );
219     popup->setItemEnabled( id, hasSelectedText() );
220     popup->connectItem ( id, this, SLOT( copy() ) );
221     id = popup->insertItem( tr( "Select &All" ) );
222     popup->setItemEnabled( id, (bool)text().length() && !allSelected );
223     popup->connectItem ( id, this, SLOT( selectAll() ) );
224     if ( finished ) {
225       QWidget* p = parentWidget();
226       while ( p && !p->inherits( "SALOME_InstallWizard" ) )
227         p = p->parentWidget();
228       if ( p && p->inherits( "SALOME_InstallWizard" ) ) {
229         popup->insertSeparator();
230         id = popup->insertItem( tr( "&Save Log" ) );
231         popup->setItemEnabled( id, (bool)text().length() );
232         popup->connectItem ( id, (SALOME_InstallWizard*)p, SLOT( saveLog() ) );
233       }
234     }
235     return popup;
236   }
237 private:
238   bool finished;
239 };
240
241 // ================================================================
242 /*!
243  *  getAllProducts [ static ]
244  *  Defines list of all products as a string separated by space symbols
245  */
246 // ================================================================
247 static QString getAllProducts(MapProducts& theProductsMap)
248 {
249   QStringList aModules, aPrereqs;
250   for ( MapProducts::Iterator mapIter = theProductsMap.begin(); mapIter != theProductsMap.end(); ++mapIter ) {
251     QCheckListItem* item = mapIter.key();
252     Dependancies dep = mapIter.data();
253     QString curModule = item->text(0);
254     if ( !aModules.contains( curModule ) && !aPrereqs.contains( curModule ) ) {
255       if ( dep.getType() == "component" ) {
256         aModules.append( curModule );
257         aModules.append( curModule + "_src" );
258       }
259       else {
260         aPrereqs.append( curModule );
261         aPrereqs.append( curModule + "_src" );
262       }
263     }
264   }
265   return QStringList(aPrereqs+aModules).join(" ");
266 }
267
268 // ================================================================
269 /*!
270  *  setAboutInfo [ static ]
271  *  Sets 'what's this' and 'tooltip' information for the widget
272  */
273 // ================================================================
274 static void setAboutInfo( QWidget* widget, const QString& tip )
275 {
276   QWhatsThis::add( widget, tip );
277   QToolTip::add  ( widget, tip );
278 }
279
280 #define QUOTE(arg) QString("'") + QString(arg) + QString("'")
281
282 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
283                T H E   O L D   I M P L E M E N T A T I O N
284 static QString DefineDependeces(MapProducts& theProductsMap, QCheckListItem* product ){
285   QStringList aProducts;
286   if ( theProductsMap.contains( product ) ) {
287     Dependancies dep = theProductsMap[ product ];
288     QStringList deps = dep.getDependancies();
289     for (int i = 0; i<(int)deps.count(); i++ ) {
290       aProducts.append( deps[i] );
291     }
292   }
293   return QString("\"") + aProducts.join(" ") + QString("\"");
294 }
295 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
296
297 // ================================================================
298 /*!
299  *  makeDir [ static ]
300  *  Makes directory recursively, returns false if not succedes
301  */
302 // ================================================================
303 static bool makeDir( const QString& theDir, QString& theCreated )
304 {
305   if ( theDir.isEmpty() )
306     return false;
307   QString aDir = QDir::cleanDirPath( QFileInfo( theDir ).absFilePath() );
308   int start = 1;
309   while ( start > 0 ) {
310     start = aDir.find( QDir::separator(), start );
311     if ( start > 0 ) {
312       QFileInfo fi( aDir.left( start ) );
313       if ( !fi.exists() ) {
314         // VSR: Create directory and set permissions to allow other users to remove it
315         Script script;
316         script << "mkdir"     << QUOTE( fi.absFilePath() ) << ">& /dev/null" << "&&";
317         script << "chmod 777" << QUOTE( fi.absFilePath() ) << ">& /dev/null";
318         ___MESSAGE___( "script = " << script.script().latin1() );
319         if ( system( script.script().latin1() ) )
320           return false;
321         // VSR: Remember the top of the created directory (to remove it in the end of the installation)
322         if ( theCreated.isNull() )
323           theCreated = fi.absFilePath();
324       }
325     }
326     start++;
327   }
328   if ( !QFileInfo( aDir ).exists() ) {
329     // VSR: Create directory, other users should NOT have possibility to remove it!!!
330     Script script;
331     script << "mkdir" << QUOTE( aDir ) << ">& /dev/null";
332     ___MESSAGE___( "script = " << script.script().latin1() );
333     if ( system( script.script().latin1() ) )
334       return false;
335     // VSR: Remember the top of the created directory (to remove it in the end of the installation)
336     if ( theCreated.isNull() )
337       theCreated = aDir;
338   }
339   return true;
340 }
341 // ================================================================
342 /*!
343  *  readFile [ static ]
344  *  Reads the file, returns false if can't open it
345  */
346 // ================================================================
347 static bool readFile( const QString& fileName, QString& text )
348 {
349   if ( QFile::exists( fileName ) ) {
350     QFile file( fileName );
351     if ( file.open( IO_ReadOnly ) ) {
352       QTextStream stream( &file );
353       QString line;
354       while ( !stream.eof() ) {
355         line = stream.readLine(); // line of text excluding '\n'
356         text += line + "\n";
357       }
358       file.close();
359       return true;
360     }
361   }
362   return false;
363 }
364 // ================================================================
365 /*!
366  *  hasSpace [ static ]
367  *  Checks if string contains spaces; used to check directory paths
368  */
369 // ================================================================
370 static bool hasSpace( const QString& dir )
371 {
372   for ( int i = 0; i < (int)dir.length(); i++ ) {
373     if ( dir[ i ].isSpace() )
374       return true;
375   }
376   return false;
377 }
378
379 // ================================================================
380 /*!
381  *  makeTitle
382  *  Creates HTML-wrapped title text
383  */
384 // ================================================================
385 static QString makeTitle( const QString& text, const QString& separator = " ", bool fl = true )
386 {
387   QStringList words = QStringList::split( separator, text );
388   if ( fl ) {
389     for ( uint i = 0; i < words.count(); i++ )
390       words[i] = QString( "<font color=red>%1</font>" ).arg( words[i].left(1) ) + words[i].mid(1);
391   }
392   else {
393     if ( words.count() > 0 )
394       words[0] = QString( "<font color=red>%1</font>" ).arg( words[0] );
395     if ( words.count() > 1 )
396       words[words.count()-1] = QString( "<font color=red>%1</font>" ).arg( words[words.count()-1] );
397   }
398   QString res = words.join( separator );
399   if ( !res.isEmpty() )
400     res = QString( "<b>%1</b>" ).arg( res );
401   return res;
402 }
403
404 // ================================================================
405 /*!
406  *  QMyCheckBox class : custom check box
407  *  The only goal is to give access to the protected setState() method
408  */
409 // ================================================================
410 class QMyCheckBox: public QCheckBox
411 {
412 public:
413   QMyCheckBox( const QString& text, QWidget* parent, const char* name = 0 ) : QCheckBox ( text, parent, name ) {}
414   void setState ( ToggleState s ) { QCheckBox::setState( s ); }
415 };
416
417 // ================================================================
418 /*!
419  *  AboutDlg
420  *  "About dialog box.
421  */
422 // ================================================================
423 class AboutDlg: public QDialog
424 {
425 public:
426   AboutDlg( SALOME_InstallWizard* parent ) : QDialog( parent, "About dialog box", true )
427   {
428     // caption
429     setCaption( QString( "About %1" ).arg( parent->getIWName() ) );
430     // palette
431     QPalette pal = palette();
432     QColorGroup cg = pal.active();
433     cg.setColor( QColorGroup::Foreground, Qt::darkBlue );
434     cg.setColor( QColorGroup::Background, Qt::white );
435     pal.setActive( cg ); pal.setInactive( cg ); pal.setDisabled( cg );
436     setPalette( pal );
437     // layout
438     QGridLayout* main = new QGridLayout( this, 1, 1, 11, 6 );
439     // image
440     QLabel* logo = new QLabel( this, "logo" );
441     logo->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
442     logo->setMinimumSize( 32, 32 ); logo->setMaximumSize( 32, 32 );
443     logo->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
444     logo->setFrameStyle( QLabel::NoFrame | QLabel::Plain );
445     logo->setPixmap( pixmap( pxAbout ) );
446     logo->setScaledContents( false );
447     logo->setAlignment( QLabel::AlignCenter );
448     // decoration
449     QLabel* decorLeft = new QLabel( this, "decorLeft" );
450     decorLeft->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding ) );
451     decorLeft->setMinimumWidth( 32 ); decorLeft->setMaximumWidth( 32 );
452     decorLeft->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
453     decorLeft->setScaledContents( false );
454     QLabel* decorTop = new QLabel( this, "decorTop" );
455     decorTop->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
456     decorTop->setMinimumHeight( 32 ); decorTop->setMaximumHeight( 32 );
457     decorTop->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
458     decorTop->setScaledContents( false );
459     // contents
460     QLabel* title = new QLabel( this, "title" );
461     QString tlt = parent->getIWName();
462     title->setText( makeTitle( tlt ) );
463     QLabel* version = new QLabel( this, "version" );
464     version->setText( QString( "<b>Version</b>: %1.%1.%1" ).arg( __IW_VERSION_MAJOR__ ) \
465                       .arg( __IW_VERSION_MINOR__ ) \
466                       .arg( __IW_VERSION_PATCH__ ) );
467     QLabel* copyright = new QLabel( this, "copyright" );
468     copyright->setText( "<b>Copyright</b> &copy; 2007-2009 CEA/DEN" );
469     QFont font = title->font();
470     font.setPointSize( (int)( font.pointSize() * 1.8 ) );
471     title->setFont( font );
472     QFrame* line = new QFrame( this, "line" );
473     line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
474     QLabel* url = new QLabel( this, "url" );
475     url->setText( makeTitle( "www.salome-platform.org", ".", false ) );
476     url->setAlignment( AlignRight );
477     font = version->font();
478     font.setPointSize( (int)( font.pointSize() / 1.2 ) );
479     version->setFont( font );
480     copyright->setFont( font );
481     url->setFont( font );
482     // layout
483     main->addWidget( logo, 0, 0 );
484     main->addMultiCellWidget( decorLeft, 1, 5, 0, 0 );
485     main->addWidget( decorTop, 0, 1 );
486     main->addWidget( title, 1, 1 );
487     main->addWidget( version, 2, 1 );
488     main->addWidget( copyright, 3, 1 );
489     main->addWidget( line, 4, 1 );
490     main->addWidget( url, 5, 1 );
491     // resize
492     QFontMetrics fm( title->font() );
493     int width = (int)( fm.width( tlt ) * 1.5 );
494     title->setMinimumWidth( width );
495 //     setMaximumSize( minimumSize() );
496   }
497   void mousePressEvent( QMouseEvent* )
498   {
499     accept();
500   }
501 };
502
503 // ================================================================
504 /*!
505  *  SALOME_InstallWizard::SALOME_InstallWizard
506  *  Constructor
507  */
508 // ================================================================
509 SALOME_InstallWizard::SALOME_InstallWizard(const QString& aXmlFileName,
510                                            const QString& aTargetDir,
511                                            const QString& aTmpDir,
512                                            const bool     aForceSrc,
513                                            const bool     aSingleDir)
514      : InstallWizard( qApp->desktop(), "SALOME_InstallWizard", false, 0 ),
515        helpWindow( NULL ),
516        moreMode( false ),
517        previousPage( 0 ),
518        exitConfirmed( false ),
519        hasErrors( false )
520 {
521   myIWName     = tr( "Installation Wizard" );
522   tmpCreated   = QString::null;
523   xmlFileName  = aXmlFileName;
524   myTargetPath = aTargetDir;
525   myTmpPath    = aTmpDir;
526   forceSrc     = aForceSrc;
527   singleDir    = aSingleDir;
528   stateChanged = true;
529
530   QDir rootDir( rootDirPath() );
531   binPath = rootDir.filePath( "Products/BINARIES" );
532   srcPath = rootDir.filePath( "Products/SOURCES" );
533   oneProdDirName = "PRODUCTS";
534   
535   commonPlatform = "Debian 3.1";
536   
537   //
538   // get XML filename and current platform
539   //
540   // ... get current platform
541   curPlatform = currentPlatform().join(" ");
542   //cout << "curOS = " << curPlatform << endl;
543   refPlatform = "";
544   // ... check XML and platform definition
545   getXmlAndPlatform();
546
547   // set application font
548   QFont fnt = font();
549   fnt.setPointSize( 14 );
550   fnt.setBold( true );
551   setTitleFont( fnt );
552
553   // set icon
554   setIcon( pixmap( pxIcon ) );
555   // enable sizegrip
556   setSizeGripEnabled( true );
557
558   // add logo
559   addLogo( pixmap( pxLogo ) );
560
561   // set defaults
562   setVersion( "5.1.3" );
563   setCaption( tr( "SALOME %1" ).arg( myVersion ) );
564   setCopyright( tr( "<h5>Copyright &copy; 2007-2009 CEA/DEN, EDF R&amp;D, OPEN CASCADE<br></h5>"
565                 "<h5>Copyright &copy; 2003-2007 OPEN CASCADE,<br>EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&amp;D,<br>LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</h5>" ));
566   setLicense( tr( "<h5>GNU LGPL</h5>" ) );
567
568   ___MESSAGE___( "Configuration file : " << xmlFileName.latin1() );
569   ___MESSAGE___( "Target directory   : " << myTargetPath.latin1() );
570   ___MESSAGE___( "Temporary directory: " << myTmpPath.latin1() );
571
572   //
573   // xml reader
574   //
575   StructureParser* parser = new StructureParser( this );
576   parser->readXmlFile(xmlFileName);
577
578   // create instance of class for starting shell script to get available disk space
579   diskSpaceProc = new QProcess( this, "procDiskSpace" );
580   // create instance of class for starting shell install script
581   shellProcess = new QProcess( this, "shellProcess" );
582   // create instance of class for starting shell script to modify SALOME *.la files
583   modifyLaProc = new QProcess( this, "modifyLaProc" );
584   // create instance of class for starting shell script to check Fortran libraries
585   checkFLibProc = new QProcess( this, "checkFLibProc" );
586
587   // create introduction page
588   setupIntroPage();
589   // create page to select installation type
590   setupTypePage();
591   // create page to select the reference installation platform (if necessary)
592   setupPlatformPage();
593   // create directories page
594   setupDirPage();
595   // create products page
596   setupProductsPage();
597   // create prestart page
598   setupCheckPage();
599   // create progress page
600   setupProgressPage();
601   // create readme page
602   setupReadmePage();
603
604   // common buttons
605   setAboutInfo( backButton(),   tr( "Return to the previous step\nof the installation procedure" ) );
606   setAboutInfo( nextButton(),   tr( "Move to the next step\nof the installation procedure" ) );
607   setAboutInfo( finishButton(), tr( "Finish the installation and quit the program" ) );
608   setAboutInfo( cancelButton(), tr( "Cancel the installation and quit the program" ) );
609   setAboutInfo( helpButton(),   tr( "Show the help information" ) );
610
611   // common signals connections
612   connect( this, SIGNAL( selected( const QString& ) ),
613                                            this, SLOT( pageChanged( const QString& ) ) );
614   connect( this, SIGNAL( helpClicked() ),  this, SLOT( helpClicked() ) );
615   connect( this, SIGNAL( aboutClicked() ), this, SLOT( onAbout() ) );
616
617   // catch signals from launched diskSpaceProc
618   connect( diskSpaceProc, SIGNAL( processExited() ), this, SLOT( updateAvailableSpace() ) );
619   // catch signals from launched shellProcess
620   connect(shellProcess, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout() ) );
621   connect(shellProcess, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr() ) );
622   connect(shellProcess, SIGNAL( processExited() ),   this, SLOT( productInstalled() ) );
623   connect(shellProcess, SIGNAL( wroteToStdin() ),    this, SLOT( wroteToStdin() ) );
624   // catch signals from launched modifyLaProc
625   connect(modifyLaProc, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout() ) );
626   connect(modifyLaProc, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr() ) );
627   connect(modifyLaProc, SIGNAL( processExited() ), this, SLOT( checkModifyLaResult() ) );
628   // catch signals from launched checkFLibProc
629   connect(checkFLibProc, SIGNAL( processExited() ), this, SLOT( checkFLibResult() ) );
630
631   // create validation thread
632   myThread = new ProcessThread( this );
633
634   // show about button
635   setAboutIcon( pixmap( pxAbout ) );
636   showAboutBtn( true );
637 }
638 // ================================================================
639 /*!
640  *  SALOME_InstallWizard::~SALOME_InstallWizard
641  *  Destructor
642  */
643 // ================================================================
644 SALOME_InstallWizard::~SALOME_InstallWizard()
645 {
646   shellProcess->kill(); // kill it for sure
647   int PID = (int)shellProcess->processIdentifier();
648   if ( PID > 0 ) {
649     Script script;
650     script << "kill -9" << QString::number( PID ) << ">& /dev/null";
651     ___MESSAGE___( "script: " << script.script().latin1() );
652     if ( system( script.script().latin1() ) ) {
653       // error
654     }
655   }
656   delete myThread;
657 }
658 // ================================================================
659 /*!
660  *  SALOME_InstallWizard::getBasePlatform
661  *  Determine the base platform for binaries installation
662  */
663 // ================================================================
664 QString SALOME_InstallWizard::getBasePlatform()
665 {
666   QString aBasePlt = "";
667   if ( platformsMap.find( curPlatform ) != platformsMap.end() )
668     aBasePlt = curPlatform;
669   else
670     aBasePlt = commonPlatform;
671   return aBasePlt;
672 }
673 // ================================================================
674 /*!
675  *  SALOME_InstallWizard::currentPlatform
676  *  Tries to determine the current user's operating system
677  */
678 // ================================================================
679 QStringList SALOME_InstallWizard::currentPlatform()
680 {
681   // file parsing
682   QString platName, platVersion, platArch;
683   QString osFileName = "/etc/issue";
684   if ( QFile::exists( osFileName ) ) {
685     QFile file( osFileName );
686     if ( file.open( IO_ReadOnly ) ) {
687       QTextStream stream( &file );
688       QStringList lines = QStringList::split( "\n", stream.read() );
689       file.close();
690       for ( uint i = 0; i < lines.count(); i++ ) {
691         QString str = lines[i];
692         if ( str.isEmpty() ) continue;
693         // parse line
694         QRegExp regvar = QRegExp( "(.*)\\s+[^\\s]*[R|r]elease[^\\s]*\\s+([\\d.]*)" );
695         int pos = regvar.search( str );
696         if ( pos == -1 ) {
697           regvar = QRegExp( "(.*)\\s+[^\\s]*[L|l][I|i][N|n][U|u][X|x][^\\s]*(.*)\\s+([\\d.]*)\\s+" );
698           pos = regvar.search( str );
699         }
700         if ( pos >= 0 ) {
701           QStringList name;
702           for ( int i = 1; i < regvar.numCaptures(); i++ )
703             name.append( regvar.cap( i ) );
704
705           // retrieve platform name
706           platName = QStringList::split( " ", name.join( " " ) ).join( " " );
707           platName = platName.replace( "Linux", "" ).replace( "linux", "" ).replace( "LINUX", "" ).stripWhiteSpace();
708           platName = platName.replace( "Welcome to", "" ).stripWhiteSpace();
709           platName = QStringList::split( " ", platName ).join( " " );
710           // retrieve platform version number
711           platVersion = regvar.cap( regvar.numCaptures() );
712           // retrieve platform 
713           utsname uname_data;
714           uname( &uname_data );
715           if ( QString( uname_data.machine ) == "x86_64" )
716             platArch = "64bit";
717           break;
718         }
719       }
720     }
721   }
722   QStringList vals;
723   if ( !platName.isEmpty() )    vals.append( platName ); 
724   if ( !platVersion.isEmpty() ) vals.append( platVersion ); 
725   if ( !platArch.isEmpty() )    vals.append( platArch ); 
726   return vals;
727 }
728
729 // ================================================================
730 /*!
731  *  SALOME_InstallWizard::rootDirPath
732  *  Get application root dir
733  */
734 // ================================================================
735 QString SALOME_InstallWizard::rootDirPath()
736 {
737   static QString rootDir;
738   if ( rootDir.isEmpty() ) {
739     QDir appDir( qApp->applicationDirPath() );
740     appDir.cdUp();
741     rootDir = appDir.absPath();
742   }
743   return rootDir;
744 }
745
746 // ================================================================
747 /*!
748  *  SALOME_InstallWizard::getPlatformBinPath
749  *  Get platform binaries path
750  */
751 // ================================================================
752 QString SALOME_InstallWizard::getPlatformBinPath( const QString& plt ) const
753 {
754   return QDir::cleanDirPath( getBinPath() + "/" + QStringList::split( " ", plt ).join( "_" ) );
755 }
756
757 // ================================================================
758 /*!
759  *  SALOME_InstallWizard::getXmlMap
760  *  Creates a map of the supported operating systems and 
761  *  corresponding XML files.
762  */
763 // ================================================================
764 MapXmlFiles SALOME_InstallWizard::getXmlMap( const QString& aXmlFileName )
765 {
766   MapXmlFiles xmlMap;
767   QStringList xmlList;
768   if ( !aXmlFileName.isEmpty() )
769     xmlList.append( QFileInfo( aXmlFileName ).absFilePath() );
770   else {
771     QDir dir( rootDirPath() );
772     QStringList entries = dir.entryList( "*.xml", QDir::Files | QDir::Readable );
773     if ( entries.remove( "config.xml" ) )
774       entries.append( "config.xml" );
775     for ( uint i = 0; i < entries.count(); i++ )
776       xmlList.append( QDir( rootDirPath() ).filePath( entries[i] ) ); 
777   }
778   // XML files parsing
779   QFile file;
780   QDomDocument doc( "xml_doc" );
781   QDomElement docElem;
782   QDomNodeList nodeList;
783   QDomNode node;
784   QDomElement elem;
785   QString platforms = "";
786   QStringList platList;
787   for ( uint i = 0; i < xmlList.count(); i++ ) {
788     file.setName( xmlList[i] );
789     if ( !doc.setContent( &file ) ) {
790       file.close();
791       continue;
792     }
793     file.close();
794     
795     docElem = doc.documentElement();
796     nodeList = docElem.elementsByTagName( "config" );
797     if ( nodeList.count() == 0 )
798       continue;      
799     node = nodeList.item( 0 );
800     if ( node.isElement() ) {
801       elem = node.toElement();
802       if ( elem.attribute( "platforms" ) ) {
803         platforms = elem.attribute( "platforms" ).stripWhiteSpace();
804         QStringList platList = QStringList::split( ",", platforms );
805         for ( uint j = 0; j < platList.count(); j++ ) {
806           QString platform = platList[j].stripWhiteSpace();
807           if ( !platform.isEmpty() && xmlMap.find( platform ) == xmlMap.end() )
808             xmlMap[ platList[j] ] = xmlList[i];
809         }
810       }
811     }
812   }
813   return xmlMap;
814 }
815 // ================================================================
816 /*!
817  *  SALOME_InstallWizard::checkXmlAndPlatform
818  *  Check XML file and current platform definition
819  */
820 // ================================================================
821 void SALOME_InstallWizard::getXmlAndPlatform()
822 {
823   MapXmlFiles xmlMap;
824   if ( xmlFileName.isEmpty() ) {
825     xmlMap = getXmlMap();
826     if ( !curPlatform.isEmpty() ) {
827       // try to get XML file for current platform
828       if ( xmlMap.find( curPlatform ) != xmlMap.end() ) {
829         xmlFileName = xmlMap[ curPlatform ];
830         QFileInfo fibp( getPlatformBinPath( curPlatform ) );
831         if ( !fibp.isDir() ) {
832           warnMsg = tr( "Binaries are absent for current platform" );
833         }
834         platformsMap = xmlMap;
835       }
836       else {
837         platformsMap = xmlMap;
838         warnMsg = tr( "Your Linux platform is not supported by this SALOME package" );
839       }
840     }
841     else {
842       // get all supported platforms
843       platformsMap = xmlMap;
844       warnMsg = tr( "Installation Wizard can't identify target Linux platform" );
845     }
846   }
847   else {
848     xmlMap = getXmlMap( xmlFileName );
849     if ( !curPlatform.isEmpty() ) {
850       // check that the user's XML file supports current platform
851       if ( xmlMap.find( curPlatform ) == xmlMap.end() ) {
852         platformsMap = getXmlMap();
853         MapXmlFiles::Iterator it;
854         for ( it = xmlMap.begin(); it != xmlMap.end(); ++it )
855           platformsMap.insert( it.key(), it.data(), true );
856         warnMsg = tr( "The given configuration file doesn't support your Linux platform" );
857       }
858       else {
859         platformsMap = xmlMap;
860       }
861     }
862     else {
863       // get all supported platforms
864       platformsMap = getXmlMap();
865       MapXmlFiles::Iterator it;
866       for ( it = xmlMap.begin(); it != xmlMap.end(); ++it )
867         platformsMap.insert( it.key(), it.data(), true );
868       warnMsg = tr( "Installation Wizard can't define your Linux platform" );
869     }
870   }
871 }
872 // ================================================================
873 /*!
874  *  SALOME_InstallWizard::eventFilter
875  *  Event filter, spies for Help window closing
876  */
877 // ================================================================
878 bool SALOME_InstallWizard::eventFilter( QObject* object, QEvent* event )
879 {
880   if ( object && object == helpWindow && event->type() == QEvent::Close )
881     helpWindow = NULL;
882   return InstallWizard::eventFilter( object, event );
883 }
884 // ================================================================
885 /*!
886  *  SALOME_InstallWizard::closeEvent
887  *  Close event handler
888  */
889 // ================================================================
890 void SALOME_InstallWizard::closeEvent( QCloseEvent* ce )
891 {
892   if ( WarnDialog::isWarnDlgShown() ) {
893     ce->ignore();
894     return;
895   }
896   if ( !exitConfirmed ) {
897     if ( QMessageBox::information( this,
898                                    tr( "Exit" ),
899                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
900                                    tr( "&Yes" ),
901                                    tr( "&No" ),
902                                    QString::null,
903                                    0,
904                                    1 ) == 1 ) {
905       ce->ignore();
906     }
907     else {
908       ce->accept();
909       exitConfirmed = true;
910       reject();
911     }
912   }
913 }
914 // ================================================================
915 /*!
916  *  SALOME_InstallWizard::setupIntroPage
917  *  Creates introduction page
918  */
919 // ================================================================
920 void SALOME_InstallWizard::setupIntroPage()
921 {
922   // create page
923   introPage = new QWidget( this, "IntroPage" );
924   QGridLayout* pageLayout = new QGridLayout( introPage );
925   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
926   // create logo picture
927   logoLab = new QLabel( introPage );
928   logoLab->setPixmap( pixmap( pxBigLogo ) );
929   logoLab->setScaledContents( false );
930   logoLab->setFrameStyle( QLabel::Plain | QLabel::NoFrame );
931   logoLab->setAlignment( AlignCenter );
932   // create version box
933   QVBox* versionBox = new QVBox( introPage ); versionBox->setSpacing( 6 );
934   versionBox->setFrameStyle( QVBox::Panel | QVBox::Sunken );
935   QWidget* stretch1 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch1, 5 );
936   versionLab = new QLabel( QString("%1 %2").arg( tr( "Version" ) ).arg(myVersion), versionBox );
937   versionLab->setAlignment( AlignCenter );
938   copyrightLab = new QLabel( myCopyright, versionBox );
939   copyrightLab->setAlignment( AlignCenter );
940   licenseLab = new QLabel( myLicense, versionBox );
941   licenseLab->setAlignment( AlignCenter );
942   QWidget* stretch2 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch2, 5 );
943   // create info box
944   info = new QLabel( introPage );
945   info->setText( tr( "This program will install <b>%1</b>."
946                      "<br><br>The wizard will also help you to install all products "
947                      "which are necessary for <b>%2</b> and setup "
948                      "your environment.<br><br>Click <code>Cancel</code> button to abort "
949                      "installation and quit. Click <code>Next</code> button to continue with the "
950                      "installation program." ).arg( myCaption ).arg( myCaption ) );
951   info->setFrameStyle( QLabel::WinPanel | QLabel::Sunken );
952   info->setMargin( 6 );
953   info->setAlignment( WordBreak );
954   info->setMinimumWidth( 250 );
955   QPalette pal = info->palette();
956   pal.setColor( QColorGroup::Background, QApplication::palette().active().base() );
957   info->setPalette( pal );
958   info->setLineWidth( 2 );
959   // layouting
960   pageLayout->addWidget( logoLab, 0, 0 );
961   pageLayout->addWidget( versionBox, 1, 0 );
962   pageLayout->addMultiCellWidget( info, 0, 1, 1, 1 );
963   pageLayout->setColStretch( 1, 5 );
964   pageLayout->setRowStretch( 1, 5 );
965   // adding page
966   addPage( introPage, tr( "Introduction" ) );
967 }
968 // ================================================================
969 /*!
970  *  SALOME_InstallWizard::setupTypePage
971  *  Creates installation types page
972  */
973 // ================================================================
974 void SALOME_InstallWizard::setupTypePage()
975 {
976   // create page
977   typePage = new QWidget( this, "TypePage" );
978   QGridLayout* pageLayout = new QGridLayout( typePage );
979   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
980   // create installation type button group
981   buttonGrp = new QButtonGroup( typePage );
982   buttonGrp->setFrameShape(QButtonGroup::NoFrame);
983   QGridLayout* buttonGrpLayout = new QGridLayout( buttonGrp );
984   buttonGrpLayout->setMargin( 0 ); buttonGrpLayout->setSpacing( 6 );
985   QSpacerItem* spacer1 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
986   QSpacerItem* spacer2 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
987   QLabel* selectLab = new QLabel( tr( "Select a type of the installation:" ), buttonGrp );
988   QSpacerItem* spacer3 = new QSpacerItem( 20, 20, QSizePolicy::Fixed, QSizePolicy::Minimum );
989   // ... 'install binaries' layout
990   QGridLayout* binLayout = new QGridLayout( 2, 2, 0 );
991   binBtn = new QRadioButton( tr( "Install binaries" ), buttonGrp );
992   QFont rbFont = binBtn->font();
993   rbFont.setBold( true );
994   binBtn->setFont( rbFont );
995   QSpacerItem* spacer4 = new QSpacerItem( 16, 16, QSizePolicy::Fixed, QSizePolicy::Minimum );
996   QLabel* binLab = new QLabel( tr( "- all the binaries and sources of the chosen SALOME modules will be installed.\n"
997                                    "- all the binaries of the chosen prerequisites will be installed." ), 
998                                buttonGrp );
999   binLayout->addMultiCellWidget( binBtn,  0, 0, 0, 1 );
1000   binLayout->addItem           ( spacer4, 1,    0    );
1001   binLayout->addWidget         ( binLab,  1,    1    );
1002   // ... 'install sources' layout
1003   QGridLayout* srcLayout = new QGridLayout( 2, 2, 0 );
1004   srcBtn = new QRadioButton( tr( "Install sources" ), buttonGrp );
1005   srcBtn->setFont( rbFont );
1006   QSpacerItem* spacer5 = new QSpacerItem( 16, 16, QSizePolicy::Fixed, QSizePolicy::Minimum );
1007   QLabel* srcLab = new QLabel( tr( "- all the sources of the chosen modules and prerequisites will be installed without\ncompilation." ), 
1008                                buttonGrp );
1009   srcLayout->addMultiCellWidget( srcBtn,  0, 0, 0, 1 );
1010   srcLayout->addItem           ( spacer5, 1,    0    );
1011   srcLayout->addWidget         ( srcLab,  1,    1    );
1012   // ... 'install sources and make compilation' layout
1013   QGridLayout* srcCompileLayout = new QGridLayout( 3, 3, 0 );
1014   srcCompileBtn = new QRadioButton( tr( "Install sources and make a compilation" ), buttonGrp );
1015   srcCompileBtn->setFont( rbFont );
1016   QSpacerItem* spacer6 = new QSpacerItem( 16, 16, QSizePolicy::Fixed, QSizePolicy::Minimum );
1017   QLabel* srcCompileLab1 = new QLabel( tr( "- all the sources of the chosen modules and prerequisites will be installed and\ncompiled." ), 
1018                                        buttonGrp );
1019   QLabel* srcCompileLab2 = new QLabel( tr( "Note:" ), 
1020                                        buttonGrp );
1021   QFont noteFont = srcCompileLab2->font();
1022   noteFont.setUnderline( true );
1023   srcCompileLab2->setFont( noteFont );
1024   srcCompileLab2->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) );
1025   srcCompileLab2->setAlignment( Qt::AlignHCenter | Qt::AlignTop );
1026   QLabel* srcCompileLab3 = new QLabel( " " + 
1027                                        tr( "it is a long time operation and it can take more than 24 hours depending\n on the computer." ), 
1028                                        buttonGrp );
1029   removeSrcBtn = new QCheckBox( tr( "Remove sources and temporary files after compilation" ), typePage );
1030   setAboutInfo( removeSrcBtn, tr( "Check this option if you want to remove sources of the products\nwith all the temporary files after build finishing" ) );
1031   removeSrcBtn->setChecked( false );
1032   removeSrcBtn->setEnabled( false );
1033   rmSrcPrevState = removeSrcBtn->isChecked();
1034
1035   srcCompileLayout->addMultiCellWidget( srcCompileBtn,  0, 0, 0, 2 );
1036   srcCompileLayout->addMultiCell      ( spacer6,        1, 2, 0, 0 );
1037   srcCompileLayout->addMultiCellWidget( srcCompileLab1, 1, 1, 1, 2 );
1038   srcCompileLayout->addWidget         ( srcCompileLab2, 2,    1    );
1039   srcCompileLayout->addWidget         ( srcCompileLab3, 2,    2    );
1040   srcCompileLayout->addMultiCellWidget( removeSrcBtn,   3, 3, 1, 2 );
1041   // layout widgets in the button group
1042   buttonGrpLayout->addItem           ( spacer1,          0,    1    );
1043   buttonGrpLayout->addMultiCellWidget( selectLab,        1, 1, 0, 1 );
1044   buttonGrpLayout->addMultiCell      ( spacer3,          2, 4, 0, 0 );
1045   buttonGrpLayout->addLayout         ( binLayout,        2,    1    );
1046   buttonGrpLayout->addLayout         ( srcLayout,        3,    1    );
1047   buttonGrpLayout->addLayout         ( srcCompileLayout, 4,    1    );
1048   buttonGrpLayout->addItem           ( spacer2,          5,    1    );
1049   // layout button group at the page
1050   pageLayout->addWidget( buttonGrp, 0, 0 );
1051   // connecting signals
1052   connect( buttonGrp, SIGNAL( clicked(int) ), this, SLOT ( onButtonGroup(int) ) );
1053   // adding page
1054   addPage( typePage, tr( "Installation type" ) );
1055 }
1056 // ================================================================
1057 /*!
1058  *  SALOME_InstallWizard::setupPlatformPage
1059  *  Creates platforms page, if necessary
1060  */
1061 // ================================================================
1062 void SALOME_InstallWizard::setupPlatformPage()
1063 {
1064   // create page
1065   platformsPage = new QWidget( this, "PlatformsPage" );
1066   QGridLayout* pageLayout = new QGridLayout( platformsPage );
1067   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1068   // create warning labels
1069   QLabel* warnLab2 = new QLabel( tr( "WARNING!" ), platformsPage );
1070   warnLab2->setAlignment( Qt::AlignHCenter );
1071   QFont fnt = warnLab2->font();
1072   fnt.setBold( true );
1073   warnLab2->setFont( fnt );
1074   warnLab = new QLabel( warnMsg, platformsPage );
1075   warnLab->setAlignment( Qt::AlignHCenter | Qt::WordBreak );
1076   warnLab3 = new QLabel( tr( "If you want to proceed anyway, please select platform from the following list:" ), 
1077                                  platformsPage );
1078   warnLab3->setAlignment( Qt::AlignHCenter | Qt::WordBreak );
1079   // create button group
1080   platBtnGrp = new QButtonGroup( platformsPage );
1081   platBtnGrp->setFrameShape(QButtonGroup::LineEditPanel);
1082   platBtnGrp->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) );
1083   QVBoxLayout* platBtnGrpLayout = new QVBoxLayout( platBtnGrp );
1084   platBtnGrpLayout->setMargin( 11 ); platBtnGrpLayout->setSpacing( 6 );
1085   // create platforms radio-buttons
1086   QString plat;
1087   MapXmlFiles::Iterator it;
1088   for ( it = platformsMap.begin(); it != platformsMap.end(); ++it ) {
1089     plat = it.key();
1090     QRadioButton* rb = new QRadioButton( plat, platBtnGrp, plat );
1091     platBtnGrpLayout->addWidget( rb );
1092   }
1093   // create spacers
1094   QSpacerItem* spacer1 = new QSpacerItem( 16, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
1095   QSpacerItem* spacer2 = new QSpacerItem( 16, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
1096
1097   // layout widgets on page
1098   pageLayout->addItem           ( spacer1,    0,    0    );
1099   pageLayout->addWidget         ( warnLab2,   1,    0    );
1100   pageLayout->addWidget         ( warnLab,    2,    0    );
1101   pageLayout->addWidget         ( warnLab3,   3,    0    );
1102   pageLayout->addItem           ( spacer2,    4,    0    );
1103   pageLayout->addMultiCellWidget( platBtnGrp, 0, 4, 1, 1 );
1104
1105   // connecting signals
1106   connect( platBtnGrp, SIGNAL( clicked(int) ), this, SLOT ( onButtonGroup(int) ) );
1107
1108   // adding page
1109   addPage( platformsPage, tr( "Installation platform" ) );
1110 }
1111 // ================================================================
1112 /*!
1113  *  SALOME_InstallWizard::setupDirPage
1114  *  Creates directories page
1115  */
1116 // ================================================================
1117 void SALOME_InstallWizard::setupDirPage()
1118 {
1119   // create page
1120   dirPage = new QWidget( this, "DirPage" );
1121   QGridLayout* pageLayout = new QGridLayout( dirPage );
1122   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1123   QSpacerItem* spacer1 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
1124   QSpacerItem* spacer2 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
1125   // target directory
1126   QGridLayout* targetLayout = new QGridLayout( 2, 2, 0 );
1127   QLabel* targetLab = new QLabel( tr( "Set a target directory to install SALOME platform:" ), dirPage );
1128   targetFolder = new QLineEdit( dirPage );
1129   targetBtn = new QPushButton( tr( "Browse..." ), dirPage );
1130   setAboutInfo( targetBtn, tr( "Click this button to browse\nthe installation directory" ) );
1131   targetLayout->addMultiCellWidget( targetLab,    0, 0, 0, 1 );
1132   targetLayout->addWidget         ( targetFolder, 1,    0    );
1133   targetLayout->addWidget         ( targetBtn,    1,    1    );
1134   // temporary directory
1135   QGridLayout* tempLayout = new QGridLayout( 2, 2, 0 );
1136   QLabel* tempLab = new QLabel( tr( "Set a directory that should be used for temporary SALOME files:" ), dirPage );
1137   tempFolder = new QLineEdit( dirPage );
1138   tempBtn = new QPushButton( tr( "Browse..." ), dirPage );
1139   setAboutInfo( tempBtn, tr( "Click this button to browse\nthe temporary directory" ) );
1140   tempLayout->addMultiCellWidget( tempLab,    0, 0, 0, 1 );
1141   tempLayout->addWidget         ( tempFolder, 1,    0    );
1142   tempLayout->addWidget         ( tempBtn,    1,    1    );
1143   // AKL: 13/08/07 - disable temporary directory setting in GUI ==>
1144   tempLab->hide();
1145   tempFolder->hide();
1146   tempBtn->hide();
1147   // AKL: 13/08/07 - disable temporary directory setting in GUI <==
1148   // layout widgets
1149   pageLayout->addItem  ( spacer1,      0, 0 );
1150   pageLayout->addLayout( targetLayout, 1, 0 );
1151   pageLayout->addLayout( tempLayout,   2, 0 );
1152   pageLayout->addItem  ( spacer2,      3, 0 );
1153   // connecting signals
1154   connect( targetFolder,  SIGNAL( textChanged( const QString& ) ),
1155            this,          SLOT( directoryChanged( const QString& ) ) );
1156   connect( targetBtn,     SIGNAL( clicked() ), 
1157            this,          SLOT( browseDirectory() ) );
1158   connect( tempFolder,    SIGNAL( textChanged( const QString& ) ),
1159            this,          SLOT( directoryChanged( const QString& ) ) );
1160   connect( tempBtn,       SIGNAL( clicked() ), this, SLOT( browseDirectory() ) );
1161
1162   // adding page
1163   addPage( dirPage, tr( "Installation directory" ) );
1164 }
1165 // ================================================================
1166 /*!
1167  *  SALOME_InstallWizard::setupProductsPage
1168  *  Creates products page
1169  */
1170 // ================================================================
1171 void SALOME_InstallWizard::setupProductsPage()
1172 {
1173   // create page
1174   productsPage = new QWidget( this, "ProductsPage" );
1175   QGridLayout* pageLayout = new QGridLayout( productsPage );
1176   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1177   //
1178   // create left column widgets
1179   //
1180   QVBoxLayout* leftBoxLayout = new QVBoxLayout;
1181   leftBoxLayout->setMargin( 0 ); leftBoxLayout->setSpacing( 6 );
1182   // ... modules list
1183   modulesView = new ProductsView( productsPage, "modulesView" );
1184   setAboutInfo( modulesView, tr( "The modules available for the installation" ) );
1185   modulesView->setColumnAlignment( 1, Qt::AlignRight );
1186   leftBoxLayout->addWidget( modulesView );
1187   // ... 'Installation with GUI' checkbox
1188   installGuiBtn = new QMyCheckBox( tr( "Installation with GUI" ), productsPage );
1189   setAboutInfo( installGuiBtn, tr( "Check this option if you want\nto install SALOME with GUI" ) );
1190   leftBoxLayout->addWidget( installGuiBtn );
1191   // ... prerequisites list
1192   prereqsView = new ProductsView( productsPage, "prereqsView" );
1193   prereqsView->renameColumn( 0, "Prerequisite" );
1194   setAboutInfo( prereqsView, tr( "The prerequisites that can be installed" ) );
1195   prereqsView->setColumnAlignment( 1, Qt::AlignRight );
1196   leftBoxLayout->addWidget( prereqsView );
1197   // ... 'Show/Hide prerequisites' button
1198   moreBtn = new QPushButton( tr( "Show prerequisites..." ), productsPage );
1199   setAboutInfo( moreBtn, tr( "Click to show list of prerequisites" ) );
1200   leftBoxLayout->addWidget( moreBtn );
1201   //
1202   // create right column widgets
1203   //
1204   // ... info box
1205   productInfo = new QTextBrowser( productsPage );
1206   productInfo->setFrameShape( QFrame::LineEditPanel );
1207   productInfo->setPaletteBackgroundColor( productsPage->paletteBackgroundColor() );
1208   setAboutInfo( productInfo, tr( "Short information about the product being selected" ) );
1209   // ... disk space labels
1210   QLabel* reqLab1 = new QLabel( tr( "Disk space required:" ), productsPage );
1211   setAboutInfo( reqLab1, tr( "Total disk space required for the installation\nof the selected products" ) );
1212   requiredSize = new QLabel( productsPage );
1213   setAboutInfo( requiredSize, tr( "Total disk space required for the installation\nof the selected products" ) );
1214   requiredSize->setAlignment( Qt::AlignRight );
1215   QLabel* reqLab2 = new QLabel( tr( "Space for temporary files:" ), productsPage );
1216   setAboutInfo( reqLab2, tr( "Disk space required for the temporary files" ) );
1217   requiredTemp = new QLabel( productsPage );
1218   setAboutInfo( requiredTemp, tr( "Disk space required for the temporary files" ) );
1219   requiredTemp->setAlignment( Qt::AlignRight );
1220   QLabel* reqLab3 = new QLabel( tr( "Available disk space:" ), productsPage );
1221   setAboutInfo( reqLab3, tr( "Disk space available on the selected device" ) );
1222   availableSize = new QLabel( productsPage );
1223   setAboutInfo( availableSize, tr( "Disk space available on the selected device" ) );
1224   availableSize->setAlignment( Qt::AlignRight );
1225   // layout size widgets
1226   QGridLayout* sizeLayout = new QGridLayout; sizeLayout->setMargin( 0 ); sizeLayout->setSpacing( 6 );
1227   sizeLayout->addWidget( reqLab1,       0, 0 );
1228   sizeLayout->addWidget( requiredSize,  0, 1 );
1229   sizeLayout->addWidget( reqLab2,       1, 0 );
1230   sizeLayout->addWidget( requiredTemp,  1, 1 );
1231   sizeLayout->addWidget( reqLab3,       2, 0 );
1232   sizeLayout->addWidget( availableSize, 2, 1 );
1233   // ... 'single installation directory' check-boxes
1234   oneModDirBtn = new QMyCheckBox( tr( "Install modules to a single directory" ), productsPage );
1235   setAboutInfo( oneModDirBtn, tr( "Check this box if you want to install binaries of\nthe selected SALOME modules into a single directory" ) );
1236   oneProdDirBtn = new QMyCheckBox( tr( "Install prerequisites to a single directory" ), productsPage );
1237   setAboutInfo( oneProdDirBtn, tr( "Check this box if you want to install binaries of\nthe selected prerequisites into a single directory" ) );
1238   oneProdDirBtn->hide(); // temporarily! waiting for correct prerequisites availability
1239   QFrame* split_line = new QFrame( productsPage, "split_line" );
1240   split_line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
1241
1242   // layout common widgets
1243   pageLayout->addMultiCellLayout( leftBoxLayout, 0, 4, 0, 0 );
1244   pageLayout->addWidget         ( productInfo,   0,    1    );
1245   pageLayout->addLayout         ( sizeLayout,    1,    1    );
1246   pageLayout->addWidget         ( split_line,    2,    1    );
1247   pageLayout->addWidget         ( oneModDirBtn,  3,    1    );
1248   pageLayout->addWidget         ( oneProdDirBtn, 4,    1    );
1249
1250   // adding page
1251   addPage( productsPage, tr( "Choice of the products to be installed" ) );
1252
1253   // connecting signals
1254   connect( modulesView,   SIGNAL( selectionChanged() ),
1255            this, SLOT( onSelectionChanged() ) );
1256   connect( prereqsView,   SIGNAL( selectionChanged() ),
1257            this, SLOT( onSelectionChanged() ) );
1258   connect( modulesView,   SIGNAL( clicked ( QListViewItem * item ) ),
1259            this, SLOT( onSelectionChanged() ) );
1260   connect( prereqsView,   SIGNAL( clicked ( QListViewItem * item ) ),
1261            this, SLOT( onSelectionChanged() ) );
1262   connect( modulesView,   SIGNAL( itemToggled( QCheckListItem* ) ),
1263            this, SLOT( onItemToggled( QCheckListItem* ) ) );
1264   connect( prereqsView,   SIGNAL( itemToggled( QCheckListItem* ) ),
1265            this, SLOT( onItemToggled( QCheckListItem* ) ) );
1266   connect( installGuiBtn, SIGNAL( toggled( bool ) ), 
1267            this, SLOT( onInstallGuiBtn() ) );
1268   connect( moreBtn, SIGNAL( clicked() ), this, SLOT( onMoreBtn() ) );
1269   // start on default - non-advanced mode
1270   prereqsView->hide();
1271 }
1272 // ================================================================
1273 /*!
1274  *  SALOME_InstallWizard::setupCheckPage
1275  *  Creates prestart page
1276  */
1277 // ================================================================
1278 void SALOME_InstallWizard::setupCheckPage()
1279 {
1280   // create page
1281   prestartPage = new QWidget( this, "PrestartPage" );
1282   QVBoxLayout* pageLayout = new QVBoxLayout( prestartPage );
1283   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1284   // choice text view
1285   choices = new QTextEdit( prestartPage );
1286   choices->setReadOnly( true );
1287   choices->setTextFormat( RichText );
1288   choices->setUndoRedoEnabled ( false );
1289   setAboutInfo( choices, tr( "Information about the installation choice you have made" ) );
1290   choices->setPaletteBackgroundColor( prestartPage->paletteBackgroundColor() );
1291   choices->setMinimumHeight( 10 );
1292   // layouting
1293   pageLayout->addWidget( choices );
1294   pageLayout->setStretchFactor( choices, 5 );
1295   // adding page
1296   addPage( prestartPage, tr( "Check your choice" ) );
1297 }
1298 // ================================================================
1299 /*!
1300  *  SALOME_InstallWizard::setupProgressPage
1301  *  Creates progress page
1302  */
1303 // ================================================================
1304 void SALOME_InstallWizard::setupProgressPage()
1305 {
1306   // create page
1307   progressPage = new QWidget( this, "progressPage" );
1308   QGridLayout* pageLayout = new QGridLayout( progressPage );
1309   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1310   // top splitter
1311   splitter = new QSplitter( Vertical, progressPage );
1312   splitter->setOpaqueResize( true );
1313   // the parent for the widgets
1314   QWidget* widget = new QWidget( splitter );
1315   QGridLayout* layout = new QGridLayout( widget );
1316   layout->setMargin( 0 ); layout->setSpacing( 6 );
1317   // installation progress view box
1318   installInfo = new InstallInfo( widget );
1319   installInfo->setReadOnly( true );
1320   installInfo->setTextFormat( RichText );
1321   installInfo->setUndoRedoEnabled ( false );
1322   installInfo->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
1323   installInfo->setMinimumSize( 100, 10 );
1324   setAboutInfo( installInfo, tr( "Installation process output" ) );
1325   // parameters for the script
1326   parametersLab = new QLabel( tr( "Enter your answer here:" ), widget );
1327   passedParams = new QLineEdit ( widget );
1328   setAboutInfo( passedParams, tr( "Use this field to enter the answer\nfor the running script when it is necessary") );
1329   // VSR: 10/11/05 - disable answer mode ==>
1330   parametersLab->hide();
1331   passedParams->hide();
1332   // VSR: 10/11/05 - disable answer mode <==
1333   // layouting
1334   layout->addWidget( installInfo,   0, 0 );
1335   layout->addWidget( parametersLab, 1, 0 );
1336   layout->addWidget( passedParams,  2, 0 );
1337   layout->addRowSpacing( 3, 6 );
1338   // the parent for the widgets
1339   widget = new QWidget( splitter );
1340   layout = new QGridLayout( widget );
1341   layout->setMargin( 0 ); layout->setSpacing( 6 );
1342   // installation results view box
1343   QLabel* resultLab = new QLabel( tr( "Installation Status:" ), widget );
1344   progressView = new ProgressView( widget );
1345   progressView->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
1346   progressView->setMinimumSize( 100, 10 );
1347   // possibility to ignore all errors
1348   ignoreErrCBox = new QCheckBox( tr( "Ignore errors" ), widget );
1349   setAboutInfo( ignoreErrCBox, tr( "Check this option if you want to proceed installation \nprocess even there will be some errors" ) );
1350   ignoreErrCBox->setChecked( false );
1351   // product installation status bar
1352   statusLab = new QLabel( widget );
1353   statusLab->setFrameShape( QButtonGroup::LineEditPanel );
1354   setAboutInfo( progressView, tr( "Installation status on the selected products" ) );
1355   // layouting
1356   layout->addRowSpacing( 0, 6 );
1357   layout->addWidget( resultLab,     1, 0 );
1358   layout->addWidget( progressView,  2, 0 );
1359   layout->addWidget( ignoreErrCBox, 3, 0 );
1360   layout->addWidget( statusLab,     4, 0 );
1361   // layouting
1362   pageLayout->addWidget( splitter,  0, 0 );
1363   // adding page
1364   addPage( progressPage, tr( "Installation progress" ) );
1365   // connect signals
1366   connect( passedParams, SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) ) ;
1367 }
1368 // ================================================================
1369 /*!
1370  *  SALOME_InstallWizard::setupReadmePage
1371  *  Creates readme page
1372  */
1373 // ================================================================
1374 void SALOME_InstallWizard::setupReadmePage()
1375 {
1376   // create page
1377   readmePage = new QWidget( this, "readmePage" );
1378   QVBoxLayout* pageLayout = new QVBoxLayout( readmePage );
1379   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1380   // README info text box
1381   readme = new QTextEdit( readmePage );
1382   readme->setReadOnly( true );
1383   readme->setTextFormat( PlainText );
1384   readme->setFont( QFont( "Fixed", 12 ) );
1385   readme->setUndoRedoEnabled ( false );
1386   setAboutInfo( readme, tr( "README information" ) );
1387   readme->setPaletteBackgroundColor( readmePage->paletteBackgroundColor() );
1388   readme->setMinimumHeight( 10 );
1389
1390   pageLayout->addWidget( readme );
1391   pageLayout->setStretchFactor( readme, 5 );
1392
1393   // Operation buttons
1394   QHBoxLayout* hLayout = new QHBoxLayout( -1, "finishButtons" );
1395   hLayout->setMargin( 0 ); hLayout->setSpacing( 6 );
1396   hLayout->addStretch();
1397   pageLayout->addLayout( hLayout );
1398
1399   // loading README file
1400   QString readmeFile = QDir( rootDirPath() ).filePath( "README" );
1401   QString text;
1402   if ( readFile( readmeFile, text ) )
1403     readme->setText( text );
1404   else
1405     readme->setText( tr( "README file has not been found" ) );
1406
1407   // adding page
1408   addPage( readmePage, tr( "Finish installation" ) );
1409 }
1410 // ================================================================
1411 /*!
1412  *  SALOME_InstallWizard::showChoiceInfo
1413  *  Displays choice info
1414  */
1415 // ================================================================
1416 void SALOME_InstallWizard::showChoiceInfo()
1417 {
1418   choices->clear();
1419
1420   long totSize, tempSize;
1421   checkSize( &totSize, &tempSize );
1422   int nbProd = 0;
1423   QString text;
1424
1425   text += tr( "Current Linux platform" )+ ": <b>" + (!curPlatform.isEmpty() ? curPlatform : QString( "Unknown" )) + "</b><br>";
1426   if ( !refPlatform.isEmpty() )
1427     text += tr( "Reference Linux platform" ) + ": <b>" + refPlatform + "</b><br>";
1428   text += "<br>";
1429
1430   text += tr( "Target directory:" ) + " <b>" + QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) + "</b><br>";
1431   text += tr( "Temporary directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
1432   text += "<br>";
1433
1434   text += tr( "SALOME modules to be installed" ) + ":<ul>";
1435   QCheckListItem* item = (QCheckListItem*)( modulesView->firstChild() );
1436   while( item ) {
1437     if ( productsMap.contains( item ) ) {
1438       if ( item->isOn() ) {
1439         text += "<li><b>" + item->text() + "</b><br>";
1440         nbProd++;
1441       }
1442     }
1443     item = (QCheckListItem*)( item->nextSibling() );
1444   }
1445   if ( nbProd == 0 ) {
1446     text += "<li><b>" + tr( "none" ) + "</b><br>";
1447   }
1448   text += "</ul>";
1449   nbProd = 0;
1450   text += tr( "Prerequisites to be installed" ) + ":<ul>";
1451   item = (QCheckListItem*)( prereqsView->firstChild() );
1452   while( item ) {
1453     if ( productsMap.contains( item ) ) {
1454       if ( item->isOn() ) {
1455         text += "<li><b>" + item->text() + " " + productsMap[ item ].getVersion() + "</b><br>";
1456         nbProd++;
1457       }
1458     }
1459     item = (QCheckListItem*)( item->nextSibling() );
1460   }
1461   if ( nbProd == 0 ) {
1462     text += "<li><b>" + tr( "none" ) + "</b><br>";
1463   }
1464   text += "</ul>";
1465   text += tr( "Total disk space required:" ) + " <b>" + QString::number( totSize ) + " KB</b><br>" ;
1466   text += tr( "Space for temporary files required:" ) + " <b>" + QString::number( tempSize ) + " KB</b><br>" ;
1467   choices->setText( text );
1468 }
1469 // ================================================================
1470 /*!
1471  *  SALOME_InstallWizard::acceptData
1472  *  Validates page when <Next> button is clicked
1473  */
1474 // ================================================================
1475 bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
1476 {
1477   QString tmpstr;
1478   QWidget* aPage = InstallWizard::page( pageTitle );
1479   if ( aPage == typePage ) {
1480     // installation type page
1481     warnLab3->show();
1482     this->setAppropriate( platformsPage, false );
1483     if ( installType == Binaries ) { // 'Binary' installation type
1484       // check binaries directory
1485       QFileInfo fib( QDir::cleanDirPath( getBinPath() ) );
1486       if ( !fib.isDir() ) {
1487         QMessageBox::warning( this,
1488                               tr( "Warning" ),
1489                               tr( "The directory %1 doesn't exist.\n"
1490                                   "This directory must contains another one directory with binary archives for current platform.").arg( fib.absFilePath() ),
1491                               QMessageBox::Ok,
1492                               QMessageBox::NoButton, 
1493                               QMessageBox::NoButton );
1494         return false;
1495       }
1496       if ( platformsMap.find( curPlatform ) == platformsMap.end() ) {
1497         // Unknown platform case
1498         QString aMsg = warnMsg + tr( ".\nBy default the universal binary package will be installed." );
1499         aMsg += tr( "\nIf you want to select another one, please use the following list:" );
1500         warnLab->setText( aMsg );
1501         warnLab3->hide();
1502         this->setAppropriate( platformsPage, true );
1503       }
1504       else {
1505         // Supported platform case
1506         QFileInfo fibp( getPlatformBinPath( curPlatform ) );
1507         if ( !fibp.isDir() ) {
1508           warnLab->setText( tr( "Binaries are absent for current platform." ) );
1509           this->setAppropriate( platformsPage, true );
1510         }
1511       }
1512
1513       // check sources directory
1514       QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
1515       if ( !fis.isDir() )
1516         if ( QMessageBox::warning( this,
1517                                    tr( "Warning" ),
1518                                    tr( "The directory %1 doesn't exist.\n"
1519                                        "This directory must contains sources archives.\n"
1520                                        "Continue?" ).arg( fis.absFilePath() ),
1521                                    tr( "&Yes" ),
1522                                    tr( "&No" ), 
1523                                    QString::null, 1, 1 ) == 1 )
1524           return false;
1525     }
1526     else { // 'Source' or 'Compile' installation type
1527       // check sources directory
1528       QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
1529       if ( !fis.isDir() ) {
1530         QMessageBox::warning( this,
1531                               tr( "Warning" ),
1532                               tr( "The directory %1 doesn't exist.\n"
1533                                   "This directory must contains sources archives.\n" ).arg( fis.absFilePath() ),
1534                               QMessageBox::Ok,
1535                               QMessageBox::NoButton, 
1536                               QMessageBox::NoButton );
1537         return false;
1538       }
1539       else if ( !QDir( fis.filePath(), "*.tar.gz" ).count() ) {
1540         QMessageBox::warning( this,
1541                               tr( "Warning" ),
1542                               tr( "The directory %1 doesn't contain source archives.\n" ).arg( fis.absFilePath() ),
1543                               QMessageBox::Ok,
1544                               QMessageBox::NoButton, 
1545                               QMessageBox::NoButton );
1546         return false;
1547       }
1548       if ( platformsMap.find( curPlatform ) == platformsMap.end() ) {
1549         QString aMsg = warnMsg + ".";
1550         if ( installType == Compile )
1551           aMsg = warnMsg + tr( " and compilation is not tested on this one." );
1552         warnLab->setText( aMsg );
1553         this->setAppropriate( platformsPage, true );
1554       }
1555     }
1556   }
1557
1558   else if ( aPage == platformsPage ) {
1559     // installation platform page
1560     if ( platBtnGrp->id( platBtnGrp->selected() ) == -1 ) {
1561       QMessageBox::warning( this,
1562                             tr( "Warning" ),
1563                             tr( "Select installation platform before" ),
1564                             QMessageBox::Ok,
1565                             QMessageBox::NoButton,
1566                             QMessageBox::NoButton );
1567       return false;
1568     }
1569     else if ( installType == Binaries ) {
1570       QString aPlatform = platBtnGrp->selected()->name();
1571       QFileInfo fib( getPlatformBinPath( aPlatform ) );
1572       if ( !fib.isDir() ) {
1573         QMessageBox::warning( this,
1574                               tr( "Warning" ),
1575                               tr( "The directory %1 doesn't exist.\n"
1576                                   "This directory must contains binary archives.\n" ).arg( fib.absFilePath() ),
1577                               QMessageBox::Ok,
1578                               QMessageBox::NoButton, 
1579                               QMessageBox::NoButton );
1580         return false;
1581       }
1582       else if ( QDir( fib.filePath(), "*.tar.gz" ).count() == 0 ) {
1583         QMessageBox::warning( this,
1584                               tr( "Warning" ),
1585                               tr( "The directory %1 doesn't contain binary archives.\n" ).arg( fib.absFilePath() ),
1586                               QMessageBox::Ok,
1587                               QMessageBox::NoButton, 
1588                               QMessageBox::NoButton );
1589         return false;
1590       }
1591     }
1592   }
1593
1594   else if ( aPage == dirPage ) {
1595     // installation directory page
1596     // ########## check target and temp directories (existence and available disk space)
1597     // get dirs
1598     QString targetDir = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1599     QString tempDir   = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() );
1600     // check target directory
1601     if ( targetDir.isEmpty() ) {
1602       QMessageBox::warning( this,
1603                             tr( "Warning" ),
1604                             tr( "Please, enter valid target directory path" ),
1605                             QMessageBox::Ok,
1606                             QMessageBox::NoButton,
1607                             QMessageBox::NoButton );
1608       return false;
1609     }
1610     QFileInfo fi( QDir::cleanDirPath( targetDir ) );
1611     if ( !fi.isDir() ) {
1612       bool toCreate =
1613         QMessageBox::warning( this,
1614                               tr( "Warning" ),
1615                               tr( "The directory %1 doesn't exist.\n"
1616                                   "Create directory?" ).arg( fi.absFilePath() ),
1617                               QMessageBox::Yes,
1618                               QMessageBox::No,
1619                               QMessageBox::NoButton ) == QMessageBox::Yes;
1620       if ( !toCreate)
1621         return false;
1622       if ( !makeDir( fi.absFilePath(), tmpstr ) ) {
1623         QMessageBox::critical( this,
1624                                tr( "Error" ),
1625                                tr( "Can't create the directory\n%1").arg( fi.absFilePath() ),
1626                                QMessageBox::Ok,
1627                                QMessageBox::NoButton,
1628                                QMessageBox::NoButton );
1629         return false;
1630       }
1631     }
1632     if ( !fi.isDir() ) {
1633       QMessageBox::warning( this,
1634                             tr( "Warning" ),
1635                             tr( "%1 is not a directory.\n"
1636                                 "Please, enter valid target directory path" ).arg( fi.absFilePath() ),
1637                             QMessageBox::Ok,
1638                             QMessageBox::NoButton,
1639                             QMessageBox::NoButton );
1640       return false;
1641     }
1642     if ( !fi.isWritable() ) {
1643       QMessageBox::warning( this,
1644                             tr( "Warning" ),
1645                             tr( "The directory %1 is not writable.\n"
1646                                 "Please, enter valid target directory path or change permissions" ).arg( fi.absFilePath() ),
1647                             QMessageBox::Ok,
1648                             QMessageBox::NoButton,
1649                             QMessageBox::NoButton );
1650       return false;
1651     }
1652     if ( hasSpace( fi.absFilePath() ) &&
1653          QMessageBox::warning( this,
1654                                tr( "Warning" ),
1655                                tr( "The target directory contains space symbols.\n"
1656                                    "This may cause problems with compiling or installing of products.\n\n"
1657                                    "Do you want to continue?"),
1658                                QMessageBox::Yes,
1659                                QMessageBox::No,
1660                                QMessageBox::NoButton ) == QMessageBox::No ) {
1661       return false;
1662     }
1663     // check temp directory
1664     if ( tempDir.isEmpty() ) {
1665       QMessageBox::warning( this,
1666                             tr( "Warning" ),
1667                             tr( "Please, enter valid temporary directory path" ),
1668                             QMessageBox::Ok,
1669                             QMessageBox::NoButton,
1670                             QMessageBox::NoButton );
1671       return false;
1672     }
1673     QFileInfo fit( QDir::cleanDirPath( tempDir ) );
1674     if ( !makeDir( fit.absFilePath() + TEMPDIRNAME, tmpCreated ) ) {
1675       QMessageBox::critical( this,
1676                              tr( "Error" ),
1677                              tr( "Can't use temporary directory.\nCheck permissions for the %1 directory.").arg( fit.absFilePath() ),
1678                              QMessageBox::Ok,
1679                              QMessageBox::NoButton,
1680                              QMessageBox::NoButton );
1681       return false;
1682     }
1683   }
1684
1685   else if ( aPage == productsPage ) {
1686     // products page
1687     // ########## check if any products are selected to be installed
1688     long totSize, tempSize;
1689     bool anySelected = checkSize( &totSize, &tempSize );
1690     if ( installType == Compile && removeSrcBtn->isOn() ) {
1691       totSize += tempSize;
1692     }
1693     if ( !anySelected ) {
1694       QMessageBox::warning( this,
1695                             tr( "Warning" ),
1696                             tr( "Select one or more products to install" ),
1697                             QMessageBox::Ok,
1698                             QMessageBox::NoButton,
1699                             QMessageBox::NoButton );
1700       return false;
1701     }
1702     // run script that checks available disk space for installing of products    // returns 1 in case of error
1703     QDir rd( rootDirPath() );
1704     QFileInfo fi( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) );
1705     Script script;
1706     script << QUOTE( rd.filePath( "config_files/checkSize.sh" ) );
1707     script << QUOTE( fi.absFilePath() ) << QString::number( totSize );
1708     ___MESSAGE___( "script = " << script.script().latin1() );
1709     if ( system( script.script().latin1() ) ) {
1710       QMessageBox::critical( this,
1711                              tr( "Out of space" ),
1712                              tr( "There is no available disk space for installing of selected products" ),
1713                              QMessageBox::Ok,
1714                              QMessageBox::NoButton,
1715                              QMessageBox::NoButton );
1716       return false;
1717     }
1718     // AKL: 13/08/07 - skip tmp disk space checking (all files are unpacked into installation directory) ==>
1719     /*
1720     // run script that check available disk space for temporary files
1721     // returns 1 in case of error
1722     QFileInfo fit( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) );
1723     Script tscript;
1724     tscript << QUOTE( rd.filePath( "config_files/checkSize.sh" ) );
1725     tscript << QUOTE( fit.absFilePath() ) << QString::number( tempSize );
1726     ___MESSAGE___( "script = " << tscript.script().latin1() );
1727     if ( system( tscript.script().latin1() ) ) {
1728       QMessageBox::critical( this,
1729                              tr( "Out of space" ),
1730                              tr( "There is no available disk space for the temporary files" ),
1731                              QMessageBox::Ok,
1732                              QMessageBox::NoButton,
1733                              QMessageBox::NoButton );
1734       return false;
1735       }
1736     */
1737     // AKL: 13/08/07 - skip tmp disk space checking (all files are unpacked into installation directory) <==
1738
1739     // ########## check installation scripts
1740     QCheckListItem* item;
1741     ProductsView* prodsView = modulesView;
1742     for ( int i = 0; i < 2; i++ ) {
1743       item = (QCheckListItem*)( prodsView->firstChild() );
1744       while( item ) {
1745         if ( productsMap.contains( item ) && item->isOn() ) {
1746           // check installation script definition
1747           if ( item->text(2).isEmpty() || item->text(2).isNull() ) {
1748             QMessageBox::warning( this,
1749                                   tr( "Error" ),
1750                                   tr( "The installation script for %1 is not defined.").arg(item->text(0)),
1751                                   QMessageBox::Ok,
1752                                   QMessageBox::NoButton,
1753                                   QMessageBox::NoButton );
1754             if ( !moreMode ) onMoreBtn();
1755             QListView* listView = item->listView();
1756             listView->setCurrentItem( item );
1757             listView->setSelected( item, true );
1758             listView->ensureItemVisible( item );
1759             return false;
1760           }
1761           // check installation script existence
1762           else {
1763             QDir rd( rootDirPath() );
1764             QFileInfo fi( rd.filePath( QString( "config_files/%1" ).arg( item->text(2) ) ) );
1765             if ( !fi.exists() || !fi.isExecutable() ) {
1766               QMessageBox::warning( this,
1767                                     tr( "Error" ),
1768                                     tr( "The script %1 required for %2 doesn't exist or doesn't have execute permissions.").arg(fi.filePath()).arg(item->text(0)),
1769                                     QMessageBox::Ok,
1770                                     QMessageBox::NoButton,
1771                                     QMessageBox::NoButton );
1772               if ( !moreMode ) onMoreBtn();
1773               QListView* listView = item->listView();
1774               listView->setCurrentItem( item );
1775               listView->setSelected( item, true );
1776               listView->ensureItemVisible( item );
1777               return false;
1778             }
1779           }
1780           // check installation scripts dependencies
1781           QStringList dependOn = productsMap[ item ].getDependancies();
1782           QString version = productsMap[ item ].getVersion();
1783           for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1784             QCheckListItem* depitem = findItem( dependOn[ i ] );
1785             if ( !depitem ) {
1786               QMessageBox::warning( this,
1787                                     tr( "Error" ),
1788                                     tr( "%1 is required for %2 %3 installation.\n"
1789                                         "This product is missing in the configuration file %4.").arg(dependOn[ i ]).arg(item->text(0)).arg(version).arg(xmlFileName),
1790                                     QMessageBox::Ok,
1791                                     QMessageBox::NoButton,
1792                                     QMessageBox::NoButton );
1793               return false;
1794             }
1795           }
1796         }
1797         item = (QCheckListItem*)( item->nextSibling() );
1798       }
1799       prodsView = prereqsView;
1800     }
1801 //     return true; // return in order to avoid default postValidateEvent() action
1802   }
1803   return InstallWizard::acceptData( pageTitle );
1804 }
1805 // ================================================================
1806 /*!
1807  *  SALOME_InstallWizard::checkSize
1808  *  Calculates disk space required for the installation
1809  */
1810 // ================================================================
1811 bool SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
1812 {
1813   long tots = 0, temps = 0;
1814   long maxSrcTmp = 0;
1815   int nbSelected = 0;
1816
1817   MapProducts::Iterator mapIter;
1818   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1819     QCheckListItem* item = mapIter.key();
1820     Dependancies dep = mapIter.data();
1821     if ( !item->isOn() )
1822       continue;
1823     tots += ( QStringList::split( " ", item->text(1) )[0] ).toLong();
1824     maxSrcTmp = max( maxSrcTmp, dep.getSize( Compile ) - dep.getSize( Binaries ) );
1825     temps += dep.getTempSize( installType );
1826     nbSelected++;
1827   }
1828
1829   if ( totSize )
1830     if ( installType == Compile && removeSrcBtn->isOn() )
1831       temps += maxSrcTmp;
1832     *totSize = tots;
1833   if ( tempSize )
1834     *tempSize = temps;
1835   return ( nbSelected > 0 );
1836 }
1837 // ================================================================
1838 /*!
1839  *  SALOME_InstallWizard::updateAvailableSpace
1840  *  Slot to update 'Available disk space' field
1841  */
1842 // ================================================================
1843 void SALOME_InstallWizard::updateAvailableSpace()
1844 {
1845   if ( diskSpaceProc->normalExit() )
1846     availableSize->setText( diskSpaceProc->readLineStdout() + " KB");
1847 }
1848 // ================================================================
1849 /*!
1850  *  SALOME_InstallWizard::runModifyLaFiles
1851  *  Run the modification of SALOME *.la files
1852  */
1853 // ================================================================
1854 void SALOME_InstallWizard::runModifyLaFiles()
1855 {
1856   modifyLaProc->clearArguments();
1857   // ... update status label
1858   statusLab->setText( tr( "Modification of *.la files of SALOME modules..." ) );
1859   // set process arguments
1860   modifyLaProc->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
1861   modifyLaProc->addArgument( "modifyLaFiles.sh" );
1862   modifyLaProc->addArgument( "modify_la_files" );
1863   modifyLaProc->addArgument( QDir::cleanDirPath( QFileInfo( targetFolder->text().stripWhiteSpace() ).absFilePath() ) );
1864   // ... run script
1865   if ( !modifyLaProc->start() )
1866     ___MESSAGE___( "Error: process could not start!" );
1867 }
1868 // ================================================================
1869 /*!
1870  *  SALOME_InstallWizard::checkModifyLaResult
1871  *  Slot to take result of modification SALOME *.la files
1872  */
1873 // ================================================================
1874 void SALOME_InstallWizard::checkModifyLaResult()
1875 {
1876   if ( modifyLaProc->normalExit() && modifyLaProc->exitStatus() == 1 )
1877     runCheckFLib();
1878   else {
1879     // abort of the current installation
1880     abort();
1881     statusLab->setText( tr( "Installation has been aborted" ) );
1882     QMessageBox::critical( this,
1883                            tr( "Error" ),
1884                            tr( "Modification of *.la SALOME files has not been completed."),
1885                            QMessageBox::Ok,
1886                            QMessageBox::NoButton,
1887                            QMessageBox::NoButton );
1888     // enable <Next> button
1889     setNextEnabled( true );
1890     doPostActions( tr( "&Start" ), tr( "Start installation process" ) );
1891     connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1892     // enable <Back> button
1893     setBackEnabled( true );
1894   }
1895 }
1896 // ================================================================
1897 /*!
1898  *  SALOME_InstallWizard::runCheckFLib
1899  *  Run the Fortran and other required libraries checking
1900  */
1901 // ================================================================
1902 void SALOME_InstallWizard::runCheckFLib()
1903 {
1904   // Check Fortran libraries
1905   checkFLibProc->clearArguments();
1906   // ... update status label
1907   statusLab->setText( tr( "Check Fortran and other required libraries..." ) );
1908   // ... search "not found" libraries
1909   checkFLibProc->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
1910   checkFLibProc->addArgument( "checkFortran.sh" );
1911   checkFLibProc->addArgument( "find_libraries" );
1912   checkFLibProc->addArgument( QDir::cleanDirPath( QFileInfo( targetFolder->text().stripWhiteSpace() ).absFilePath() ) );
1913   // ... run script
1914   if ( !checkFLibProc->start() )
1915     ___MESSAGE___( "Error: process could not start!" );
1916 }
1917 // ================================================================
1918 /*!
1919  *  SALOME_InstallWizard::checkFLibResult
1920  *  Slot to take result of Fortran and other required libraries checking
1921  */
1922 // ================================================================
1923 void SALOME_InstallWizard::checkFLibResult()
1924 {
1925   if ( checkFLibProc->normalExit() && checkFLibProc->exitStatus() == 1 ) {
1926     QStringList notFoundLibsList, notFoundOptLibsList;
1927     QString record = "";
1928     QStringList prefOptLibs = getOptionalLibs();
1929     // create list of strings with all 'not found' libraries
1930     while ( checkFLibProc->canReadLineStdout() ) {
1931       record = checkFLibProc->readLineStdout().stripWhiteSpace();
1932       if ( !record.isEmpty() ) {
1933         record = QStringList::split( " ", record )[0];
1934         if ( !notFoundLibsList.contains( record ) && 
1935              !notFoundOptLibsList.contains( record ) ) {
1936           bool isOptional = false;
1937           QStringList::Iterator it_opt;
1938           for ( it_opt = prefOptLibs.begin(); it_opt != prefOptLibs.end(); ++it_opt )
1939             if ( record.startsWith( (*it_opt).stripWhiteSpace(), false ) ) {
1940               isOptional = true;
1941               break;
1942             }
1943           isOptional ? notFoundOptLibsList.append( record )             \
1944             : notFoundLibsList.append( record );
1945         }
1946       }
1947     }
1948     QString msg = tr( "Some libraries are absent!<br><br>" );
1949     if ( !notFoundLibsList.isEmpty() ) {
1950       msg += tr( "One or several <b>mandatory</b> libraries listed below are not found. SALOME <u>may not work</u> properly.<br>" );
1951       msg += notFoundLibsList.join( "<br>" );
1952       msg += "<br><br>";
1953     }
1954     if ( !notFoundOptLibsList.isEmpty() ) {
1955       msg += tr( "One or several <b>optional</b> libraries listed below are not found. This <u>does not affect</u> on the correct work of SALOME platform.<br>" );
1956       msg += notFoundOptLibsList.join( "<br>" );
1957     }
1958     if ( !notFoundLibsList.isEmpty() )
1959       QMessageBox::warning( this,
1960                             tr( "Warning" ),
1961                             msg,
1962                             QMessageBox::Ok,
1963                             QMessageBox::NoButton,
1964                             QMessageBox::NoButton );
1965     else if ( !notFoundOptLibsList.isEmpty() )
1966       QMessageBox::information( this,
1967                                 tr( "Information" ),
1968                                 msg,
1969                                 QMessageBox::Ok,
1970                                 QMessageBox::NoButton,
1971                                 QMessageBox::NoButton );
1972   }
1973   // Update GUI and check installation errors
1974   completeInstallation();
1975 }
1976 // ================================================================
1977 /*!
1978  *  SALOME_InstallWizard::updateSizeColumn
1979  *  Sets required size for each product according to 
1980  *  installation type and 'Remove SRC & TMP' checkbox state
1981  */
1982 // ================================================================
1983 void SALOME_InstallWizard::updateSizeColumn()
1984 {
1985   long prodSize = 0;
1986   bool removeSrc = removeSrcBtn->isChecked();
1987   MapProducts::Iterator mapIter;
1988   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1989     QCheckListItem* item = mapIter.key();
1990     Dependancies dep = mapIter.data();
1991     // get required size for current product
1992     long binSize = dep.getSize( Binaries );
1993     long srcSize = dep.getSize( Sources );
1994     long bldSize = dep.getSize( Compile );
1995     InstallationType instType = getInstType();
1996     if ( instType == Binaries ) {
1997       if ( dep.getType() == "component" )
1998         prodSize = binSize + srcSize;
1999       else
2000         prodSize = ( binSize != 0 ? binSize : srcSize );
2001     }
2002     else if ( instType == Sources )
2003       prodSize = srcSize;
2004     else
2005       if ( removeSrc )
2006         prodSize = ( binSize != 0 ? binSize : srcSize );
2007       else {
2008         prodSize = ( bldSize != 0 ? bldSize : srcSize );
2009       }
2010     // fill in 'Size' field
2011     item->setText( 1, QString::number( prodSize )+" KB" );
2012   }
2013 }
2014 // ================================================================
2015 /*!
2016  *  SALOME_InstallWizard::checkProductPage
2017  *  Checks products page validity (directories and products selection) and
2018  *  enabled/disables "Next" button for the Products page
2019  */
2020 // ================================================================
2021 void SALOME_InstallWizard::checkProductPage()
2022 {
2023   if ( this->currentPage() != productsPage )
2024     return;
2025   long tots = 0, temps = 0;
2026   // check if any product is selected;
2027   bool isAnyProductSelected = checkSize( &tots, &temps );
2028
2029   // update required size information
2030   requiredSize->setText( QString::number( tots )  + " KB");
2031   requiredTemp->setText( QString::number( temps ) + " KB");
2032
2033   // update available size information
2034   QFileInfo fi( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) );
2035   if ( fi.exists() ) {
2036     diskSpaceProc->clearArguments();
2037     diskSpaceProc->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
2038     diskSpaceProc->addArgument( "diskSpace.sh" );
2039     diskSpaceProc->addArgument( fi.absFilePath() );
2040     // run script
2041     diskSpaceProc->start();
2042   }
2043
2044   // enable/disable "Next" button
2045   setNextEnabled( productsPage, isAnyProductSelected );
2046 }
2047 // ================================================================
2048 /*!
2049  *  SALOME_InstallWizard::setPrerequisites
2050  *  Sets the product and all products this one depends on to be checked ( recursively )
2051  */
2052 // ================================================================
2053 void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
2054 {
2055   if ( !productsMap.contains( item ) )
2056     return;
2057   if ( !item->isOn() )
2058     return;
2059   // get all prerequisites
2060   QStringList dependOn = productsMap[ item ].getDependancies();
2061   // install SALOME without GUI case
2062   if ( installGuiBtn->state() != QButton::On && 
2063        woGuiModules.find( item->text(0) ) != woGuiModules.end() && 
2064        woGuiModules[item->text(0)] == True ) {
2065     dependOn.remove( "GUI" );
2066   }
2067   // setting prerequisites
2068   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
2069     MapProducts::Iterator itProd;
2070     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2071       if ( itProd.data().getName() == dependOn[ i ] ) {
2072         if ( itProd.data().getType() == "component" && !itProd.key()->isOn() )
2073           itProd.key()->setOn( true );
2074         else if ( itProd.data().getType() == "prerequisite" ) {
2075           itProd.key()->setOn( true );
2076           itProd.key()->setEnabled( false );
2077         }
2078         break;
2079       }
2080     }
2081   }
2082 }
2083 // ================================================================
2084 /*!
2085  *  SALOME_InstallWizard::unsetPrerequisites
2086  *  Unsets all modules which depend of the unchecked product ( recursively )
2087  */
2088 // ================================================================
2089 void SALOME_InstallWizard::unsetPrerequisites( QCheckListItem* item )
2090 {
2091   if ( !productsMap.contains( item ) )
2092     return;
2093   if ( item->isOn() )
2094     return;
2095
2096 // uncheck dependent products
2097   QString itemName = productsMap[ item ].getName();
2098   MapProducts::Iterator itProd;
2099   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2100     if ( itProd.data().getType() == productsMap[ item ].getType() ) {
2101       QStringList dependOn = itProd.data().getDependancies();
2102       for ( int i = 0; i < (int)dependOn.count(); i++ ) {
2103         if ( dependOn[ i ] == itemName ) {
2104           if ( itProd.key()->isOn() ) {
2105             itProd.key()->setOn( false );
2106           }
2107         }
2108       }
2109     }
2110   }
2111
2112 // uncheck prerequisites
2113   int nbDependents;
2114 //   cout << "item name = " << productsMap[ item ].getName() << endl;
2115   QStringList dependOnList = productsMap[ item ].getDependancies();
2116   for ( int j = 0; j < (int)dependOnList.count(); j++ ) {
2117     nbDependents = 0;
2118     MapProducts::Iterator itProd1;
2119     for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
2120       if ( itProd1.data().getName() == dependOnList[ j ] ) {
2121         if ( itProd1.data().getType() == "prerequisite" ) {
2122           MapProducts::Iterator itProd2;
2123           for ( itProd2 = productsMap.begin(); itProd2 != productsMap.end(); ++itProd2 ) {
2124             if ( itProd2.key()->isOn() ) {
2125               QStringList prereqsList = productsMap[ itProd2.key() ].getDependancies();
2126               for ( int k = 0; k < (int)prereqsList.count(); k++ ) {
2127                 if ( prereqsList[ k ] == itProd1.data().getName() ) {
2128                   nbDependents++;
2129                   break;
2130                 }
2131               }
2132             }
2133           }
2134           if ( nbDependents == 0 ) {
2135             itProd1.key()->setEnabled( true );
2136             itProd1.key()->setOn( false );
2137           }
2138         }
2139         break;
2140       }
2141     }
2142   }
2143 }
2144 // ================================================================
2145 /*!
2146  *  SALOME_InstallWizard::launchScript
2147  *  Runs installation script
2148  */
2149 // ================================================================
2150 void SALOME_InstallWizard::launchScript()
2151 {
2152   // try to find product being processed now
2153   QString prodProc = progressView->findStatus( Processing );
2154   if ( !prodProc.isNull() ) {
2155     ___MESSAGE___( "Found <Processing>: " );
2156
2157     // if found - set status to "completed"
2158     progressView->setStatus( prodProc, Completed );
2159     // ... clear status label
2160     statusLab->clear();
2161     // ... and call this method again
2162     launchScript();
2163     return;
2164   }
2165   // else try to find next product which is not processed yet
2166   prodProc = progressView->findStatus( Waiting );
2167   if ( !prodProc.isNull() ) {
2168     ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
2169     // if found - set status to "processed" and run script
2170     progressView->setStatus( prodProc, Processing );
2171     progressView->ensureVisible( prodProc );
2172     
2173     QCheckListItem* item = 0;
2174     // fill in script parameters
2175     shellProcess->clearArguments();
2176     // ... script name
2177     shellProcess->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
2178     if ( !extraProducts.contains( prodProc ) ) {
2179       item = findItem( prodProc );
2180       shellProcess->addArgument( item->text(2) );
2181     }
2182     else
2183       shellProcess->addArgument( extraProducts[ prodProc ] );
2184
2185     // ... get folder with binaries
2186     QString OS = getPlatform();
2187     if ( refPlatform.isEmpty() && platformsMap.find( curPlatform ) == platformsMap.end() )
2188       OS = commonPlatform;
2189     QString binDir = getPlatformBinPath( OS );
2190     // ... temp folder
2191     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
2192     //if( !tempFolder->isEnabled() )
2193     //  tmpFolder = "/tmp";
2194
2195     // ... not install : try to find preinstalled
2196     if ( notInstall.contains( prodProc ) || prodProc == "gcc" ) {
2197       shellProcess->addArgument( "try_preinstalled" );
2198       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
2199       shellProcess->addArgument( QDir( rootDirPath() ).filePath( "Products" ) );
2200       statusLab->setText( tr( "Collecting environment for '" ) + prodProc + "'..." );
2201     }
2202     // ... binaries ?
2203     else if ( installType == Binaries ) {
2204       shellProcess->addArgument( "install_binary" );
2205       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
2206       shellProcess->addArgument( binDir );
2207       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
2208     }
2209     // ... sources or sources_and_compilation ?
2210     else {
2211       shellProcess->addArgument( installType == Sources ? "install_source" : 
2212                                  "install_source_and_build" );
2213       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
2214       shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
2215       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
2216     }
2217     // ... target folder
2218     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
2219     shellProcess->addArgument( QFileInfo( tgtFolder ).absFilePath() );
2220     // ... list of all products
2221     QString depproducts = getAllProducts(productsMap);
2222     depproducts.prepend( QStringList( extraProducts.keys() ).join(" ") + " " );
2223     ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
2224     shellProcess->addArgument( depproducts );
2225     // ... product name - currently installed product
2226     if ( !extraProducts.contains( prodProc ) )
2227       shellProcess->addArgument( item->text(0) );
2228     else
2229       shellProcess->addArgument( prodProc );
2230     // ... list of products being installed
2231     shellProcess->addArgument( prodSequence.join( " " ) );
2232     // ... sources directory
2233     shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
2234     // ... remove sources and tmp files or not?
2235     if ( installType == Compile && removeSrcBtn->isOn() )
2236       shellProcess->addArgument( "TRUE" );
2237     else 
2238       shellProcess->addArgument( "FALSE" );
2239     // ... binaries directory
2240     shellProcess->addArgument( binDir );
2241     // ... install SALOME with GUI or not?
2242     if ( woGuiModules.find( prodProc ) != woGuiModules.end() )
2243       ( installGuiBtn->state() != QButton::On && woGuiModules[ prodProc ] == True ) ? 
2244         shellProcess->addArgument( "FALSE" ) : 
2245         shellProcess->addArgument( "TRUE" );
2246     // ... single installation directory for SALOME modules, if this option was selected
2247     if ( oneModDirBtn->isChecked() ) {
2248       MapProducts::Iterator mapIter;
2249       for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter )
2250         if ( mapIter.data().getName() == prodProc && mapIter.data().getType() == "component" ) {
2251           shellProcess->addArgument( "TRUE" );
2252           break;
2253         }
2254     }
2255     // ... single installation directory for prerequisites, if this option was selected
2256     if ( oneProdDirBtn->isChecked() ) {
2257       if ( prodProc == "DebianLibsForSalome" )
2258         shellProcess->addArgument( oneProdDirName );
2259       else {
2260         MapProducts::Iterator mapIter;
2261         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter )
2262           if ( mapIter.data().getName() == prodProc && mapIter.data().getType() == "prerequisite" ) {
2263             shellProcess->addArgument( oneProdDirName );
2264             break;
2265           }
2266       }
2267     }
2268     
2269     // run script
2270     if ( !shellProcess->start() ) {
2271       // error handling can be here
2272       ___MESSAGE___( "error" );
2273     }
2274     return;
2275   }
2276
2277   // else try to find aborted product
2278   prodProc = progressView->findStatus( Aborted );
2279   if ( !prodProc.isNull() )
2280     return; // installation has been aborted
2281
2282   ___MESSAGE___( "All products have been installed successfully" );
2283   // all products are installed successfully
2284   MapProducts::Iterator mapIter;
2285   ___MESSAGE___( "starting pick-up environment" );
2286   QString depproducts = QUOTE( getAllProducts(productsMap).prepend( QStringList( extraProducts.keys() ).join(" ") + " " ) );
2287   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2288     QCheckListItem* item = mapIter.key();
2289     Dependancies dep = mapIter.data();
2290     if ( item->isOn() && dep.pickUpEnvironment() ) {
2291       statusLab->setText( tr( "Pick-up products environment for " ) + dep.getName().latin1() + "..." );
2292       ___MESSAGE___( "... for " << dep.getName().latin1() );
2293       QDir rd( rootDirPath() );
2294       Script script;
2295       script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2296       script << item->text(2) << "pickup_env";
2297       script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2298       script << QUOTE( QFileInfo( QDir::cleanDirPath( QDir( rootDirPath() ).filePath( "Products" ) ) ).absFilePath() );
2299       script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2300       script << depproducts << item->text(0) << QUOTE( prodSequence.join( " " ) );
2301       ___MESSAGE___( "... --> " << script.script().latin1() );
2302       if ( system( script.script().latin1() ) ) {
2303         ___MESSAGE___( "ERROR" );
2304       }
2305     }
2306   }
2307
2308   if ( installType == Binaries ) {
2309     if ( oneModDirBtn->isChecked() )
2310       runModifyLaFiles();
2311     else
2312       runCheckFLib();
2313   }
2314   else {
2315     // Update GUI and check installation errors
2316     completeInstallation();
2317   }
2318   
2319 }
2320 // ================================================================
2321 /*!
2322  *  SALOME_InstallWizard::completeInstallation
2323  *  Update GUI and check installation errors
2324  */
2325 // ================================================================
2326 void SALOME_InstallWizard::completeInstallation()
2327 {
2328   // update status label
2329   statusLab->setText( tr( "Installation completed" ) );
2330   // <Next> button
2331   setNextEnabled( true );
2332   doPostActions( tr( "&Next >" ), tr( "Move to the next step of the installation procedure" ) );
2333   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2334   // <Back> button
2335   setBackEnabled( true );
2336   // script parameters
2337   passedParams->clear();
2338   passedParams->setEnabled( false );
2339   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2340   installInfo->setFinished( true );
2341   if ( isMinimized() )
2342     showNormal();
2343   raise();
2344   if ( hasErrors ) {
2345     if ( QMessageBox::warning( this,
2346                                tr( "Warning" ),
2347                                tr( "There were some errors during the installation.\n"
2348                                    "Do you want to save the installation log?" ),
2349                                tr( "&Save" ),
2350                                tr( "&Cancel" ),
2351                                QString::null,
2352                                0,
2353                                1 ) == 0 )
2354       saveLog();
2355   }
2356   hasErrors = false;
2357
2358 }
2359 // ================================================================
2360 /*!
2361  *  SALOME_InstallWizard::onInstallGuiBtn
2362  *  <Installation with GUI> check-box slot
2363  */
2364 // ================================================================
2365 void SALOME_InstallWizard::onInstallGuiBtn()
2366 {
2367   MapProducts::Iterator itProd;
2368   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2369     if ( itProd.data().getType() == "component" ) {
2370       if ( installGuiBtn->state() == QButton::On ) {
2371         itProd.key()->setEnabled( true );
2372         itProd.key()->setOn( true );
2373       }
2374       else {
2375         QString itemName = itProd.data().getName();
2376         if ( woGuiModules.find( itemName ) == woGuiModules.end() || 
2377              woGuiModules[ itemName ] == False ) {
2378           itProd.key()->setOn( false );
2379           itProd.key()->setEnabled( false );
2380         }
2381         else
2382           itProd.key()->setOn( true );
2383       }
2384     }
2385   }
2386 }
2387 // ================================================================
2388 /*!
2389  *  SALOME_InstallWizard::onMoreBtn
2390  *  <More...> button slot
2391  */
2392 // ================================================================
2393 void SALOME_InstallWizard::onMoreBtn()
2394 {
2395   if ( moreMode ) {
2396     prereqsView->hide();
2397     moreBtn->setText( tr( "Show prerequisites..." ) );
2398     setAboutInfo( moreBtn, tr( "Show list of prerequisites" ) );
2399   }
2400   else {
2401     prereqsView->show();
2402     moreBtn->setText( tr( "Hide prerequisites" ) );
2403     setAboutInfo( moreBtn, tr( "Hide list of prerequisites" ) );
2404   }
2405   qApp->processEvents();
2406   moreMode = !moreMode;
2407   InstallWizard::layOut();
2408   qApp->processEvents();
2409   if ( !isMaximized() ) {
2410     qApp->processEvents();
2411   }
2412   checkProductPage();
2413 }
2414 // ================================================================
2415 /*!
2416  *  SALOME_InstallWizard::onFinishButton
2417  *  Operation buttons slot
2418  */
2419 // ================================================================
2420 void SALOME_InstallWizard::onFinishButton()
2421 {
2422   const QObject* btn = sender();
2423   ButtonList::Iterator it;
2424   for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2425     if ( (*it).button() && (*it).button() == btn ) {
2426       QDir rd( rootDirPath() );
2427       Script script;
2428       script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2429       script << (*it).script() << "execute";
2430       script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2431       script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2432       script << ">& /dev/null";
2433       ___MESSAGE___( "script: " << script.script().latin1() );
2434       if ( (*it).script().isEmpty() || system( script.script().latin1() ) ) {
2435         QMessageBox::warning( this,
2436                               tr( "Error" ),
2437                               tr( "Can't perform action!"),
2438                               QMessageBox::Ok,
2439                               QMessageBox::NoButton,
2440                               QMessageBox::NoButton );
2441       }
2442       return;
2443     }
2444   }
2445 }
2446 // ================================================================
2447 /*!
2448  *  SALOME_InstallWizard::onAbout
2449  *  <About> button slot: shows <About> dialog box
2450  */
2451 // ================================================================
2452 void SALOME_InstallWizard::onAbout()
2453 {
2454   AboutDlg d( this );
2455   d.exec();
2456 }
2457
2458 // ================================================================
2459 /*!
2460  *  SALOME_InstallWizard::findItem
2461  *  Searches product listview item with given symbolic name
2462  */
2463 // ================================================================
2464 QCheckListItem* SALOME_InstallWizard::findItem( const QString& sName )
2465 {
2466   MapProducts::Iterator mapIter;
2467   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2468     if ( mapIter.data().getName() == sName )
2469       return mapIter.key();
2470   }
2471   return 0;
2472 }
2473 // ================================================================
2474 /*!
2475  *  SALOME_InstallWizard::abort
2476  *  Sets progress state to Aborted
2477  */
2478 // ================================================================
2479 void SALOME_InstallWizard::abort()
2480 {
2481   QString prod = progressView->findStatus( Processing );
2482   while ( !prod.isNull() ) {
2483     progressView->setStatus( prod, Aborted );
2484     prod = progressView->findStatus( Processing );
2485   }
2486   prod = progressView->findStatus( Waiting );
2487   while ( !prod.isNull() ) {
2488     progressView->setStatus( prod, Aborted );
2489     prod = progressView->findStatus( Waiting );
2490   }
2491 }
2492 // ================================================================
2493 /*!
2494  *  SALOME_InstallWizard::reject
2495  *  Reject slot, clears temporary directory and closes application
2496  */
2497 // ================================================================
2498 void SALOME_InstallWizard::reject()
2499 {
2500   ___MESSAGE___( "REJECTED" );
2501   if ( !exitConfirmed ) {
2502     if ( QMessageBox::information( this,
2503                                    tr( "Exit" ),
2504                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
2505                                    tr( "&Yes" ),
2506                                    tr( "&No" ),
2507                                    QString::null,
2508                                    0,
2509                                    1 ) == 1 ) {
2510       return;
2511     }
2512     exitConfirmed = true;
2513   }
2514   clean(true);
2515   InstallWizard::reject();
2516 }
2517 // ================================================================
2518 /*!
2519  *  SALOME_InstallWizard::accept
2520  *  Accept slot, clears temporary directory and closes application
2521  */
2522 // ================================================================
2523 void SALOME_InstallWizard::accept()
2524 {
2525   ___MESSAGE___( "ACCEPTED" );
2526   clean(true);
2527   InstallWizard::accept();
2528 }
2529 // ================================================================
2530 /*!
2531  *  SALOME_InstallWizard::clean
2532  *  Clears and (optionally) removes temporary directory
2533  */
2534 // ================================================================
2535 void SALOME_InstallWizard::clean(bool rmDir)
2536 {
2537   WarnDialog::showWarnDlg( 0, false );
2538   myThread->clearCommands();
2539   myWC.wakeAll();
2540   while ( myThread->running() );
2541   // first remove temporary files
2542   QDir rd( rootDirPath() );
2543   Script script;
2544   script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2545   script << "remove_tmp.sh" << QUOTE( tempFolder->text().stripWhiteSpace() + TEMPDIRNAME );
2546   script << QUOTE( getAllProducts( productsMap ) );
2547   script << ">& /dev/null";
2548   ___MESSAGE___( "script = " << script.script().latin1() );
2549   if ( system( script.script().latin1() ) ) {
2550     // error
2551   }
2552   // then try to remove created temporary directory
2553   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
2554   if ( rmDir && !tmpCreated.isNull() ) {
2555     script.clear();
2556     script << "rm -rf" << QUOTE( tmpCreated );
2557     script << ">& /dev/null";
2558     if ( system( script.script().latin1() ) ) {
2559       // error
2560     }
2561     ___MESSAGE___( "script = " << script.script().latin1() );
2562   }
2563 }
2564 // ================================================================
2565 /*!
2566  *  SALOME_InstallWizard::pageChanged
2567  *  Called when user moves from page to page
2568  */
2569 // ================================================================
2570 void SALOME_InstallWizard::pageChanged( const QString & mytitle)
2571 {
2572   doPostActions( tr( "&Next >" ), tr( "Move to the next step of the installation procedure" ) );
2573   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2574   cancelButton()->disconnect();
2575   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
2576
2577   QWidget* aPage = InstallWizard::page( mytitle );
2578   if ( !aPage )
2579     return;
2580   updateCaption();
2581
2582   if ( aPage == typePage ) {
2583     // installation type page
2584     if ( buttonGrp->id( buttonGrp->selected() ) == -1 )
2585       // set default installation type
2586       forceSrc ? srcCompileBtn->animateClick() : binBtn->animateClick();
2587     else
2588       buttonGrp->selected()->animateClick();
2589   }
2590   else if ( aPage == platformsPage ) {
2591     // installation platforms page
2592     MapXmlFiles::Iterator it;
2593     if ( previousPage == typePage ) {
2594       for ( it = platformsMap.begin(); it != platformsMap.end(); ++it ) {
2595         QString plat = it.key();
2596         QRadioButton* rb = ( (QRadioButton*) platBtnGrp->child( plat ) );
2597         if ( installType == Binaries ) {
2598           QFileInfo fib( getPlatformBinPath( plat ) );
2599           rb->setEnabled( true/*fib.isDir()*/ );
2600           if ( platBtnGrp->id( platBtnGrp->selected() ) == -1 && plat == getBasePlatform() )
2601             rb->animateClick();
2602         }
2603 //      rb->setChecked( rb->isChecked() && rb->isEnabled() );
2604         if ( rb->isChecked() && rb->isEnabled() )
2605           rb->animateClick();
2606       }
2607       setNextEnabled( platformsPage, platBtnGrp->id( platBtnGrp->selected() ) != -1 );
2608     }
2609   }
2610   else  if ( aPage == dirPage ) {
2611     // installation and temporary directories page
2612     if ( ( ( this->indexOf( platformsPage ) != -1 && this->appropriate( platformsPage ) ) ? 
2613            previousPage == platformsPage : previousPage == typePage ) 
2614          && stateChanged ) {
2615       // clear global variables before reading XML file
2616       modulesView->clear();
2617       prereqsView->clear();
2618       productsMap.clear();
2619       // read XML file
2620       StructureParser* parser = new StructureParser( this );
2621       parser->setProductsLists( modulesView, prereqsView );
2622       if ( targetFolder->text().isEmpty() )
2623         parser->setTargetDir( targetFolder );
2624       if ( tempFolder->text().isEmpty() )
2625         parser->setTempDir( tempFolder );
2626       parser->readXmlFile( xmlFileName );
2627       // create a map of SALOME modules names, that can support installation without GUI mode
2628       if ( woGuiModules.isEmpty() ) {
2629         MapProducts::Iterator mapIter;
2630         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); mapIter++ ) {
2631           Dependancies dep = mapIter.data();
2632           if ( dep.getType() == "component" && dep.supportWoGuiMode() != NotDefined )
2633             woGuiModules[ dep.getName() ] = dep.supportWoGuiMode();
2634         }
2635       }
2636   
2637       // update required size for each product
2638       updateSizeColumn();
2639       // take into account command line parameters
2640       if ( !myTargetPath.isEmpty() )
2641         targetFolder->setText( myTargetPath );
2642       if ( !myTmpPath.isEmpty() )
2643         tempFolder->setText( myTmpPath );
2644       // set all modules to be checked and first module to be selected
2645       installGuiBtn->setState( QButton::Off );
2646       installGuiBtn->setState( QButton::On );
2647       if ( modulesView->childCount() > 0 && !modulesView->selectedItem() )
2648         modulesView->setSelected( modulesView->firstChild(), true );
2649       stateChanged = false;
2650     } 
2651     else if ( rmSrcPrevState != removeSrcBtn->isChecked() ) {
2652       // only update required size for each product
2653       updateSizeColumn();
2654       rmSrcPrevState = removeSrcBtn->isChecked();
2655     }
2656     // add extra products to install list
2657     extraProducts.clear();
2658     //extraProducts.insert( "gcc", "gcc-common.sh" );
2659     if ( refPlatform == commonPlatform && installType == Binaries )
2660       extraProducts.insert( "DebianLibsForSalome", "DEBIANFORSALOME-3.1.sh" );
2661   }
2662   else if ( aPage == productsPage ) {
2663     // products page
2664     onSelectionChanged();
2665     checkProductPage();
2666   }
2667   else if ( aPage == prestartPage ) {
2668     // prestart page
2669     showChoiceInfo();
2670   }
2671   else if ( aPage == progressPage ) {
2672     if ( previousPage == prestartPage ) {
2673       // progress page
2674       statusLab->clear();
2675       progressView->clear();
2676       installInfo->clear();
2677       installInfo->setFinished( false );
2678       passedParams->clear();
2679       passedParams->setEnabled( false );
2680       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2681       doPostActions( tr( "&Start" ), tr( "Start installation process" ) );
2682       connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2683       setNextEnabled( true );
2684       // reconnect Cancel button to terminate process
2685       cancelButton()->disconnect();
2686       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
2687     }
2688   }
2689   else if ( aPage == readmePage ) {
2690     ButtonList::Iterator it;
2691     for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2692       if ( (*it).button() ) {
2693         QDir rd( rootDirPath() );
2694         Script script;
2695         script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2696         script << (*it).script() << "check_enabled";
2697         script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2698         script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2699         script << ">& /dev/null";
2700         ___MESSAGE___( "script: " << script.script().latin1() );
2701         (*it).button()->setEnabled( !(*it).script().isEmpty() && !system( script.script().latin1() ) );
2702       }
2703     }
2704     finishButton()->setEnabled( true );
2705   }
2706   previousPage = aPage;
2707   ___MESSAGE___( "previousPage = " << previousPage );
2708 }
2709 // ================================================================
2710 /*!
2711  *  SALOME_InstallWizard::onButtonGroup
2712  *  Called when user selected either installation type or installation platform
2713  */
2714 // ================================================================
2715 void SALOME_InstallWizard::onButtonGroup( int rbIndex )
2716 {
2717   int prevType = installType;
2718   QString prevPlat = getPlatform();
2719   QWidget* aPage = InstallWizard::currentPage();
2720   if ( aPage == typePage ) {
2721     installType = InstallationType( rbIndex );
2722     // management of the <Remove source and tmp files> check-box
2723     removeSrcBtn->setEnabled( installType == Compile );
2724     oneModDirBtn->setEnabled( installType == Binaries /*|| installType == Compile*/ );
2725     oneProdDirBtn->setEnabled( installType == Binaries || installType == Compile );
2726     refPlatform = "";
2727     xmlFileName = getXmlFile( curPlatform );
2728   }
2729   else if ( aPage == platformsPage ) {
2730     refPlatform = platBtnGrp->find( rbIndex )->name();
2731     xmlFileName = getXmlFile( refPlatform );
2732     setNextEnabled( platformsPage, true );
2733   }
2734   if ( prevType != installType || 
2735        ( indexOf( platformsPage ) != -1 ? prevPlat != getPlatform() : false ) ) {
2736     stateChanged = true;
2737     oneModDirBtn->setChecked( installType == Binaries && singleDir );
2738     oneProdDirBtn->setChecked( false );
2739   }
2740 }
2741 // ================================================================
2742 /*!
2743  *  SALOME_InstallWizard::helpClicked
2744  *  Shows help window
2745  */
2746 // ================================================================
2747 void SALOME_InstallWizard::helpClicked()
2748 {
2749   if ( helpWindow == NULL ) {
2750     helpWindow = HelpWindow::openHelp( this );
2751     if ( helpWindow ) {
2752       helpWindow->show();
2753       helpWindow->installEventFilter( this );
2754     }
2755     else {
2756       QMessageBox::warning( this,
2757                             tr( "Help file not found" ),
2758                             tr( "Sorry, help is unavailable" ) );
2759     }
2760   }
2761   else {
2762     helpWindow->raise();
2763     helpWindow->setActiveWindow();
2764   }
2765 }
2766 // ================================================================
2767 /*!
2768  *  SALOME_InstallWizard::browseDirectory
2769  *  Shows directory selection dialog
2770  */
2771 // ================================================================
2772 void SALOME_InstallWizard::browseDirectory()
2773 {
2774   const QObject* theSender = sender();
2775   QLineEdit* theFolder;
2776   if ( theSender == targetBtn )
2777     theFolder = targetFolder;
2778   else if (theSender == tempBtn)
2779     theFolder = tempFolder;
2780   else
2781     return;
2782   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
2783   if ( !typedDir.isNull() ) {
2784     theFolder->setText( typedDir );
2785     theFolder->end( false );
2786   }
2787 }
2788 // ================================================================
2789 /*!
2790  *  SALOME_InstallWizard::directoryChanged
2791  *  Called when directory path (target or temp) is changed
2792  */
2793 // ================================================================
2794 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
2795 {
2796   checkProductPage();
2797 }
2798 // ================================================================
2799 /*!
2800  *  SALOME_InstallWizard::onStart
2801  *  <Start> button's slot - runs installation
2802  */
2803 // ================================================================
2804 void SALOME_InstallWizard::onStart()
2805 {
2806   if ( nextButton()->text() == tr( "&Stop" ) ) {
2807     statusLab->setText( tr( "Aborting installation..." ) );
2808     shellProcess->kill();
2809     modifyLaProc->kill();
2810     while( shellProcess->isRunning() );
2811     statusLab->setText( tr( "Installation has been aborted by user" ) );
2812     return;
2813   }
2814
2815   hasErrors = false;
2816   progressView->clear();
2817   installInfo->clear();
2818   installInfo->setFinished( false );
2819   passedParams->clear();
2820   passedParams->setEnabled( false );
2821   // disable 'Ignore errors' checkbox during installation process
2822   ignoreErrCBox->setEnabled( false );
2823   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2824
2825   // update status label
2826   statusLab->setText( tr( "Preparing for installation..." ) );
2827   // clear lists of products
2828   toInstall.clear();
2829   notInstall.clear();
2830   toInstall += extraProducts.keys();
2831   // ... and fill it for new process
2832   QCheckListItem* item = (QCheckListItem*)( prereqsView->firstChild() );
2833   while( item ) {
2834     if ( productsMap.contains( item ) ) {
2835       if ( item->isOn() )
2836         toInstall.append( productsMap[item].getName() );
2837       else
2838         notInstall.append( productsMap[item].getName() );
2839     }
2840     item = (QCheckListItem*)( item->nextSibling() );
2841   }
2842   item = (QCheckListItem*)( modulesView->firstChild() );
2843   while( item ) {
2844     if ( productsMap.contains( item ) ) {
2845       if ( item->isOn() )
2846         toInstall.append( productsMap[item].getName() );
2847       else
2848         notInstall.append( productsMap[item].getName() );
2849     }
2850     item = (QCheckListItem*)( item->nextSibling() );
2851   }
2852   // if something at all is selected
2853   if ( (int)toInstall.count() > 1 ) {
2854
2855     if ( installType == Compile ) {
2856       // update status label
2857       statusLab->setText( tr( "Check Fortran compiler..." ) );
2858       // check Fortran compiler.
2859       QDir rd( rootDirPath() );
2860       Script script;
2861       script << QUOTE( rd.filePath( "config_files/checkFortran.sh" ) ) << "find_compilers";
2862       script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2863       ___MESSAGE___( "script = " << script.script().latin1() );
2864       if ( system( script.script().latin1() ) ) {
2865         QMessageBox::critical( this,
2866                                tr( "Error" ),
2867                                tr( "Fortran compiler was not found at current system!\n"
2868                                    "Installation can not be continued!"),
2869                                QMessageBox::Ok,
2870                                QMessageBox::NoButton,
2871                                QMessageBox::NoButton );
2872         // installation aborted
2873         abort();
2874         statusLab->setText( tr( "Installation has been aborted" ) );
2875         // enable <Next> button
2876         setNextEnabled( true );
2877         doPostActions( tr( "&Start" ), tr( "Start installation process" ) );
2878         connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2879         // enable <Back> button
2880         setBackEnabled( true );
2881         return;
2882       }
2883     }  
2884     
2885     // update status label
2886     statusLab->setText( tr( "Preparing for installation..." ) );
2887
2888     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
2889     // disable <Next> button
2890     //setNextEnabled( false );
2891     nextButton()->setText( tr( "&Stop" ) );
2892     setAboutInfo( nextButton(), tr( "Abort installation process" ) );
2893     // disable <Back> button
2894     setBackEnabled( false );
2895     // enable script parameters line edit
2896     // VSR commented: 18/09/03: passedParams->setEnabled( true );
2897     // VSR commented: 18/09/03: passedParams->setFocus();
2898     ProgressViewItem* progressItem;
2899     // set status for installed products
2900     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
2901       if ( !extraProducts.contains( toInstall[i] ) ) {
2902         item = findItem( toInstall[i] );
2903         progressView->addProduct( item->text(0), item->text(2) );
2904         continue;
2905       }
2906       progressItem = progressView->addProduct( toInstall[i], extraProducts[toInstall[i]] );
2907       progressItem->setVisible( false );
2908     }
2909     // set status for not installed products
2910     for ( int i = 0; i < (int)notInstall.count(); i++ ) {
2911       item = findItem( notInstall[i] );
2912       progressItem = progressView->addProduct( item->text(0), item->text(2) );
2913       progressItem->setVisible( false );
2914     }
2915     // get specified list of products being installed
2916     prodSequence.clear();
2917     for (int i = 0; i<(int)toInstall.count(); i++ ) {
2918       if ( extraProducts.contains( toInstall[i] ) ) {
2919         prodSequence.append( toInstall[i] );
2920         continue;
2921       }
2922       if ( installType == Binaries ) {
2923         prodSequence.append( toInstall[i] );
2924         QString prodType;
2925         MapProducts::Iterator mapIter;
2926         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2927           if ( mapIter.data().getName() == toInstall[i] && mapIter.data().getType() == "component" ) {
2928             prodSequence.append( toInstall[i] + "_src" );
2929             break;
2930           }
2931         }
2932       }
2933       else if ( installType == Sources )
2934         prodSequence.append( toInstall[i] + "_src" );
2935       else {
2936         prodSequence.append( toInstall[i] );
2937         prodSequence.append( toInstall[i] + "_src" );
2938       }
2939     }
2940
2941     // create a backup of 'env_build.csh', 'env_build.sh', 'env_products.csh', 'env_products.sh'
2942     // ( backup of 'salome.csh' and 'salome.sh' is made if pick-up environment is called )
2943     QDir rd( rootDirPath() );
2944     Script script;
2945     script << QUOTE( rd.filePath( "config_files/backupEnv.sh" ) );
2946     script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2947     ___MESSAGE___( "script = " << script.script().latin1() );
2948     if ( system( script.script().latin1() ) ) {
2949       if ( QMessageBox::warning( this,
2950                                  tr( "Warning" ),
2951                                  tr( "Backup environment files have not been created.\n"
2952                                      "Do you want to continue an installation process?" ),
2953                                  tr( "&Yes" ),
2954                                  tr( "&No" ), 
2955                                  QString::null, 0, 1 ) == 1 ) {
2956         // installation aborted
2957         abort();
2958         statusLab->setText( tr( "Installation has been aborted by user" ) );
2959         // update <Next> button
2960         setNextEnabled( true );
2961         doPostActions( tr( "&Start" ), tr( "Start installation process" ) );
2962         connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2963         // enable <Back> button
2964         setBackEnabled( true );
2965         return;
2966       }
2967     }
2968
2969     // launch install script
2970     launchScript();
2971   }
2972 }
2973 // ================================================================
2974 /*!
2975  *  SALOME_InstallWizard::onReturnPressed
2976  *  Called when users tries to pass parameters for the script
2977  */
2978 // ================================================================
2979 void SALOME_InstallWizard::onReturnPressed()
2980 {
2981   QString txt = passedParams->text();
2982   installInfo->append( txt );
2983   txt += "\n";
2984   shellProcess->writeToStdin( txt );
2985   passedParams->clear();
2986   progressView->setFocus();
2987   passedParams->setEnabled( false );
2988   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2989 }
2990 /*!
2991   Callback function - as response for the script finishing
2992 */
2993 void SALOME_InstallWizard::productInstalled()
2994 {
2995   ___MESSAGE___( "process exited" );
2996   if ( shellProcess->normalExit() ) {
2997     ___MESSAGE___( "...normal exit" );
2998     // normal exit - try to proceed installation further
2999     launchScript();
3000   }
3001   else {
3002     ___MESSAGE___( "...abnormal exit" );
3003     statusLab->setText( tr( "Installation has been aborted" ) );
3004     // installation aborted
3005     abort();
3006     // clear script passed parameters lineedit
3007     passedParams->clear();
3008     passedParams->setEnabled( false );
3009     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
3010     installInfo->setFinished( true );
3011     // enable <Next> button
3012     setNextEnabled( true );
3013     doPostActions( tr( "&Start" ), tr( "Start installation process" ) );
3014     connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
3015     //doPostActions( tr( "&Next >" ), tr( "Move to the next step of the installation procedure" ) );
3016     //connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
3017     // enable <Back> button
3018     setBackEnabled( true );
3019   }
3020 }
3021 // ================================================================
3022 /*!
3023  *  SALOME_InstallWizard::tryTerminate
3024  *  Slot, called when <Cancel> button is clicked during installation script running
3025  */
3026 // ================================================================
3027 void SALOME_InstallWizard::tryTerminate()
3028 {
3029   if ( shellProcess->isRunning() ) {
3030     if ( QMessageBox::information( this,
3031                                    tr( "Exit" ),
3032                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
3033                                    tr( "&Yes" ),
3034                                    tr( "&No" ),
3035                                    QString::null,
3036                                    0,
3037                                    1 ) == 1 ) {
3038       return;
3039     }
3040     exitConfirmed = true;
3041     // if process still running try to terminate it first
3042     shellProcess->tryTerminate();
3043     abort();
3044     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
3045     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
3046   }
3047   else {
3048     // else just quit install wizard
3049     reject();
3050   }
3051 }
3052 // ================================================================
3053 /*!
3054  *  SALOME_InstallWizard::onCancel
3055  *  Kills installation process and quits application
3056  */
3057 // ================================================================
3058 void SALOME_InstallWizard::onCancel()
3059 {
3060   shellProcess->kill();
3061   modifyLaProc->kill();
3062   checkFLibProc->kill();
3063   reject();
3064 }
3065 // ================================================================
3066 /*!
3067  *  SALOME_InstallWizard::onSelectionChanged
3068  *  Called when selection is changed in the products list view
3069  *  to fill in the 'Information about product' text box
3070  */
3071 // ================================================================
3072 void SALOME_InstallWizard::onSelectionChanged()
3073 {
3074   const QObject* snd = sender();
3075   QListViewItem* item = modulesView->selectedItem();
3076   if ( snd == prereqsView )
3077     item = prereqsView->selectedItem();
3078   if ( !item )
3079     return;
3080   productInfo->clear();
3081   QCheckListItem* anItem = (QCheckListItem*)item;
3082   if ( !productsMap.contains( anItem ) )
3083     return;
3084   Dependancies dep = productsMap[ anItem ];
3085   QString text = "<b>" + anItem->text(0) + "</b>" + "<br>";
3086   if ( !dep.getVersion().isEmpty() )
3087     text += tr( "Version" ) + ": " + dep.getVersion() + "<br>";
3088   text += "<br>";
3089   if ( !dep.getDescription().isEmpty() ) {
3090     text += "<i>" + dep.getDescription() + "</i><br><br>";
3091   }
3092   /* AKL: 07/08/28 - hide required disk space for tmp files for each product ==>
3093      long tempSize = 0;
3094      tempSize = dep.getTempSize( installType );
3095      text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " KB<br>";
3096      AKL: 07/08/28 - hide required disk space for tmp files for each product <==
3097   */
3098   text += tr( "Disk space required" ) + ": " + item->text(1) + "<br>";
3099   text += "<br>";
3100   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
3101   text +=  tr( "Prerequisites" ) + ": " + req;
3102   productInfo->setText( text );
3103 }
3104 // ================================================================
3105 /*!
3106  *  SALOME_InstallWizard::onItemToggled
3107  *  Called when user checks/unchecks any product item
3108  *  Recursively sets all prerequisites and updates "Next" button state
3109  */
3110 // ================================================================
3111 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
3112 {
3113   if ( productsMap.contains( item ) ) {
3114     if ( item->isOn() )
3115       setPrerequisites( item );
3116     else 
3117       unsetPrerequisites( item );
3118   }
3119   onSelectionChanged();
3120   checkProductPage();
3121 }
3122 // ================================================================
3123 /*!
3124  *  SALOME_InstallWizard::wroteToStdin
3125  *  QProcess slot: -->something was written to stdin
3126  */
3127 // ================================================================
3128 void SALOME_InstallWizard::wroteToStdin( )
3129 {
3130   ___MESSAGE___( "Something was sent to stdin" );
3131 }
3132 // ================================================================
3133 /*!
3134  *  SALOME_InstallWizard::readFromStdout
3135  *  QProcess slot: -->something was written to stdout
3136  */
3137 // ================================================================
3138 void SALOME_InstallWizard::readFromStdout( )
3139 {
3140   ___MESSAGE___( "Something was sent to stdout" );
3141   QProcess* theProcess = ( QProcess* )sender();
3142   while ( theProcess->canReadLineStdout() ) {
3143     installInfo->append( QString( theProcess->readLineStdout() ) );
3144     installInfo->scrollToBottom();
3145   }
3146   QString str( theProcess->readStdout() );
3147   if ( !str.isEmpty() ) {
3148     installInfo->append( str );
3149     installInfo->scrollToBottom();
3150   }
3151 }
3152
3153 #define OUTLINE_TEXT(x) QString( "<font color=#FF0000><b>" ) + QString( x ) + QString( "</b></font>" )
3154
3155 // ================================================================
3156 /*!
3157  *  SALOME_InstallWizard::readFromStderr
3158  *  QProcess slot: -->something was written to stderr
3159  */
3160 // ================================================================
3161 void SALOME_InstallWizard::readFromStderr( )
3162 {
3163   ___MESSAGE___( "Something was sent to stderr" );
3164   QProcess* theProcess = ( QProcess* )sender();
3165   while ( theProcess->canReadLineStderr() ) {
3166     installInfo->append( OUTLINE_TEXT( QString( theProcess->readLineStderr() ) ) );
3167     installInfo->scrollToBottom();
3168     hasErrors = true;
3169   }
3170   QString str( theProcess->readStderr() );
3171   if ( !str.isEmpty() ) {
3172     installInfo->append( OUTLINE_TEXT( str ) );
3173     installInfo->scrollToBottom();
3174     hasErrors = true;
3175   }
3176
3177   // stop or proceed installation process
3178   manageInstProc();
3179
3180   // VSR: 10/11/05 - disable answer mode ==>
3181   // passedParams->setEnabled( true );
3182   // passedParams->setFocus();
3183   // QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
3184   // VSR: 10/11/05 - disable answer mode <==
3185 }
3186 // ================================================================
3187 /*!
3188  *  SALOME_InstallWizard::manageInstProc
3189  *  QProcess slot: -->stop installation if there is an error in stderr
3190  */
3191 // ================================================================
3192 void SALOME_InstallWizard::manageInstProc()
3193 {
3194   if ( !hasErrors || ignoreErrCBox->isChecked() )
3195     return; //proceed installation process
3196   
3197   // abort the current installation
3198   statusLab->setText( tr( "Aborting installation..." ) );
3199   abort();
3200   statusLab->setText( tr( "Installation has been aborted because some errors" ) );
3201   if ( QMessageBox::critical( this,
3202                               tr( "Error" ),
3203                               tr( "Installation process has been stopped, because an error occured \n"
3204                                   "during an installation of the current product!\n"
3205                                   "Please see the installation progress view for more details about the error.\n\n"
3206                                   "Do you want to save the installation log?" ),
3207                               tr( "&Save" ),
3208                               tr( "&Cancel" ),
3209                               QString::null,
3210                               0,
3211                               1 ) == 0 )
3212     saveLog();
3213   // enable <Next> button
3214   setNextEnabled( true );
3215   doPostActions( tr( "&Start" ), tr( "Start installation process" ) );
3216   connect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
3217   // enable <Back> button
3218   setBackEnabled( true );
3219   installInfo->setFinished( true );
3220 }
3221 // ================================================================
3222 /*!
3223  *  SALOME_InstallWizard::setDependancies
3224  *  Sets dependancies for the product item
3225  */
3226 // ================================================================
3227 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
3228 {
3229   productsMap[item] = dep;
3230 }
3231 // ================================================================
3232 /*!
3233  *  SALOME_InstallWizard::doPostActions
3234  *  Executes some actions after finish of installation process (successful or not)
3235  */
3236 // ================================================================
3237 void SALOME_InstallWizard::doPostActions( const QString& btnText,
3238                                           const QString& btnAboutInfo )
3239 {
3240   // update <Next> button
3241   nextButton()->setText( btnText );
3242   setAboutInfo( nextButton(), btnAboutInfo );
3243   // reconnect Next button - to use it as Start button
3244   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
3245   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
3246   // enable 'Ignore errors' checkbox
3247   ignoreErrCBox->setEnabled( true );
3248 }
3249 // ================================================================
3250 /*!
3251  *  SALOME_InstallWizard::addFinishButton
3252  *  Add button for the <Finish> page.
3253  *  Clear list of buttons if <toClear> flag is true.
3254  */
3255 // ================================================================
3256 void SALOME_InstallWizard::addFinishButton( const QString& label,
3257                                             const QString& tooltip,
3258                                             const QString& script,
3259                                             bool toClear )
3260 {
3261   ButtonList btns;
3262   if ( toClear ) {
3263     btns = buttons;
3264     buttons.clear();
3265   }
3266   buttons.append( Button( label, tooltip, script ) );
3267   // create finish buttons
3268   QButton* b = new QPushButton( tr( buttons.last().label() ), readmePage );
3269   if ( !buttons.last().tootip().isEmpty() )
3270     setAboutInfo( b, tr( buttons.last().tootip() ) );
3271   QHBoxLayout* hLayout = (QHBoxLayout*)readmePage->layout()->child("finishButtons");
3272   if ( toClear ) {
3273     // remove previous buttons
3274     ButtonList::Iterator it;
3275     for ( it = btns.begin(); it != btns.end(); ++it ) {
3276       hLayout->removeChild( (*it).button() );
3277       delete (*it).button();
3278     }
3279   }
3280   // add buttons to finish page
3281   hLayout->insertWidget( buttons.count()-1, b );
3282   buttons.last().setButton( b );
3283   connect( b, SIGNAL( clicked() ), this, SLOT( onFinishButton() ) );
3284 }
3285 // ================================================================
3286 /*!
3287  *  SALOME_InstallWizard::polish
3288  *  Polishing of the widget - to set right initial size
3289  */
3290 // ================================================================
3291 void SALOME_InstallWizard::polish()
3292 {
3293   resize( 0, 0 );
3294   InstallWizard::polish();
3295 }
3296 // ================================================================
3297 /*!
3298  *  SALOME_InstallWizard::saveLog
3299  *  Save installation log to file
3300  */
3301 // ================================================================
3302 void SALOME_InstallWizard::saveLog()
3303 {
3304   QString txt = installInfo->text();
3305   if ( txt.length() <= 0 )
3306     return;
3307   QDateTime dt = QDateTime::currentDateTime();
3308   QString fileName = dt.toString("ddMMyy-hhmm");
3309   fileName.prepend("install-"); fileName.append(".html");
3310   fileName = QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ), fileName ).absFilePath();
3311   fileName = QFileDialog::getSaveFileName( fileName,
3312                                            QString( "HTML files (*.htm *.html)" ),
3313                                            this, 0,
3314                                            tr( "Save Log file" ) );
3315   if ( !fileName.isEmpty() ) {
3316     QFile f( fileName );
3317     if ( f.open( IO_WriteOnly ) ) {
3318       QTextStream stream( &f );
3319       stream << txt;
3320       f.close();
3321     }
3322     else {
3323       QMessageBox::critical( this,
3324                              tr( "Error" ),
3325                              tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ),
3326                              QMessageBox::Ok,
3327                              QMessageBox::NoButton,
3328                              QMessageBox::NoButton );
3329     }
3330   }
3331 }
3332 // ================================================================
3333 /*!
3334  *  SALOME_InstallWizard::updateCaption
3335  *  Updates caption according to the current page number
3336  */
3337 // ================================================================
3338 void SALOME_InstallWizard::updateCaption()
3339 {
3340   QWidget* aPage = InstallWizard::currentPage();
3341   if ( !aPage )
3342     return;
3343   InstallWizard::setCaption( tr( myCaption ) + " " +
3344                              tr( getIWName() ) + " - " +
3345                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
3346 }
3347
3348 // ================================================================
3349 /*!
3350  *  SALOME_InstallWizard::processValidateEvent
3351  *  Processes validation event (<val> is validation code)
3352  */
3353 // ================================================================
3354 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
3355 {
3356   QWidget* aPage = InstallWizard::currentPage();
3357   if ( aPage != productsPage ) {
3358     InstallWizard::processValidateEvent( val, data );
3359     return;
3360   }
3361   myMutex.lock();
3362   myMutex.unlock();
3363   if ( val > 0 ) {
3364   }
3365   if ( myThread->hasCommands() )
3366     myWC.wakeAll();
3367   else {
3368     WarnDialog::showWarnDlg( 0, false );
3369     InstallWizard::processValidateEvent( val, data );
3370   }
3371 }