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