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