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