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