Salome HOME
Update copyright notes
[tools/install.git] / src / SALOME_InstallWizard.cxx
index 53a07e7c892f0685639fb26ec3e9824f17285d1c..acedde53dea629edc5e7c6a45d96c4280b13d75b 100644 (file)
@@ -1,10 +1,11 @@
 //  File      : SALOME_InstallWizard.cxx 
 //  Created   : Thu Dec 18 12:01:00 2002
-//  Author    : Vadim SANDLER
-//  Project   : PAL/SALOME
-//  Module    : InstallWizard
-//  Copyright : 2004 CEA
-//  $Header$ 
+//  Author    : Vadim SANDLER, Open CASCADE SAS (vadim.sandler@opencascade.com)
+//  Project   : SALOME
+//  Module    : Installation Wizard
+//  Copyright : 2002-2006 CEA
+
+#include "globals.h"
 
 #include "SALOME_InstallWizard.hxx"
 #include "SALOME_ProductsView.hxx"
 #include <qwhatsthis.h> 
 #include <qtooltip.h>
 #include <qfile.h>
+#include <qthread.h>
+#include <qwaitcondition.h>
+#include <qmutex.h>
+#include <qstringlist.h>
+#include <qpopupmenu.h>
 
 #ifdef WNT
 #include <iostream.h>
 #define max( x, y ) ( x ) > ( y ) ? ( x ) : ( y )
 #endif
 
-#define TEMPDIRNAME ( "/INSTALLWORK" + QString::number( getpid() ) )
+QString tmpDirName() { return QString(  "/INSTALLWORK" ) + QString::number( getpid() ); }
+#define TEMPDIRNAME tmpDirName()
+
+// ================================================================
+/*!
+ *  ProcessThread
+ *  Class for executing systen commands
+ */
+// ================================================================
+static QMutex myMutex(false);
+static QWaitCondition myWC;
+class ProcessThread: public QThread
+{
+  typedef QPtrList<QCheckListItem> ItemList;
+public:
+  ProcessThread( SALOME_InstallWizard* iw ) : QThread(), myWizard( iw ) { myItems.setAutoDelete( false ); }
+
+  void addCommand( QCheckListItem* item, const QString& cmd ) {
+    myItems.append( item );
+    myCommands.push_back( cmd );
+  }
+
+  bool hasCommands() const { return myCommands.count() > 0; }
+  void clearCommands()     { myCommands.clear(); myItems.clear(); }
+
+  virtual void run() {
+    while ( hasCommands() ) {
+      ___MESSAGE___( "ProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() );
+      int result = system( myCommands[ 0 ] ) / 256; // return code is <errno> * 256 
+      ___MESSAGE___( "ProcessThread::run - Result : " << result );
+      QCheckListItem* item = myItems.first();
+      myCommands.pop_front();
+      myItems.removeFirst();
+      myMutex.lock();
+      SALOME_InstallWizard::postValidateEvent( myWizard, result, (void*)item );
+      if ( hasCommands() )
+       myWC.wait(&myMutex);
+      myMutex.unlock();
+    };
+  }
+
+private:
+  QStringList           myCommands;
+  ItemList              myItems;
+  SALOME_InstallWizard* myWizard;
+};
+
+// ================================================================
+/*!
+ *  WarnDialog
+ *  Warning dialog box
+ */
+// ================================================================
+class WarnDialog: public QDialog
+{
+  static WarnDialog* myDlg;
+  bool myCloseFlag;
+
+  WarnDialog( QWidget* parent ) 
+  : QDialog( parent, "WarnDialog", true, WDestructiveClose ) {
+    setCaption( tr( "Information" ) );
+    myCloseFlag = false;
+    QLabel* lab = new QLabel( tr( "Please, wait while checking native products configuration ..." ), this );
+    lab->setAlignment( AlignCenter );
+    lab->setFrameStyle( QFrame::Box | QFrame::Plain ); 
+    QVBoxLayout* l = new QVBoxLayout( this );
+    l->setMargin( 0 );
+    l->add( lab );
+    this->setFixedSize( lab->sizeHint().width()  + 50, 
+                       lab->sizeHint().height() * 5 );
+  }
+  void accept() { return; }
+  void reject() { return; }
+  void closeEvent( QCloseEvent* e )
+  { if ( !myCloseFlag ) return; 
+    e->accept();
+    QDialog::closeEvent( e );
+  }
+  ~WarnDialog() { myDlg = 0; }
+public:
+  static void showWarnDlg( QWidget* parent, bool show ) {
+    if ( show ) {
+      if ( !myDlg ) {
+       myDlg = new WarnDialog( parent );
+       QSize sh = myDlg->size();
+       myDlg->move( parent->x() + (parent->width()-sh.width())/2, 
+                    parent->y() + (parent->height()-sh.height())/2 );
+       myDlg->show();
+      }
+      myDlg->raise();
+      myDlg->setFocus();
+    }
+    else {
+      if ( myDlg ) {
+       myDlg->myCloseFlag = true;
+       myDlg->close();
+      }
+    }
+  }
+  static bool isWarnDlgShown() { return myDlg != 0; }
+};
+WarnDialog* WarnDialog::myDlg = 0;
+
+// ================================================================
+/*!
+ *  InstallInfo
+ *  Installation progress info window class
+ */
+// ================================================================
+class InstallInfo : public QTextEdit
+{
+public:
+  InstallInfo( QWidget* parent ) : QTextEdit( parent ), finished( false ) {}
+  void setFinished( const bool f ) { finished = f; }
+protected:
+  QPopupMenu* createPopupMenu( const QPoint& )
+  {
+    int para1, col1, para2, col2;
+    getSelection(&para1, &col1, &para2, &col2);
+    bool allSelected = hasSelectedText() &&
+      para1 == 0 && para2 == paragraphs()-1 && col1 == 0 && col2 == paragraphLength(para2);
+    QPopupMenu* popup = new QPopupMenu( this );
+    int id = popup->insertItem( tr( "&Copy" ) );
+    popup->setItemEnabled( id, hasSelectedText() );
+    popup->connectItem ( id, this, SLOT( copy() ) );
+    id = popup->insertItem( tr( "Select &All" ) );
+    popup->setItemEnabled( id, (bool)text().length() && !allSelected );
+    popup->connectItem ( id, this, SLOT( selectAll() ) );
+    if ( finished ) {
+      QWidget* p = parentWidget();
+      while ( p && !p->inherits( "SALOME_InstallWizard" ) )
+       p = p->parentWidget();
+      if ( p && p->inherits( "SALOME_InstallWizard" ) ) {
+       popup->insertSeparator();
+       id = popup->insertItem( tr( "&Save Log" ) );
+       popup->setItemEnabled( id, (bool)text().length() );
+       popup->connectItem ( id, (SALOME_InstallWizard*)p, SLOT( saveLog() ) );
+      }
+    }
+    return popup;
+  }
+private:
+  bool finished;
+};
 
 // ================================================================
 /*!
  *  Defines list of dependancies as string separated by space symbols
  */
 // ================================================================
-static QString DefineDependeces(MapProducts& theProductsMap) {
+static QString DefineDependeces(MapProducts& theProductsMap) 
+{
   QStringList aProducts;
   for ( MapProducts::Iterator mapIter = theProductsMap.begin(); mapIter != theProductsMap.end(); ++mapIter ) {
     QCheckListItem* item = mapIter.key();
@@ -95,7 +245,6 @@ static QString DefineDependeces(MapProducts& theProductsMap, QCheckListItem* pro
 // ================================================================
 static bool makeDir( const QString& theDir, QString& theCreated )
 {
-  theCreated = QString::null;
   if ( theDir.isEmpty() )
     return false;
   QString aDir = QDir::cleanDirPath( QFileInfo( theDir ).absFilePath() );
@@ -168,40 +317,175 @@ static bool hasSpace( const QString& dir )
   return false;
 }
 
+// ================================================================
+/*!
+ *  makeTitle
+ *  Creates HTML-wrapped title text
+ */
+// ================================================================
+QString makeTitle( const QString& text, const QString& separator = " ", bool fl = true )
+{
+  QStringList words = QStringList::split( separator, text );
+  if ( fl ) {
+    for ( uint i = 0; i < words.count(); i++ )
+      words[i] = QString( "<font color=red>%1</font>" ).arg( words[i].left(1) ) + words[i].mid(1);
+  }
+  else {
+    if ( words.count() > 0 )
+      words[0] = QString( "<font color=red>%1</font>" ).arg( words[0] );
+    if ( words.count() > 1 )
+      words[words.count()-1] = QString( "<font color=red>%1</font>" ).arg( words[words.count()-1] );
+  }
+  QString res = words.join( separator );
+  if ( !res.isEmpty() )
+    res = QString( "<b>%1</b>" ).arg( res );
+  return res;
+}
+
+// ================================================================
+/*!
+ *  QMyCheckBox class : custom check box
+ *  The only goal is to give access to the protected setState() method
+ */
+// ================================================================
+class QMyCheckBox: public QCheckBox
+{
+public:
+  QMyCheckBox( const QString& text, QWidget* parent, const char* name = 0 ) : QCheckBox ( text, parent, name ) {}
+  void setState ( ToggleState s ) { QCheckBox::setState( s ); }
+};
+
+// ================================================================
+/*!
+ *  AboutDlg
+ *  "About dialog box.
+ */
+// ================================================================
+class AboutDlg: public QDialog
+{
+public:
+  AboutDlg( SALOME_InstallWizard* parent ) : QDialog( parent, "About dialog box", true )
+  {
+    // caption
+    setCaption( QString( "About %1" ).arg( parent->getIWName() ) );
+    // palette
+    QPalette pal = palette();
+    QColorGroup cg = pal.active();
+    cg.setColor( QColorGroup::Foreground, Qt::darkBlue );
+    cg.setColor( QColorGroup::Background, Qt::white );
+    pal.setActive( cg ); pal.setInactive( cg ); pal.setDisabled( cg );
+    setPalette( pal );
+    // layout
+    QGridLayout* main = new QGridLayout( this, 1, 1, 11, 6 );
+    // image
+    QLabel* logo = new QLabel( this, "logo" );
+    logo->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
+    logo->setMinimumSize( 32, 32 ); logo->setMaximumSize( 32, 32 );
+    logo->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
+    logo->setFrameStyle( QLabel::NoFrame | QLabel::Plain );
+    logo->setPixmap( pixmap( pxAbout ) );
+    logo->setScaledContents( false );
+    logo->setAlignment( QLabel::AlignCenter );
+    // decoration
+    QLabel* decorLeft = new QLabel( this, "decorLeft" );
+    decorLeft->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding ) );
+    decorLeft->setMinimumWidth( 32 ); decorLeft->setMaximumWidth( 32 );
+    decorLeft->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
+    decorLeft->setScaledContents( false );
+    QLabel* decorTop = new QLabel( this, "decorTop" );
+    decorTop->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
+    decorTop->setMinimumHeight( 32 ); decorTop->setMaximumHeight( 32 );
+    decorTop->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
+    decorTop->setScaledContents( false );
+    // contents
+    QLabel* title = new QLabel( this, "title" );
+    QString tlt = parent->getIWName();
+    title->setText( makeTitle( tlt ) );
+    QLabel* version = new QLabel( this, "version" );
+    version->setText( QString( "<b>Version</b>: %1.%1.%1" ).arg( __IW_VERSION_MAJOR__ ) \
+                     .arg( __IW_VERSION_MINOR__ ) \
+                     .arg( __IW_VERSION_PATCH__ ) );
+    QLabel* copyright = new QLabel( this, "copyright" );
+    copyright->setText( "<b>Copyright</b> &copy; 2004-2006 CEA" );
+    QFont font = title->font();
+    font.setPointSize( (int)( font.pointSize() * 1.8 ) );
+    title->setFont( font );
+    QFrame* line = new QFrame( this, "line" );
+    line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+    QLabel* url = new QLabel( this, "url" );
+    url->setText( makeTitle( "www.salome-platform.org", ".", false ) );
+    url->setAlignment( AlignRight );
+    font = version->font();
+    font.setPointSize( (int)( font.pointSize() / 1.2 ) );
+    version->setFont( font );
+    copyright->setFont( font );
+    url->setFont( font );
+    // layout
+    main->addWidget( logo, 0, 0 );
+    main->addMultiCellWidget( decorLeft, 1, 5, 0, 0 );
+    main->addWidget( decorTop, 0, 1 );
+    main->addWidget( title, 1, 1 );
+    main->addWidget( version, 2, 1 );
+    main->addWidget( copyright, 3, 1 );
+    main->addWidget( line, 4, 1 );
+    main->addWidget( url, 5, 1 );
+    // resize
+    QFontMetrics fm( title->font() );
+    int width = (int)( fm.width( tlt ) * 1.5 );
+    title->setMinimumWidth( width );
+    setMaximumSize( minimumSize() );
+  }
+  void mousePressEvent( QMouseEvent* )
+  {
+    accept();
+  }
+};
+
 // ================================================================
 /*!
  *  SALOME_InstallWizard::SALOME_InstallWizard
  *  Constructor
  */
 // ================================================================
-SALOME_InstallWizard::SALOME_InstallWizard(QString aXmlFileName)
+SALOME_InstallWizard::SALOME_InstallWizard(const QString& aXmlFileName,
+                                          const QString& aTargetDir,
+                                          const QString& aTmpDir)
      : InstallWizard( qApp->desktop(), "SALOME_InstallWizard", false, 0 ), 
        helpWindow( NULL ), 
        moreMode( false ), 
        previousPage( 0 ), 
        exitConfirmed( false )
 {
-  myIWName = tr( "Installation Wizard" );
-  tmpCreated = QString::null;
-  xmlFileName = aXmlFileName;
-  QFont fnt = font(); fnt.setPointSize( 14 ); fnt.setBold( true );
+  myIWName      = tr( "Installation Wizard" );
+  tmpCreated    = QString::null;
+  xmlFileName   = aXmlFileName;
+  targetDirPath = aTargetDir;
+  tmpDirPath    = aTmpDir;
+
+  // set application font
+  QFont fnt = font();
+  fnt.setPointSize( 14 );
+  fnt.setBold( true );
   setTitleFont( fnt );
 
   // set icon
-  setIcon( QPixmap( ( const char** ) image0_data ) );
+  setIcon( pixmap( pxIcon ) );
   // enable sizegrip
   setSizeGripEnabled( true );
-
+  
+  // add logo
+  addLogo( pixmap( pxLogo ) );
+  
   // set defaults
   setVersion( "1.2" );
-  setCaption( tr("PAL/SALOME %1").arg( myVersion ) );
+  setCaption( tr( "PAL/SALOME %1" ).arg( myVersion ) );
   setCopyright( tr( "Copyright (C) 2004 CEA" ) );
   setLicense( tr( "All right reserved" ) );
   setOS( "" );
 
-#ifdef DEBUG
-  cout << "Config. file : " << xmlFileName << endl;
-#endif
+  ___MESSAGE___( "Configuration file : " << xmlFileName );
+  ___MESSAGE___( "Target directory   : " << targetDirPath );
+  ___MESSAGE___( "Temporary directory: " << tmpDirPath );
 
   // xml reader
   QFile xmlfile(xmlFileName);
@@ -215,7 +499,7 @@ SALOME_InstallWizard::SALOME_InstallWizard(QString aXmlFileName)
   }
 
   // create instance of class for starting shell install script
-  shellProcess = new QProcess( this,"shellProcess" );
+  shellProcess = new QProcess( this, "shellProcess" );
 
   // create introduction page
   setupIntroPage();
@@ -242,13 +526,22 @@ SALOME_InstallWizard::SALOME_InstallWizard(QString aXmlFileName)
   
   // common signals connections
   connect( this, SIGNAL( selected( const QString& ) ),
-                                          this, SLOT( pageChanged( const QString& ) ) );
-  connect( this, SIGNAL( helpClicked() ), this, SLOT( helpClicked() ) );
+                                           this, SLOT( pageChanged( const QString& ) ) );
+  connect( this, SIGNAL( helpClicked() ),  this, SLOT( helpClicked() ) );
+  connect( this, SIGNAL( aboutClicked() ), this, SLOT( onAbout() ) );
+
   // catch signals from launched script
   connect(shellProcess, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout() ) );
   connect(shellProcess, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr() ) );
   connect(shellProcess, SIGNAL( processExited() ),   this, SLOT( productInstalled() ) );
   connect(shellProcess, SIGNAL( wroteToStdin() ),    this, SLOT( wroteToStdin() ) );
+
+  // create validation thread
+  myThread = new ProcessThread( this );
+
+  // show about button
+  setAboutIcon( pixmap( pxAbout ) );
+  showAboutBtn( true );
 }
 // ================================================================
 /*!
@@ -264,12 +557,11 @@ SALOME_InstallWizard::~SALOME_InstallWizard()
   if ( PID > 0 ) {
     script += QString::number( PID );
     script += " > /dev/null";
-#ifdef DEBUG
-    cout << "script: "<< script.latin1() << endl;
-#endif
+    ___MESSAGE___( "script: " << script.latin1() );
     if ( system( script.latin1() ) ) { 
     }
   }
+  delete myThread;
 }
 // ================================================================
 /*!
@@ -291,12 +583,16 @@ bool SALOME_InstallWizard::eventFilter( QObject* object, QEvent* event )
 // ================================================================
 void SALOME_InstallWizard::closeEvent( QCloseEvent* ce )
 {
+  if ( WarnDialog::isWarnDlgShown() ) {
+    ce->ignore();
+    return;
+  }
   if ( !exitConfirmed ) {
     if ( QMessageBox::information( this, 
                                   tr( "Exit" ), 
                                   tr( "Do you want to quit %1?" ).arg( getIWName() ), 
-                                  tr( "Yes" ), 
-                                  tr( "No" ),
+                                  tr( "&Yes" ), 
+                                  tr( "&No" ),
                                   QString::null,
                                   0,
                                   1 ) == 1 ) {
@@ -322,11 +618,10 @@ void SALOME_InstallWizard::setupIntroPage()
   QGridLayout* pageLayout = new QGridLayout( introPage ); 
   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
   // create logo picture
-  QPixmap logo( (const char**)SALOMEPRO_Logo_xpm );
   logoLab = new QLabel( introPage );
-  logoLab->setPixmap( logo );
+  logoLab->setPixmap( pixmap( pxBigLogo ) );
   logoLab->setScaledContents( false );
-  logoLab->setFrameStyle( QLabel::Plain | QLabel::Box );
+  logoLab->setFrameStyle( QLabel::Plain | QLabel::NoFrame );
   logoLab->setAlignment( AlignCenter );
   // create version box
   QVBox* versionBox = new QVBox( introPage ); versionBox->setSpacing( 6 );
@@ -346,7 +641,7 @@ void SALOME_InstallWizard::setupIntroPage()
                      "which are necessary for <b>%2</b> and setup "
                      "your environment.<br><br>Click <code>Cancel</code> button to abort "
                      "installation and quit. Click <code>Next</code> button to continue with the "
-                     "installation program.").arg(myCaption).arg(myCaption) );
+                     "installation program." ).arg( myCaption ).arg( myCaption ) );
   info->setFrameStyle( QLabel::WinPanel | QLabel::Sunken );
   info->setMargin( 6 );
   info->setAlignment( WordBreak );
@@ -400,7 +695,7 @@ void SALOME_InstallWizard::setupProductsPage()
   QToolTip::add  ( tempBtn, tr( "Click this to browse temporary directory" ) );
   // create products list
   productsView = new ProductsView( moreBox );
-  productsView->setMinimumSize( 200, 180 );
+  productsView->setMinimumSize( 250, 180 );
   QWhatsThis::add( productsView, tr( "This view lists the products you wish to be installed" ) );
   QToolTip::add  ( productsView, tr( "This view lists the products you wish to be installed" ) );
   // products info box
@@ -439,12 +734,23 @@ void SALOME_InstallWizard::setupProductsPage()
   prerequisites->setChecked( true );
   QWhatsThis::add( prerequisites, tr( "Check this if you want prerequisites products to be set on automatically" ) );
   QToolTip::add  ( prerequisites, tr( "Check this if you want prerequisites products to be set on automatically" ) );
-  // <Unselect All> buttons
-  unselectBtn  = new QPushButton( tr( "&Unselect All" ),    moreBox );
+  // <Unselect All> button
+  unselectBtn  = new QPushButton( tr( "&Unselect All" ), moreBox );
   QWhatsThis::add( unselectBtn, tr( "Unselects all products" ) );
   QToolTip::add  ( unselectBtn, tr( "Unselects all products" ) );
+  // <SALOME sources> / <SALOME binaries> tri-state checkboxes
+  selectSrcBtn  = new QMyCheckBox( tr( "SALOME sources" ), moreBox );
+  selectSrcBtn->setTristate( true );
+  QWhatsThis::add( selectSrcBtn, tr( "Selects/unselects SALOME sources" ) );
+  QToolTip::add  ( selectSrcBtn, tr( "Selects/unselects SALOME sources" ) );
+  selectBinBtn  = new QMyCheckBox( tr( "SALOME binaries" ), moreBox );
+  selectBinBtn->setTristate( true );
+  QWhatsThis::add( selectBinBtn, tr( "Selects/unselects SALOME binaries" ) );
+  QToolTip::add  ( selectBinBtn, tr( "Selects/unselects SALOME binaries" ) );
   QVBoxLayout* btnLayout = new QVBoxLayout; btnLayout->setMargin( 0 ); btnLayout->setSpacing( 6 );
   btnLayout->addWidget( unselectBtn );
+  btnLayout->addWidget( selectSrcBtn );
+  btnLayout->addWidget( selectBinBtn );
   // layouting advancet mode widgets
   moreBoxLayout->addMultiCellWidget( tempLab,      0, 0, 0, 2 );
   moreBoxLayout->addMultiCellWidget( tempFolder,   1, 1, 0, 1 );
@@ -477,19 +783,29 @@ void SALOME_InstallWizard::setupProductsPage()
     reader.setContentHandler( handler );
     reader.parse( source );  
   }
+  // take into account command line parameters
+  if ( !targetDirPath.isEmpty() )
+    targetFolder->setText( targetDirPath );
+  if ( !tmpDirPath.isEmpty() )
+    tempFolder->setText( tmpDirPath );
+
   // set first item to be selected
   if ( productsView->childCount() > 0 ) {
     productsView->setSelected( productsView->firstChild(), true );
-    onSelectionChanged( productsView->firstChild() );
+    onSelectionChanged();
   }
   // adding page
   addPage( productsPage, tr( "Installation settings" ) );
   // connecting signals
-  connect( productsView, SIGNAL( selectionChanged( QListViewItem* ) ), 
-                                              this, SLOT( onSelectionChanged( QListViewItem* ) ) );
+  connect( productsView, SIGNAL( selectionChanged() ), 
+                                              this, SLOT( onSelectionChanged() ) );
   connect( productsView, SIGNAL( itemToggled( QCheckListItem* ) ), 
                                               this, SLOT( onItemToggled( QCheckListItem* ) ) );
   connect( unselectBtn,  SIGNAL( clicked() ), this, SLOT( onProdBtn() ) );
+  connect( selectSrcBtn, SIGNAL( stateChanged(int) ), 
+                                             this, SLOT( onProdBtn() ) );
+  connect( selectBinBtn, SIGNAL( stateChanged(int) ), 
+                                             this, SLOT( onProdBtn() ) );
   // connecting signals
   connect( targetFolder, SIGNAL( textChanged( const QString& ) ),
                                               this, SLOT( directoryChanged( const QString& ) ) );
@@ -550,7 +866,7 @@ void SALOME_InstallWizard::setupProgressPage()
   QGridLayout* layout = new QGridLayout( widget ); 
   layout->setMargin( 0 ); layout->setSpacing( 6 );
   // installation progress view box
-  installInfo = new QTextEdit( widget );
+  installInfo = new InstallInfo( widget );
   installInfo->setReadOnly( true );
   installInfo->setTextFormat( RichText );
   installInfo->setUndoRedoEnabled ( false );
@@ -563,6 +879,10 @@ void SALOME_InstallWizard::setupProgressPage()
   passedParams = new QLineEdit ( widget );
   QWhatsThis::add( passedParams, tr( "Use this field to enter answer for the running script when it is necessary") );
   QToolTip::add  ( passedParams, tr( "Use this field to enter answer for the running script when it is necessary") );
+  // VSR: 10/11/05 - disable answer mode ==>
+  parametersLab->hide();
+  passedParams->hide();
+  // VSR: 10/11/05 - disable answer mode <==
   // layouting
   layout->addWidget( installInfo,   0, 0 );
   layout->addWidget( parametersLab, 1, 0 );
@@ -606,6 +926,7 @@ void SALOME_InstallWizard::setupReadmePage()
   readme = new QTextEdit( readmePage );
   readme->setReadOnly( true );
   readme->setTextFormat( PlainText );
+  readme->setFont( QFont( "Fixed", 12 ) );
   readme->setUndoRedoEnabled ( false );
   QWhatsThis::add( readme, tr( "Displays README information" ) );
   QToolTip::add  ( readme, tr( "Displays README information" ) );
@@ -613,18 +934,29 @@ void SALOME_InstallWizard::setupReadmePage()
   pal.setColor( QColorGroup::Base, QApplication::palette().active().background() );
   readme->setPalette( pal );
   readme->setMinimumHeight( 10 );
-  // <Launch SALOME> button
-  runSalomeBtn = new QPushButton( tr( "Launch SALOME" ), readmePage );
-  QWhatsThis::add( runSalomeBtn, tr( "Click this button to run SALOME desktop" ) );
-  QToolTip::add  ( runSalomeBtn, tr( "Click this button to run SALOME desktop" ) );
-  QHBoxLayout* hLayout = new QHBoxLayout;
-  hLayout->addWidget( runSalomeBtn ); hLayout->addStretch();
-  // layouting
+
   pageLayout->addWidget( readme );
   pageLayout->setStretchFactor( readme, 5 );
-  pageLayout->addLayout( hLayout );
-  // connecting signals
-  connect( runSalomeBtn, SIGNAL( clicked() ), this, SLOT( onLaunchSalome() ) );
+
+  // Operation buttons
+  if ( buttons.count() > 0 ) {
+    QHBoxLayout* hLayout = new QHBoxLayout;
+    hLayout->setMargin( 0 ); hLayout->setSpacing( 6 );
+    ButtonList::Iterator it;
+    for ( it = buttons.begin(); it != buttons.end(); ++it ) {
+      QButton* b = new QPushButton( tr( (*it).label() ), readmePage );
+      if ( !(*it).tootip().isEmpty() ) {
+       QWhatsThis::add( b, tr( (*it).tootip() ) );
+       QToolTip::add  ( b, tr( (*it).tootip() ) );
+      }
+      hLayout->addWidget( b ); 
+      (*it).setButton( b );
+      connect( b, SIGNAL( clicked() ), this, SLOT( onFinishButton() ) );
+    }
+    hLayout->addStretch();
+    pageLayout->addLayout( hLayout );
+  }
+
   // loading README file
   QString readmeFile = QDir::currentDirPath() + "/README";
   QString text;
@@ -632,6 +964,7 @@ void SALOME_InstallWizard::setupReadmePage()
     readme->setText( text );
   else
     readme->setText( tr( "README file has not been found" ) );
+
   // adding page
   addPage( readmePage, tr( "Finish installation" ) );
 }
@@ -651,21 +984,20 @@ void SALOME_InstallWizard::showChoiceInfo()
   QString text;
 
   if ( !xmlFileName.isEmpty() ) {
-    text += tr( "Configuration file: <b>" ) + xmlFileName + "</b><br>";
+    text += tr( "Configuration file" )+ ": <b>" + xmlFileName + "</b><br>";
     text += "<br>";
   }
   if ( !myOS.isEmpty() ) {
-    text += tr( "Target platform: <b>" ) + myOS + "</b><br>";
+    text += tr( "Reference Linux platform" ) + ": <b>" + myOS + "</b><br>";
     text += "<br>";
   }
-  text += tr( "Products to be used:<ul>" );
+  text += tr( "Native products to be used" ) + ":<ul>";
   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
   while( item ) {
     if ( productsMap.contains( item ) ) {
       if ( item->childCount() > 0 ) {
-        // Neither "SALOME binaries", no "SALOME sources"
         if ( productsView->isNative( item ) ) {
-          text += "<li><b>" + item->text() + "</b> as native<br>";
+          text += "<li><b>" + item->text() + "</b><br>";
           nbProd++;
         }
       }
@@ -673,26 +1005,25 @@ void SALOME_InstallWizard::showChoiceInfo()
     item = (QCheckListItem*)( item->nextSibling() );
   }
   if ( nbProd == 0 ) {
-    text += "<li><b>none</b><br>";
+    text += "<li><b>" + tr( "none" ) + "</b><br>";
   }
   text += "</ul>";
-  text += tr( "Products to be installed:<ul>" );
+  nbProd = 0;
+  text += tr( "Products to be installed" ) + ":<ul>";
   item = (QCheckListItem*)( productsView->firstChild() );
   while( item ) {
     if ( productsMap.contains( item ) ) {
       if ( item->childCount() > 0 ) {
-        // Neither "SALOME binaries", no "SALOME sources"
         if ( productsView->isBinaries( item ) ) {
-          text += "<li><b>" + item->text() + "</b> as binaries<br>";
+          text += "<li><b>" + item->text() + " " + item->text(1) + "</b> " + tr( "as binaries" ) + "<br>";
           nbProd++;
         }
         else if ( productsView->isSources( item ) ) {
-          text+= "<li><b>" + item->text() + "</b> as sources<br>";
+          text+= "<li><b>" + item->text() + " " + item->text(1) + "</b> " + tr( "as sources" ) + "<br>";
           nbProd++;
         }
       }
       else if ( item->isOn() ) {
-        // "SALOME binaries" or "SALOME sources"
         text+= "<li><b>" + item->text() + "</b><br>";
         nbProd++;
       }
@@ -700,17 +1031,17 @@ void SALOME_InstallWizard::showChoiceInfo()
     item = (QCheckListItem*)( item->nextSibling() );
   }
   if ( nbProd == 0 ) {
-    text += "<li><b>none</b><br>";
+    text += "<li><b>" + tr( "none" ) + "</b><br>";
   }
   text += "</ul>";
-  text += "Total disk space required: <b>" + QString::number( totSize ) + " Kb</b><br>" ;
-  text += "Space for temporary files required: <b>" + QString::number( tempSize ) + " Kb</b><br>" ;
+  text += tr( "Total disk space required:" ) + " <b>" + QString::number( totSize ) + " Kb</b><br>" ;
+  text += tr( "Space for temporary files required:" ) + " <b>" + QString::number( tempSize ) + " Kb</b><br>" ;
   text += "<br>";
-  text += "Target directory: <b>" + QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) + "</b><br>";
+  text += tr( "Target directory:" ) + " <b>" + QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) + "</b><br>";
   // VSR: Temporary folder is used always now and it is not necessary to disable it -->
   // if ( tempSize > 0 )
   // VSR: <----------------------------------------------------------------------------
-  text += "Temp directory: <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
+  text += tr( "Temporary directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
   text += "<br>";
   choices->setText( text );
 }
@@ -727,8 +1058,8 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
   if ( aPage == productsPage ) {
     // ########## check if any products are selected to be installed
     long totSize, tempSize;
-    checkSize( &totSize, &tempSize );
-    if ( totSize <= 0 ) {
+    bool anySelected = checkSize( &totSize, &tempSize );
+    if ( !anySelected ) {
       QMessageBox::warning( this, 
                             tr( "Warning" ), 
                             tr( "Select one or more products to install" ), 
@@ -767,7 +1098,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
        QMessageBox::warning( this, 
                              tr( "Warning" ), 
                              tr( "The directory %1 doesn't exist.\n"
-                                 "Do you want to create directory?" ).arg( fi.absFilePath() ), 
+                                 "Create directory?" ).arg( fi.absFilePath() ), 
                              QMessageBox::Yes, 
                              QMessageBox::No,
                              QMessageBox::NoButton ) == QMessageBox::Yes;
@@ -786,7 +1117,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
     if ( !fi.isDir() ) {
       QMessageBox::warning( this, 
                             tr( "Warning" ), 
-                            tr( "The directory %1 is not a directory.\n"
+                            tr( "%1 is not a directory.\n"
                                "Please, enter valid target directory path" ).arg( fi.absFilePath() ), 
                             QMessageBox::Ok, 
                             QMessageBox::NoButton,
@@ -814,28 +1145,67 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
                               QMessageBox::NoButton ) == QMessageBox::No ) {
       return false;
     }
-    QString binDir = "./Products/BINARIES";
-    if ( !myOS.isEmpty() )
-      binDir += "/" + myOS;
-    QFileInfo fib( QDir::cleanDirPath( binDir ) );
-    if ( !fib.exists() ) {
-      QMessageBox::warning( this, 
-                           tr( "Warning" ), 
-                           tr( "The directory %1 doesn't exist.\n"
-                               "This directory must contain binaries archives." ).arg( fib.absFilePath() ));
+    // check sources/binaries archives directories existance
+    int nbSources = 0, nbBinaries = 0; 
+    QCheckListItem* nitem = (QCheckListItem*)( productsView->firstChild() );
+    while( nitem ) {
+      if ( productsMap.contains( nitem ) ) {
+       if ( nitem->childCount() > 0 ) {
+         if ( productsView->isBinaries( nitem ) )
+           nbBinaries++;
+         else if ( productsView->isSources( nitem ) )
+           nbSources++;
+       }
+       else if ( nitem->isOn() ) {
+         nbBinaries++;
+         nbSources++;
+       }
+      }
+      nitem = (QCheckListItem*)( nitem->nextSibling() );
+    }
+
+    if ( nbBinaries > 0 ) {
+      QString binDir = "./Products/BINARIES";
+      if ( !myOS.isEmpty() )
+       binDir += "/" + myOS;
+      QFileInfo fib( QDir::cleanDirPath( binDir ) );
+      if ( !fib.exists() ) {
+       if ( QMessageBox::warning( this, 
+                                  tr( "Warning" ), 
+                                  tr( "The directory %1 doesn't exist.\n"
+                                      "This directory must contain binaries archives.\n"
+                                      "Continue?" ).arg( fib.absFilePath() ),
+                                  QMessageBox::Yes,
+                                  QMessageBox::No,
+                                  QMessageBox::NoButton ) == QMessageBox::No )
+         return false;
+      }
+    }
+    if ( nbSources > 0 ) {
+      QString srcDir = "./Products/SOURCES";
+      QFileInfo fis( QDir::cleanDirPath( srcDir ) );
+      if ( !fis.exists() ) {
+       if ( QMessageBox::warning( this, 
+                                  tr( "Warning" ), 
+                                  tr( "The directory %1 doesn't exist.\n"
+                                      "This directory must contain sources archives.\n"
+                                      "Continue?" ).arg( fis.absFilePath() ),
+                                  QMessageBox::Yes,
+                                  QMessageBox::No,
+                                  QMessageBox::NoButton ) == QMessageBox::No )
+         return false;
+      }
     }
     // run script that checks available disk space for installing of products    // returns 1 in case of error
     QString script = "./config_files/checkSize.sh '";
     script += fi.absFilePath();
     script += "' ";
     script += QString( "%1" ).arg( totSize );
-#ifdef DEBUG
-    cout << "script = " << script << endl;
-#endif
+    ___MESSAGE___( "script = " << script );
     if ( system( script ) ) {
       QMessageBox::critical( this, 
                              tr( "Out of space" ), 
-                             tr( "There is not available disk space for installing of selected products" ), 
+                             tr( "There is no available disk space for installing of selected products" ), 
                              QMessageBox::Ok, 
                              QMessageBox::NoButton, 
                              QMessageBox::NoButton );
@@ -846,14 +1216,15 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
       if ( moreMode ) {
        QMessageBox::warning( this, 
                              tr( "Warning" ), 
-                             tr( "Please, enter valid temp directory path" ), 
+                             tr( "Please, enter valid temporary directory path" ), 
                              QMessageBox::Ok, 
                              QMessageBox::NoButton,
                              QMessageBox::NoButton );
        return false; 
       }
       else {
-       tempFolder->setText( "/tmp" );
+       tempDir = "/tmp";
+       tempFolder->setText( tempDir );
       }
     }
     QFileInfo fit( QDir::cleanDirPath( tempDir ) );
@@ -872,13 +1243,11 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
     tscript += fit.absFilePath();
     tscript += "' ";
     tscript += QString( "%1" ).arg( tempSize );
-#ifdef DEBUG
-    cout << "script = " << tscript << endl;
-#endif
+    ___MESSAGE___( "script = " << tscript );
     if ( system( tscript ) ) {
       QMessageBox::critical( this, 
                             tr( "Out of space" ), 
-                            tr( "There is not available disk space for the temporary files" ), 
+                            tr( "There is no available disk space for the temporary files" ), 
                             QMessageBox::Ok, 
                             QMessageBox::NoButton, 
                             QMessageBox::NoButton );
@@ -891,30 +1260,41 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
     while( item ) {
       if ( productsMap.contains( item ) ) {
        if ( item->childCount() > 0 ) {
-         if ( !productsView->isNone( item ) ) {
+         // VSR : 29/01/05 : Check installation script even if product is not being installed
+         //      if ( !productsView->isNone( item ) ) {
            if ( item->text(2).isEmpty() || item->text(2).isNull() ) {
              QMessageBox::warning( this, 
-                                   tr( "Warning" ), 
-                                   tr( "You don't have a defined script for %1").arg(item->text(0)), 
+                                   tr( "Error" ), 
+                                   tr( "The installation script for %1 is not defined.").arg(item->text(0)), 
                                    QMessageBox::Ok, 
                                    QMessageBox::NoButton, 
                                    QMessageBox::NoButton );
-             productsView->setNone( item );
+              if ( !moreMode )
+               onMoreBtn();
+             productsView->setCurrentItem( item );
+             productsView->setSelected( item, true );
+             productsView->ensureItemVisible( item );
+             //productsView->setNone( item );
              return false;
            } else {
              QFileInfo fi( QString("./config_files/") + item->text(2) );
-             if ( !fi.exists() ) {
+             if ( !fi.exists() || !fi.isExecutable() ) {
                QMessageBox::warning( this, 
-                                     tr( "Warning" ),  
-                                     tr( "%1 required for %2 doesn't exist.").arg("./config_files/" + item->text(2)).arg(item->text(0)),  
+                                     tr( "Error" ),  
+                                     tr( "The script %1 required for %2 doesn't exist or doesn't have execute permissions.").arg("./config_files/" + item->text(2)).arg(item->text(0)),  
                                      QMessageBox::Ok, 
                                      QMessageBox::NoButton, 
                                      QMessageBox::NoButton );
-               productsView->setNone( item );
+                if ( !moreMode )
+                 onMoreBtn();
+               productsView->setCurrentItem( item );
+               productsView->setSelected( item, true );
+               productsView->ensureItemVisible( item );
+               //productsView->setNone( item );
                return false;
              }       
            }
-         }
+           //    }
          // collect native products
          if ( productsView->isNative( item ) ) {
            if ( natives.find( item->text(0) ) == natives.end() )
@@ -930,9 +1310,9 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
              } 
              else {
                QMessageBox::warning( this, 
-                                     tr( "Warning" ), 
+                                     tr( "Error" ), 
                                      tr( "%1 is required for %2 %3 installation.\n"
-                                         "Please, add this product in config.xml file.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)), 
+                                         "This product is missing in the configuration file %4.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)).arg(xmlFileName), 
                                      QMessageBox::Ok, 
                                      QMessageBox::NoButton, 
                                      QMessageBox::NoButton );
@@ -946,37 +1326,32 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
     }
     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
-    for ( unsigned i = 0; i < natives.count(); i++ ) {
-      item = findItem( natives[ i ] );
-      if ( item ) {
-       QString script = "cd ./config_files/;" + item->text(2) + " try_native " +
-               QFileInfo( tmpFolder ).absFilePath() + " " + QDir::currentDirPath() + "/Products " + QFileInfo( tgtFolder ).absFilePath() + " " +
-               QUOTE(DefineDependeces(productsMap)) + " " + item->text(0);
+    myThread->clearCommands();
+    if ( natives.count() > 0 ) {
+      for ( unsigned i = 0; i < natives.count(); i++ ) {
+       item = findItem( natives[ i ] );
+       if ( item ) {
+         QString dependOn = productsMap[ item ].getDependancies().join(" ");
+         QString script = "cd ./config_files/;" + item->text(2) + " try_native " +
+                 QFileInfo( tmpFolder ).absFilePath() + " " + QDir::currentDirPath() + "/Products " + QFileInfo( tgtFolder ).absFilePath() + " " +
+                 QUOTE(dependOn) + " " + item->text(0);
 
-#ifdef DEBUG
-       cout << "1. Script : " << script << endl;
-#endif
-       if ( system( script ) ) {
+         myThread->addCommand( item, script );
+       }
+       else {
          QMessageBox::warning( this, 
                                tr( "Warning" ), 
-                               tr( "You don't have native %1 %2 installed").arg(item->text(0)).arg(item->text(1)), 
+                               tr( "%The product %1 %2 required for installation.\n"
+                                   "This product is missing in the configuration file %4.").arg(item->text(0)).arg(item->text(1)).arg(xmlFileName),
                                QMessageBox::Ok, 
                                QMessageBox::NoButton, 
                                QMessageBox::NoButton );
-         productsView->setNone( item );
          return false;
        }
       }
-      else {
-       QMessageBox::warning( this, 
-                             tr( "Warning" ), 
-                             tr( "%The product %1 %2 required for installation.\n"
-                                 "Please, add this product in config.xml file.").arg(item->text(0)).arg(item->text(1)),
-                             QMessageBox::Ok, 
-                             QMessageBox::NoButton, 
-                             QMessageBox::NoButton );
-       return false;
-      }
+      WarnDialog::showWarnDlg( this, true );
+      myThread->start();
+      return true; // return in order to avoid default postValidateEvent() action
     }
   }
   return InstallWizard::acceptData( pageTitle );
@@ -987,10 +1362,10 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
  *  Calculates disk space required for the installation
  */
 // ================================================================
-void SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
+bool SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
 {
   long tots = 0, temps = 0;
-  int nativeProd = 0;
+  int nbSelected = 0;
 
   MapProducts::Iterator mapIter;
   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
@@ -1003,65 +1378,97 @@ void SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
       tots += dep.getSize(true);
       temps = max( temps, dep.getTempSize() );
     }
-    else if ( productsView->isNative( item ) ) {
-      nativeProd++;
-    }
+    if ( !productsView->isNone( item ) )
+      nbSelected++;
   }
  
-  requiredSize->setText( QString::number( tots )  + " Kb");
-  requiredTemp->setText( QString::number( temps ) + " Kb");
   if ( totSize )
     *totSize = tots;
   if ( tempSize )
     *tempSize = temps;
-  setNextEnabled( productsPage, (tots > 0) || (nativeProd > 0));
+  return ( nbSelected > 0 );
 }
 // ================================================================
 /*!
- *  SALOME_InstallWizard::checkDirs
- *  Enabled/disables "Next" button for the directory page
+ *  SALOME_InstallWizard::checkProductPage
+ *  Checks products page validity (directories and products selection) and
+ *  enabled/disables "Next" button for the Products page
  */
 // ================================================================
-void SALOME_InstallWizard::checkDirs()
+void SALOME_InstallWizard::checkProductPage()
 {
-  // VSR: Temporary folder is used always now and it is not necessary to disable it -->
-  // get disk space required
-  //long totSize, tempSize;
-  //checkSize( &totSize, &tempSize );
-  // enable/disable temp directory controls
-  // tempFolder->setEnabled( tempSize > 0 );
-  // tempBtn->setEnabled( tempSize > 0 );
-  // VSR: <----------------------------------------------------------------------------
-  // get dirs
-  QString targetDir = targetFolder->text().stripWhiteSpace();
+  long tots = 0, temps = 0;
+
+  // check if any product is selected;
+  bool isAnyProductSelected = checkSize( &tots, &temps );
+  // check if target directory is valid
+  bool isTargetDirValid = !targetFolder->text().stripWhiteSpace().isEmpty();
+  // check if temp directory is valid
+  bool isTempDirValid = !moreMode || !tempFolder->text().stripWhiteSpace().isEmpty();
+
+  // update required size information
+  requiredSize->setText( QString::number( tots )  + " Kb");
+  requiredTemp->setText( QString::number( temps ) + " Kb");
+  
+  // update <SALOME sources>, <SALOME binaries> check boxes state
+  int totSrc = 0, selSrc = 0;
+  int totBin = 0, selBin = 0;
+  MapProducts::Iterator itProd;
+  for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
+    bool srcctx = itProd.data().hasContext( "salome sources" );
+    bool binctx = itProd.data().hasContext( "salome binaries" );
+    if ( srcctx && !binctx ) {
+      totSrc++;
+      if ( productsView->isSources( itProd.key() ) )
+       selSrc++;
+    }
+    if ( binctx && !srcctx ) {
+      totBin++;
+      if ( productsView->isBinaries( itProd.key() ) )
+       selBin++;
+    }
+  }
+  selectSrcBtn->blockSignals( true );
+  selectBinBtn->blockSignals( true );
+  selectSrcBtn->setState( selSrc == 0 ? QButton::Off : ( selSrc == totSrc ? QButton::On : QButton::NoChange  ) );
+  selectBinBtn->setState( selBin == 0 ? QButton::Off : ( selBin == totBin ? QButton::On : QButton::NoChange  ) );
+  selectSrcBtn->blockSignals( false );
+  selectBinBtn->blockSignals( false );
+
   // enable/disable "Next" button
-  setNextEnabled( productsPage, !targetDir.isEmpty() );
+  setNextEnabled( productsPage, isAnyProductSelected && isTargetDirValid && isTempDirValid );
 }
 // ================================================================
 /*!
- *  SALOME_InstallWizard::setProductOn
+ *  SALOME_InstallWizard::setPrerequisites
  *  Sets the product and all products this one depends on to be checked ( recursively )
  */
 // ================================================================
-void SALOME_InstallWizard::setProductOn( QCheckListItem* item, int install )
+void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
 {
   if ( !productsMap.contains( item ) )
     return;
-  if ( productsView->isNone( item ) ) {
-    if ( install == 1 )
-      productsView->setBinaries( item );
-    else if ( install == 0 )
-      productsView->setSources( item );
-    else if ( install == 2 )
-      productsView->setNative( item );
-  }
+  if ( productsView->isNone( item ) )
+    return;
   // get all prerequisites
   QStringList dependOn = productsMap[ item ].getDependancies();
   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
     MapProducts::Iterator itProd;
     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
-      if ( itProd.data().getName() == dependOn[ i ] )
-        setProductOn( itProd.key(), 1 );
+      if ( itProd.data().getName() == dependOn[ i ] ) {
+       if ( productsView->isNone( itProd.key() ) ) {
+         QString defMode = itProd.data().getDefault();
+         if ( defMode.isEmpty() )
+           defMode = tr( "install binaries" );
+         if ( defMode == tr( "install binaries" ) )
+           productsView->setBinaries( itProd.key() );
+         else if ( defMode == tr( "install sources" ) )
+           productsView->setSources( itProd.key() );
+         else if ( defMode == tr( "use native" ) )
+           productsView->setNative( itProd.key() );
+         setPrerequisites( itProd.key() );
+       }
+      }
     }
   }
 }
@@ -1076,9 +1483,7 @@ void SALOME_InstallWizard::launchScript()
   // try to find product being processed now
   QString prodProc = progressView->findStatus( Processing );
   if ( !prodProc.isNull() ) {
-#ifdef DEBUG
-    cout << "Found <Processing>: " << prodProc.latin1() << endl;
-#endif
+    ___MESSAGE___( "Found <Processing>: " );
 
     // if found - set status to "completed"
     progressView->setStatus( prodProc, Completed );
@@ -1089,15 +1494,12 @@ void SALOME_InstallWizard::launchScript()
   // else try to find next product which is not processed yet
   prodProc = progressView->findStatus( Waiting );
   if ( !prodProc.isNull() ) {
-#ifdef DEBUG
-    cout << "Found <Waiting>: " << prodProc.latin1() << endl;
-#endif
+    ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
     // if found - set status to "processed" and run script
     progressView->setStatus( prodProc, Processing );
     progressView->ensureVisible( prodProc );
 
     QCheckListItem* item = findItem( prodProc );
-    Dependancies dep = productsMap[ item ];
     // fill in script parameters
     shellProcess->clearArguments();
     // ... script name
@@ -1106,8 +1508,8 @@ void SALOME_InstallWizard::launchScript()
 
     // ... temp folder
     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
-    if( !tempFolder->isEnabled() )
-      tmpFolder = "/tmp";
+    //if( !tempFolder->isEnabled() )
+    //tmpFolder = "/tmp";
 
     // ... binaries ?
     if ( productsView->isBinaries( item ) ) {
@@ -1142,9 +1544,7 @@ void SALOME_InstallWizard::launchScript()
     
 
     QString depproducts = DefineDependeces(productsMap); 
-#ifdef DEBUG
-    cout << "Dependancies"<< depproducts.latin1() << endl;
-#endif
+    ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
 
     shellProcess->addArgument( depproducts );
     // ... product name - currently instaled product
@@ -1153,29 +1553,51 @@ void SALOME_InstallWizard::launchScript()
     // run script
     if ( !shellProcess->start() ) {
       // error handling can be here
-#ifdef DEBUG
-      cout << "error" << endl;
-#endif
+      ___MESSAGE___( "error" );
     }
     return;
   }
-#ifdef DEBUG
-  cout << "All products have been installed successfully" << endl;
-#endif
-  // all products installed successfully
+  ___MESSAGE___( "All products have been installed successfully" );
+  // all products are installed successfully
+  QString workDir = QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() );
+  MapProducts::Iterator mapIter;
+  ___MESSAGE___( "starting pick-up environment" );
+  for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
+    QCheckListItem* item = mapIter.key();
+    Dependancies dep = mapIter.data();
+    QString depproducts = QUOTE( DefineDependeces(productsMap) ); 
+    if ( !productsView->isNone( item ) && dep.pickUpEnvironment() ) {
+      ___MESSAGE___( "... for " << dep.getName() );
+      QString script;
+      script += "cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
+      script += item->text(2) + " ";
+      script += "pickup_env ";
+      script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
+      script += QUOTE( QFileInfo( QDir::cleanDirPath( QDir::currentDirPath() + "/Products" ) ).absFilePath() ) + " ";
+      script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
+      script += depproducts + " ";
+      script += item->text(0);
+      ___MESSAGE___( "... --> " << script.latin1() );
+      if ( system( script.latin1() ) ) { 
+       ___MESSAGE___( "ERROR" ); 
+      }
+    }
+  }
   // <Next> button
-  nextButton()->setEnabled( true );
+  setNextEnabled( true );
   nextButton()->setText( tr( "&Next >" ) );
   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
-  nextButton()->disconnect();
-  connect( nextButton(), SIGNAL( clicked() ), this, SLOT( next() ) );
+  disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
+  disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
+  connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
   // <Back> button
-  backButton()->setEnabled( true );
+  setBackEnabled( true );
   // script parameters
   passedParams->clear();
   passedParams->setEnabled( false );
   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
+  installInfo->setFinished( true );
   if ( isMinimized() )
     showNormal();
   raise();
@@ -1205,33 +1627,32 @@ void SALOME_InstallWizard::onMoreBtn()
     resize( geometry().width(), 0 );
     qApp->processEvents();
   }
+  checkProductPage();
 }
 // ================================================================
 /*!
- *  SALOME_InstallWizard::onLaunchSalome
- *  <Launch Salome> button slot
+ *  SALOME_InstallWizard::onFinishButton
+ *  Operation buttons slot
  */
 // ================================================================
-void SALOME_InstallWizard::onLaunchSalome()
+void SALOME_InstallWizard::onFinishButton()
 {
-  QCheckListItem* item = 0;
-  if ( ( item = findItem("SalomePro-Bin" ) ) ) {
-    QFileInfo fi( targetFolder->text() + "/SalomePro-" + item->text(1) + "/salome" );
-    if ( fi.exists() ) {
+  const QObject* btn = sender();
+  ButtonList::Iterator it;
+  for ( it = buttons.begin(); it != buttons.end(); ++it ) {
+    if ( (*it).button() && (*it).button() == btn ) {
       QString script;
-      script += "cd " + targetFolder->text() + "/SalomePro-" + item->text(1) + "; ";
-      script += "source salome.csh; ";
-      //script += "cd bin; ";
-      //script += "runSalome > /dev/null";
-      script += "salome -g > /dev/null";
-      script = "(csh -c '" + script + "')";
-#ifdef DEBUG
-      cout << script.latin1() << endl;
-#endif
-      if ( system( script.latin1() ) ){
+      script += "( cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
+      script +=  + (*it).script();
+      script += " execute ";
+      script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
+      script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
+      script += " > /dev/null )";
+      ___MESSAGE___( "script: " << script.latin1() );
+      if ( (*it).script().isEmpty() || system( script.latin1() ) ) {
        QMessageBox::warning( this, 
                              tr( "Error" ), 
-                             tr( "Can't launch SALOME" ), 
+                             tr( "Can't perform action!"),
                              QMessageBox::Ok, 
                              QMessageBox::NoButton,
                              QMessageBox::NoButton );
@@ -1239,13 +1660,19 @@ void SALOME_InstallWizard::onLaunchSalome()
       return;
     }
   }
-  QMessageBox::warning( this, 
-                       tr( "Error" ), 
-                       tr( "You don't have SALOME binaries installed in the %1 directory!" ).arg( targetFolder->text() ), 
-                       QMessageBox::Ok, 
-                       QMessageBox::NoButton,
-                       QMessageBox::NoButton );
 }
+// ================================================================
+/*!
+ *  SALOME_InstallWizard::onAbout
+ *  <About> button slot: shows <About> dialog box
+ */
+// ================================================================
+void SALOME_InstallWizard::onAbout()
+{
+  AboutDlg d( this );
+  d.exec();
+}
+
 // ================================================================
 /*!
  *  SALOME_InstallWizard::findItem
@@ -1288,15 +1715,13 @@ void SALOME_InstallWizard::abort()
 // ================================================================
 void SALOME_InstallWizard::reject()
 {
-#ifdef DEBUG
-  cout << "REJECTED" << endl;
-#endif
+  ___MESSAGE___( "REJECTED" );
   if ( !exitConfirmed ) {
     if ( QMessageBox::information( this, 
                                   tr( "Exit" ), 
                                   tr( "Do you want to quit %1?" ).arg( getIWName() ), 
-                                  tr( "Yes" ), 
-                                  tr( "No" ),
+                                  tr( "&Yes" ), 
+                                  tr( "&No" ),
                                   QString::null,
                                   0,
                                   1 ) == 1 ) {
@@ -1304,7 +1729,7 @@ void SALOME_InstallWizard::reject()
     }
     exitConfirmed = true;
   }
-  clean();
+  clean(true);
   InstallWizard::reject();
 }
 // ================================================================
@@ -1315,41 +1740,39 @@ void SALOME_InstallWizard::reject()
 // ================================================================
 void SALOME_InstallWizard::accept()
 {
-#ifdef DEBUG
-  cout << "ACCEPTED" << endl;
-#endif
-  clean();
+  ___MESSAGE___( "ACCEPTED" );
+  clean(true);
   InstallWizard::accept();
 }
 // ================================================================
 /*!
  *  SALOME_InstallWizard::clean
- *  Clears and removes temporary directory
+ *  Clears and (optionally) removes temporary directory
  */
 // ================================================================
-void SALOME_InstallWizard::clean()
+void SALOME_InstallWizard::clean(bool rmDir)
 {
+  WarnDialog::showWarnDlg( 0, false );
+  myThread->clearCommands();
+  myWC.wakeAll();
+  while ( myThread->running() );
   // VSR: first remove temporary files
   QString script = "cd ./config_files/; remove_tmp.sh '";
-  script += tempFolder->text().stripWhiteSpace();
+  script += tempFolder->text().stripWhiteSpace() + TEMPDIRNAME;
   script += "' ";
   script += QUOTE(DefineDependeces(productsMap));
   script += " > /dev/null";
-#ifdef DEBUG
-  cout << "script = " << script << endl;
-#endif
+  ___MESSAGE___( "script = " << script );
   if ( system( script.latin1() ) ) {
   }
   // VSR: then try to remove created temporary directory
   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
-  if ( !tmpCreated.isNull() ) {
+  if ( rmDir && !tmpCreated.isNull() ) {
     script = "rm -rf " + tmpCreated;
     script += " > /dev/null";
     if ( system( script.latin1() ) ) {
     }
-#ifdef DEBUG
-    cout << "script = " << script << endl;
-#endif
+    ___MESSAGE___( "script = " << script );
   }
 }
 // ================================================================
@@ -1363,8 +1786,9 @@ void SALOME_InstallWizard::pageChanged( const QString & mytitle)
   nextButton()->setText( tr( "&Next >" ) );
   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
-  nextButton()->disconnect();
-  connect( nextButton(), SIGNAL( clicked() ), this, SLOT( next() ) );
+  disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
+  disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
+  connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
   cancelButton()->disconnect();
   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
 
@@ -1374,8 +1798,8 @@ void SALOME_InstallWizard::pageChanged( const QString & mytitle)
   updateCaption();
   if ( aPage == productsPage ) {
     // products page
-    checkSize();
-    checkDirs();
+    onSelectionChanged();
+    checkProductPage();
   }
   else if ( aPage == prestartPage ) {
     // prestart page
@@ -1386,31 +1810,42 @@ void SALOME_InstallWizard::pageChanged( const QString & mytitle)
       // progress page
       progressView->clear();
       installInfo->clear();
+      installInfo->setFinished( false );
       passedParams->clear();
       passedParams->setEnabled( false );
       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
-      nextButton()->setText( tr("&Start") );
+      nextButton()->setText( tr( "&Start" ) );
       QWhatsThis::add( nextButton(), tr( "Starts installation process" ) );
       QToolTip::add  ( nextButton(), tr( "Starts installation process" ) );
       // reconnect Next button - to use it as Start button
-      nextButton()->disconnect();
-      connect( nextButton(), SIGNAL( clicked() ), this, SLOT( onStart() ) );
-      nextButton()->setEnabled( true );
+      disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
+      disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
+      connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
+      setNextEnabled( true );
       // reconnect Cancel button to terminate process
       cancelButton()->disconnect();
       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
     }
   }
   else if ( aPage == readmePage ) {
-    QCheckListItem* item = 0;
-    runSalomeBtn->setEnabled( ( item = findItem( "SalomePro-Bin" ) ) && 
-                             QFileInfo( targetFolder->text() + "/SalomePro-" + item->text(1) + "/salome" ).exists() );
+    ButtonList::Iterator it;
+    for ( it = buttons.begin(); it != buttons.end(); ++it ) {
+      if ( (*it).button() ) {
+       QString script;
+       script += "( cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
+       script +=  + (*it).script();
+       script += " check_enabled ";
+       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
+       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
+       script += " > /dev/null )";
+       ___MESSAGE___( "script: " << script.latin1() );
+       (*it).button()->setEnabled( !(*it).script().isEmpty() && !system( script.latin1() ) );
+      }
+    }
     finishButton()->setEnabled( true );
   }
   previousPage = aPage;
-#ifdef DEBUG
-  cout << "previousPage = " << previousPage << endl;
-#endif
+  ___MESSAGE___( "previousPage = " << previousPage );
 }
 // ================================================================
 /*!
@@ -1458,7 +1893,7 @@ void SALOME_InstallWizard::browseDirectory()
     theFolder->setText( typedDir );
     theFolder->end( false );
   }
-  checkDirs();
+  checkProductPage();
 }
 // ================================================================
 /*!
@@ -1468,7 +1903,7 @@ void SALOME_InstallWizard::browseDirectory()
 // ================================================================
 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
 {
-  checkDirs();
+  checkProductPage();
 }
 // ================================================================
 /*!
@@ -1478,6 +1913,17 @@ void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
 // ================================================================
 void SALOME_InstallWizard::onStart()
 {
+  if ( nextButton()->text() == tr( "&Stop" ) ) {
+    shellProcess->kill();
+    while( shellProcess->isRunning() );
+    return;
+  }
+  progressView->clear();
+  installInfo->clear();
+  installInfo->setFinished( false );
+  passedParams->clear();
+  passedParams->setEnabled( false );
+  QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
   // clear list of products to install ...
   toInstall.clear();
   // ... and fill it for new process
@@ -1491,10 +1937,14 @@ void SALOME_InstallWizard::onStart()
   }
   // if something at all is selected
   if ( !toInstall.isEmpty() ) {
+    clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
     // disable <Next> button
-    nextButton()->setEnabled( false );
+    //setNextEnabled( false );
+    nextButton()->setText( tr( "&Stop" ) );
+    QWhatsThis::add( nextButton(), tr( "Aborts installation process" ) );
+    QToolTip::add  ( nextButton(), tr( "Aborts installation process" ) );
     // disable <Back> button
-    backButton()->setEnabled ( false );
+    setBackEnabled( false );
     // enable script parameters line edit
     // VSR commented: 18/09/03: passedParams->setEnabled( true );
     // VSR commented: 18/09/03: passedParams->setFocus();
@@ -1503,13 +1953,13 @@ void SALOME_InstallWizard::onStart()
       item = findItem( toInstall[ i ] );
       QString type = "";
       if ( productsView->isBinaries( item ) )
-       type = "binaries";
+       type = tr( "binaries" );
       else if ( productsView->isSources( item ) )
-       type = "sources";
+       type = tr( "sources" );
       else if ( productsView->isNative( item ) )
-       type = "native";
+       type = tr( "native" );
       else 
-       type = "not install";
+       type = tr( "not install" );
       progressView->addProduct( item->text(0), type, item->text(2) );
     }
     // launch install script
@@ -1538,35 +1988,38 @@ void SALOME_InstallWizard::onReturnPressed()
 */
 void SALOME_InstallWizard::productInstalled( )
 {
-#ifdef DEBUG
-  cout << "process exited" << endl;
-#endif
+  ___MESSAGE___( "process exited" );
   if ( shellProcess->normalExit() ) {
-#ifdef DEBUG
-    cout << "...normal exit" << endl;
-#endif
+    ___MESSAGE___( "...normal exit" );
     // normal exit - try to proceed installation further
     launchScript();
   }
   else {
-#ifdef DEBUG
-    cout << "...abnormal exit" << endl;
-#endif
+    ___MESSAGE___( "...abnormal exit" );
     // installation aborted
     abort();
     // clear script passed parameters lineedit
     passedParams->clear();
     passedParams->setEnabled( false );
     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
+    installInfo->setFinished( true );
     // enable <Next> button
-    nextButton()->setEnabled( true );
-    nextButton()->setText( tr( "&Next >" ) );
-    QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
-    QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
-    nextButton()->disconnect();
-    connect( nextButton(), SIGNAL( clicked() ), this, SLOT( next() ) );
+    setNextEnabled( true );
+    nextButton()->setText( tr( "&Start" ) );
+    QWhatsThis::add( nextButton(), tr( "Starts installation process" ) );
+    QToolTip::add  ( nextButton(), tr( "Starts installation process" ) );
+    // reconnect Next button - to use it as Start button
+    disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
+    disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
+    connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
+    //nextButton()->setText( tr( "&Next >" ) );
+    //QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
+    //QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
+    //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
+    //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
+    //connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
     // enable <Back> button
-    backButton()->setEnabled( true );
+    setBackEnabled( true );
   }
 }
 // ================================================================
@@ -1581,8 +2034,8 @@ void SALOME_InstallWizard::tryTerminate()
     if ( QMessageBox::information( this, 
                                   tr( "Exit" ), 
                                   tr( "Do you want to quit %1?" ).arg( getIWName() ), 
-                                  tr( "Yes" ), 
-                                  tr( "No" ),
+                                  tr( "&Yes" ), 
+                                  tr( "&No" ),
                                   QString::null,
                                   0,
                                   1 ) == 1 ) {
@@ -1617,35 +2070,48 @@ void SALOME_InstallWizard::onCancel()
  *  Called when selection is changed in the products list view
  */
 // ================================================================
-void SALOME_InstallWizard::onSelectionChanged( QListViewItem* item )
+void SALOME_InstallWizard::onSelectionChanged()
 {
   productsInfo->clear();
+  QListViewItem* item = productsView->selectedItem();
+  if ( !item )
+    return;
   if ( item->parent() )
     item = item->parent();
   QCheckListItem* aItem = (QCheckListItem*)item;
   if ( !productsMap.contains( aItem ) )
     return;
   Dependancies dep = productsMap[ aItem ];
-  QString text = "<b>" + aItem->text(0) + "</b>";
-  text += "<br><br>";
+  QString text = "<b>" + aItem->text(0) + "</b>" + "<br>";
   if ( !aItem->text(1).stripWhiteSpace().isEmpty() )
-    text += "version: " + aItem->text(1) + "<br>";
-  if ( productsView->isBinaries( aItem ) )
-    text += "Disk space required: " + QString::number( dep.getSize() ) + " Kb";
-  else
-    text += "Disk space required: " + QString::number( dep.getSize(true) ) + " Kb";
-
+    text += tr( "Version" ) + ": " + aItem->text(1) + "<br>";
   text += "<br>";
-  text += "Disk space for tmp files required: " + QString::number( dep.getTempSize() ) + " Kb";
-  text += "<br><br>";
-  QString req =( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : QString( "none" ) );
-//    if ( item->depth() == 0 && item->childCount() == 0 ) {
-//      if ( dep.getName() == "salomedoc" )
-//        req = "none";          // SALOME docs
-//      else
-//        req = "all products";  // SALOME sources and binaries
-//    }
-  text +=  "Prerequisites: " + req;
+  if ( !dep.getDescription().isEmpty() ) {
+    text += "<i>" + dep.getDescription() + "</i><br><br>";
+  }
+  text += tr( "User choice" ) + ": ";
+  long totSize = 0, tempSize = 0;
+  if ( productsView->isBinaries( aItem ) ) {
+    text += "<b>" + tr( "install binaries" ) + "</b>" + "<br>";
+    totSize = dep.getSize();
+  }
+  else if ( productsView->isSources( aItem ) ) {
+    text += "<b>" + tr( "install sources" ) + "</b>" + "<br>";
+    totSize = dep.getSize( true );
+    tempSize = dep.getTempSize();
+  }
+  else if ( productsView->isNative( aItem ) ) {
+    text += "<b>" + tr( "use native" ) + "</b>" + "<br>";
+  }
+  else {
+    text += "<b>" + tr( "not install" ) + "</b>" + "<br>";
+  }
+  
+  text += tr( "Disk space required" ) + ": " + QString::number( totSize ) + " Kb<br>";
+  text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " Kb<br>";
+  text += "<br>";
+  QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
+  text +=  tr( "Prerequisites" ) + ": " + req;
   productsInfo->setText( text );
 }
 // ================================================================
@@ -1662,16 +2128,12 @@ void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
       item = (QCheckListItem*)( item->parent() );
     if ( productsMap.contains( item ) ) {
       productsView->blockSignals( true );
-      if ( productsView->isNative( item ) )
-       setProductOn( item, 2 );
-      else if ( productsView->isBinaries( item ) )
-       setProductOn( item, 1 );
-      else if ( productsView->isSources( item ) )
-       setProductOn( item, 0 );
+      setPrerequisites( item );
       productsView->blockSignals( false );
     }
   }
-  checkSize();
+  onSelectionChanged();
+  checkProductPage();
 }
 // ================================================================
 /*!
@@ -1684,6 +2146,8 @@ void SALOME_InstallWizard::onProdBtn()
 {
   const QObject* snd = sender();
   productsView->blockSignals( true );
+  selectSrcBtn->blockSignals( true );
+  selectBinBtn->blockSignals( true );
   if ( snd == unselectBtn ) {
     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
     while( item ) {
@@ -1691,8 +2155,65 @@ void SALOME_InstallWizard::onProdBtn()
       item = (QCheckListItem*)( item->nextSibling() );
     }
   }
+  else if ( snd == selectSrcBtn )  {
+    QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
+    if ( checkBox->state() == QButton::NoChange )
+      checkBox->setState( QButton::On );
+    MapProducts::Iterator itProd;
+    for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
+      if ( itProd.data().hasContext( "salome sources" ) ) {
+       if ( checkBox->state() == QButton::Off ) {
+         int selBin = 0;
+         MapProducts::Iterator itProd1;
+         for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
+           if (  itProd1.data().hasContext( "salome binaries" ) && 
+                !itProd1.data().hasContext( "salome sources" ) &&
+                 productsView->isBinaries( itProd1.key() ) )
+             selBin++;
+         }
+         if ( !itProd.data().hasContext( "salome binaries" ) || !selBin )
+           productsView->setNone( itProd.key() );
+       }
+       else {
+         productsView->setSources( itProd.key() );
+         if ( prerequisites->isChecked() )
+           setPrerequisites( itProd.key() );
+       }
+      }
+    }
+  }
+  else if ( snd == selectBinBtn )  {
+    QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
+    if ( checkBox->state() == QButton::NoChange )
+      checkBox->setState( QButton::On );
+    MapProducts::Iterator itProd;
+    for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
+      if ( itProd.data().hasContext( "salome binaries" ) ) {
+       if ( checkBox->state() == QButton::Off ) {
+         int selSrc = 0;
+         MapProducts::Iterator itProd1;
+         for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
+           if (  itProd1.data().hasContext( "salome sources" ) && 
+                !itProd1.data().hasContext( "salome binaries" ) &&
+                 productsView->isSources( itProd1.key() ) )
+             selSrc++;
+         }
+         if ( !itProd.data().hasContext( "salome sources" ) || !selSrc )
+           productsView->setNone( itProd.key() );
+       }
+       else {
+         productsView->setBinaries( itProd.key() );
+         if ( prerequisites->isChecked() )
+           setPrerequisites( itProd.key() );
+       }
+      }
+    }
+  }
+  selectSrcBtn->blockSignals( false );
+  selectBinBtn->blockSignals( false );
   productsView->blockSignals( false );
-  checkSize();
+  onSelectionChanged();
+  checkProductPage();
 }
 // ================================================================
 /*!
@@ -1702,9 +2223,7 @@ void SALOME_InstallWizard::onProdBtn()
 // ================================================================
 void SALOME_InstallWizard::wroteToStdin( )
 {
-#ifdef DEBUG
-  cout << "Something was sent to stdin" << endl;
-#endif
+  ___MESSAGE___( "Something was sent to stdin" );
 }
 // ================================================================
 /*!
@@ -1714,9 +2233,7 @@ void SALOME_InstallWizard::wroteToStdin( )
 // ================================================================
 void SALOME_InstallWizard::readFromStdout( )
 {
-#ifdef DEBUG
-  cout << "Something was sent to stdout" << endl;
-#endif
+  ___MESSAGE___( "Something was sent to stdout" );
   while ( shellProcess->canReadLineStdout() ) {
     installInfo->append( QString( shellProcess->readLineStdout() ) );
     installInfo->scrollToBottom();
@@ -1727,6 +2244,9 @@ void SALOME_InstallWizard::readFromStdout( )
     installInfo->scrollToBottom();
   }
 }
+
+#define OUTLINE_TEXT(x) QString( "<font color=#FF0000><b>" ) + QString( x ) + QString( "</b></font>" )
+
 // ================================================================
 /*!
  *  SALOME_InstallWizard::readFromStderr
@@ -1735,21 +2255,21 @@ void SALOME_InstallWizard::readFromStdout( )
 // ================================================================
 void SALOME_InstallWizard::readFromStderr( )
 {
-#ifdef DEBUG
-  cout << "Something was sent to stderr" << endl;
-#endif
+  ___MESSAGE___( "Something was sent to stderr" );
   while ( shellProcess->canReadLineStderr() ) {
-    installInfo->append( QString( shellProcess->readLineStderr() ) );
+    installInfo->append( OUTLINE_TEXT( QString( shellProcess->readLineStderr() ) ) );
     installInfo->scrollToBottom();
   }
   QString str( shellProcess->readStderr() );
   if ( !str.isEmpty() ) {
-    installInfo->append( str );
+    installInfo->append( OUTLINE_TEXT( str ) );
     installInfo->scrollToBottom();
   }
-  passedParams->setEnabled( true );
-  passedParams->setFocus();
-  QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
+  // VSR: 10/11/05 - disable answer mode ==>
+  // passedParams->setEnabled( true );
+  // passedParams->setFocus();
+  // QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
+  // VSR: 10/11/05 - disable answer mode <==
 }
 // ================================================================
 /*!
@@ -1762,6 +2282,19 @@ void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies d
   productsMap[item] = dep;
 }
 // ================================================================
+/*!
+ *  SALOME_InstallWizard::addFinishButton
+ *  Add button for the <Finish> page
+ */
+// ================================================================
+void SALOME_InstallWizard::addFinishButton( const QString& label, 
+                                           const QString& tooltip, 
+                                           const QString& script)
+{
+  if ( !label.isEmpty() )
+    buttons.append( Button( label, tooltip, script ) );
+}
+// ================================================================
 /*!
  *  SALOME_InstallWizard::polish
  *  Polishing of the widget - to set right initial size
@@ -1773,6 +2306,41 @@ void SALOME_InstallWizard::polish()
   InstallWizard::polish();
 }
 // ================================================================
+/*!
+ *  SALOME_InstallWizard::saveLog
+ *  Save installation log to file
+ */
+// ================================================================
+void SALOME_InstallWizard::saveLog()
+{
+  QString txt = installInfo->text();
+  if ( txt.length() <= 0 )
+    return;
+  QDateTime dt = QDateTime::currentDateTime();
+  QString fileName = dt.toString("ddMMyy-hhmm");
+  fileName.prepend("install-"); fileName.append(".html");
+  fileName = QFileDialog::getSaveFileName( fileName,
+                                          QString( "HTML files (*.htm *.html)" ),
+                                          this, 0,
+                                          tr( "Save Log file" ) );
+  if ( !fileName.isEmpty() ) {
+    QFile f( fileName );
+    if ( f.open( IO_WriteOnly ) ) {
+      QTextStream stream( &f );
+      stream << txt;
+      f.close();
+    }
+    else {
+      QMessageBox::critical( this, 
+                            tr( "Error" ), 
+                            tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ), 
+                            QMessageBox::Ok, 
+                            QMessageBox::NoButton, 
+                            QMessageBox::NoButton );
+    }
+  }
+}
+// ================================================================
 /*!
  *  SALOME_InstallWizard::updateCaption
  *  Updates caption according to the current page number
@@ -1787,3 +2355,80 @@ void SALOME_InstallWizard::updateCaption()
                             tr( getIWName() ) + " - " +
                             tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
 }
+
+// ================================================================
+/*!
+ *  SALOME_InstallWizard::processValidateEvent
+ *  Processes validation event (<val> is validation code)
+ */
+// ================================================================
+void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
+{
+  QWidget* aPage = InstallWizard::currentPage();
+  if ( aPage != productsPage ) {
+    InstallWizard::processValidateEvent( val, data );
+    return;
+  }
+  myMutex.lock();
+  myMutex.unlock();
+  QCheckListItem* item = (QCheckListItem*)data;
+  if ( val > 0 ) {
+    if ( val == 2 ) {
+      WarnDialog::showWarnDlg( 0, false );
+      // when try_native returns 2 it means that native product version is higher than that is prerequisited
+      if ( QMessageBox::warning( this, 
+                                tr( "Warning" ), 
+                                tr( "You have newer version of %1 installed on your computer than that is required (%2).\nContinue?").arg(item->text(0)).arg(item->text(1)),
+                               QMessageBox::Yes, 
+                               QMessageBox::No, 
+                               QMessageBox::NoButton ) == QMessageBox::No ) {
+       myThread->clearCommands();
+       myWC.wakeAll();
+       setNextEnabled( true );
+       setBackEnabled( true );
+       return;
+      }
+      WarnDialog::showWarnDlg( this, true );
+    }
+    else {
+      WarnDialog::showWarnDlg( 0, false );
+      bool binMode = productsView->hasBinaries( item );
+      bool srcMode = productsView->hasSources( item );
+      QStringList buttons;
+      buttons.append( binMode ? tr( "Install binaries" ) : ( srcMode ? tr( "Install sources" ) : 
+                                                                      tr( "Select manually" ) ) );
+      buttons.append( binMode ? ( srcMode ? tr( "Install sources" ) : tr( "Select manually" ) ) :
+                                ( srcMode ? tr( "Select manually" ) : QString::null ) );
+      buttons.append( binMode && srcMode ? tr( "Select manually" ) : QString::null );
+      int answer = QMessageBox::warning( this, 
+                                        tr( "Warning" ), 
+                                        tr( "You don't have native %1 %2 on your computer.\nPlease, change your installation settings.").arg(item->text(0)).arg(item->text(1)), 
+                                        buttons[0],
+                                        buttons[1],
+                                        buttons[2] );
+      if ( buttons[ answer ] == tr( "Install binaries" ) )
+        productsView->setBinaries( item );
+      else if ( buttons[ answer ] == tr( "Install sources" ) )
+        productsView->setSources( item );
+      else {
+        if ( !moreMode )
+         onMoreBtn();
+       productsView->setCurrentItem( item );
+       productsView->setSelected( item, true );
+       productsView->ensureItemVisible( item );
+        myThread->clearCommands();
+        myWC.wakeAll();
+        setNextEnabled( true );
+        setBackEnabled( true );
+        return;
+      }
+      WarnDialog::showWarnDlg( this, true );
+    }
+  }
+  if ( myThread->hasCommands() )
+    myWC.wakeAll();
+  else {
+    WarnDialog::showWarnDlg( 0, false );
+    InstallWizard::processValidateEvent( val, data );
+  }
+}