Salome HOME
Merge from Mandrake_10_1 branch (version 2.2.4)
[tools/install.git] / src / SALOME_InstallWizard.cxx
index 09c1be3bbc5e86fbbd606e116ccbe7b9312559cc..ecc0a901f762b66de73df4561eefe1e8e18a26e3 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$ 
+//  Project   : SALOME
+//  Module    : Installation Wizard
+//  Copyright : 2004-2005 CEA
+
+#include "globals.h"
 
 #include "SALOME_InstallWizard.hxx"
 #include "SALOME_ProductsView.hxx"
@@ -33,6 +34,9 @@
 #include <qwhatsthis.h> 
 #include <qtooltip.h>
 #include <qfile.h>
+#include <qthread.h>
+#include <qwaitcondition.h>
+#include <qmutex.h>
 
 #ifdef WNT
 #include <iostream.h>
 QString tmpDirName() { return QString(  "/INSTALLWORK" ) + QString::number( getpid() ); }
 #define TEMPDIRNAME tmpDirName()
 
+// ================================================================
+/*!
+ *  QProcessThread
+ *  Class for executing systen commands
+ */
+// ================================================================
+static QMutex myMutex(false);
+static QWaitCondition myWC;
+class QProcessThread: public QThread
+{
+  typedef QPtrList<QCheckListItem> ItemList;
+public:
+  QProcessThread( 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___( "QProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() );
+      int result = system( myCommands[ 0 ] ) / 256; // return code is <errno> * 256 
+      ___MESSAGE___( "QProcessThread::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; 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;
+
 // ================================================================
 /*!
  *  DefineDependeces [ static ]
  *  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();
@@ -168,6 +270,19 @@ static bool hasSpace( const QString& dir )
   return false;
 }
 
+// ================================================================
+/*!
+ *  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 ); }
+};
+
 // ================================================================
 /*!
  *  SALOME_InstallWizard::SALOME_InstallWizard
@@ -188,12 +303,12 @@ SALOME_InstallWizard::SALOME_InstallWizard(QString aXmlFileName)
   setTitleFont( fnt );
 
   // set icon
-  setIcon( QPixmap( ( const char** ) image0_data ) );
+  setIcon( QPixmap( ( const char** ) image_icon ) );
   // enable sizegrip
   setSizeGripEnabled( true );
   
   // add logo
-  addLogo( QPixmap( (const char**)image1_data ) );
+  addLogo( QPixmap( (const char**)image_logo ) );
   
   // set defaults
   setVersion( "1.2" );
@@ -202,9 +317,7 @@ SALOME_InstallWizard::SALOME_InstallWizard(QString aXmlFileName)
   setLicense( tr( "All right reserved" ) );
   setOS( "" );
 
-#ifdef DEBUG
-  cout << "Config. file : " << xmlFileName << endl;
-#endif
+  ___MESSAGE___( "Config. file : " << xmlFileName );
 
   // xml reader
   QFile xmlfile(xmlFileName);
@@ -252,6 +365,9 @@ SALOME_InstallWizard::SALOME_InstallWizard(QString aXmlFileName)
   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 QProcessThread( this );
 }
 // ================================================================
 /*!
@@ -267,12 +383,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;
 }
 // ================================================================
 /*!
@@ -294,6 +409,10 @@ 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" ), 
@@ -442,12 +561,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 );
@@ -493,6 +623,10 @@ void SALOME_InstallWizard::setupProductsPage()
   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& ) ) );
@@ -609,6 +743,7 @@ void SALOME_InstallWizard::setupReadmePage()
   readme = new QTextEdit( readmePage );
   readme->setReadOnly( true );
   readme->setTextFormat( PlainText );
+  readme->setFont( QFont( "Fixed", 10 ) );
   readme->setUndoRedoEnabled ( false );
   QWhatsThis::add( readme, tr( "Displays README information" ) );
   QToolTip::add  ( readme, tr( "Displays README information" ) );
@@ -830,9 +965,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
     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" ), 
@@ -874,9 +1007,7 @@ 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" ), 
@@ -948,37 +1079,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"
+                                   "Please, add this product in config.xml file.").arg(item->text(0)).arg(item->text(1)),
                                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 );
@@ -1036,6 +1162,29 @@ void SALOME_InstallWizard::checkProductPage()
   // 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 ) {
+    if ( itProd.data().getContext() == "salome sources" ) {
+      totSrc++;
+      if ( productsView->isSources( itProd.key() ) )
+       selSrc++;
+    }
+    if ( itProd.data().getContext() == "salome binaries" ) {
+      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, isAnyProductSelected && isTargetDirValid && isTempDirValid );
@@ -1085,9 +1234,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 );
@@ -1098,15 +1245,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
@@ -1151,9 +1295,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
@@ -1162,29 +1304,21 @@ 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
+  ___MESSAGE___( "All products have been installed successfully" );
   // all products are installed successfully
   QString workDir = QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() );
   MapProducts::Iterator mapIter;
-#ifdef DEBUG
-  cout << "starting pick-up environment" << endl;
-#endif
+  ___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 ( dep.pickUpEnvironment() ) {
-#ifdef DEBUG
-      cout << "... for " << dep.getName() << endl;
-#endif
+      ___MESSAGE___( "... for " << dep.getName() );
       QString script;
       script += "cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
       script += item->text(2) + " ";
@@ -1194,25 +1328,22 @@ void SALOME_InstallWizard::launchScript()
       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
       script += depproducts + " ";
       script += item->text(0);
-#ifdef DEBUG
-      cout << "... --> " << script.latin1() << endl;
-#endif
+      ___MESSAGE___( "... --> " << script.latin1() );
       if ( system( script.latin1() ) ) { 
-#ifdef DEBUG
-       cout << "ERROR" << endl; 
-#endif
+       ___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 );
@@ -1270,9 +1401,7 @@ void SALOME_InstallWizard::onLaunchSalome()
        script += "cd bin/salome; ";
        script += "runSalome > /dev/null";
        script = "(csh -c '" + script + "')";
-#ifdef DEBUG
-       cout << script.latin1() << endl;
-#endif
+       ___MESSAGE___( "script: " << script.latin1() );
        if ( !system( script.latin1() ) )
          return;
        else
@@ -1333,9 +1462,7 @@ void SALOME_InstallWizard::abort()
 // ================================================================
 void SALOME_InstallWizard::reject()
 {
-#ifdef DEBUG
-  cout << "REJECTED" << endl;
-#endif
+  ___MESSAGE___( "REJECTED" );
   if ( !exitConfirmed ) {
     if ( QMessageBox::information( this, 
                                   tr( "Exit" ), 
@@ -1349,7 +1476,7 @@ void SALOME_InstallWizard::reject()
     }
     exitConfirmed = true;
   }
-  clean();
+  clean(true);
   InstallWizard::reject();
 }
 // ================================================================
@@ -1360,41 +1487,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() + 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 );
   }
 }
 // ================================================================
@@ -1408,8 +1533,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() ) );
 
@@ -1438,9 +1564,10 @@ void SALOME_InstallWizard::pageChanged( const QString & mytitle)
       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() ) );
@@ -1454,9 +1581,7 @@ void SALOME_InstallWizard::pageChanged( const QString & mytitle)
     finishButton()->setEnabled( true );
   }
   previousPage = aPage;
-#ifdef DEBUG
-  cout << "previousPage = " << previousPage << endl;
-#endif
+  ___MESSAGE___( "previousPage = " << previousPage );
 }
 // ================================================================
 /*!
@@ -1537,10 +1662,11 @@ 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 );
     // 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();
@@ -1584,20 +1710,14 @@ 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
@@ -1605,14 +1725,15 @@ void SALOME_InstallWizard::productInstalled( )
     passedParams->setEnabled( false );
     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
     // enable <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() ) );
     // enable <Back> button
-    backButton()->setEnabled( true );
+    setBackEnabled( true );
   }
 }
 // ================================================================
@@ -1739,6 +1860,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 ) {
@@ -1746,6 +1869,36 @@ 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().getContext() == "salome sources" ) {
+       if ( checkBox->state() == QButton::Off )
+         productsView->setNone( itProd.key() );
+       else
+         productsView->setSources( 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().getContext() == "salome binaries" ) {
+       if ( checkBox->state() == QButton::Off )
+         productsView->setNone( itProd.key() );
+       else
+         productsView->setBinaries( itProd.key() );
+      }
+    }
+  }
+  selectSrcBtn->blockSignals( false );
+  selectBinBtn->blockSignals( false );
   productsView->blockSignals( false );
   onSelectionChanged();
   checkProductPage();
@@ -1758,9 +1911,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" );
 }
 // ================================================================
 /*!
@@ -1770,9 +1921,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();
@@ -1791,9 +1940,7 @@ 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->scrollToBottom();
@@ -1843,3 +1990,61 @@ 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 );
+      QMessageBox::warning( this, 
+                          tr( "Warning" ), 
+                          tr( "You don't have native %1 %2 installed").arg(item->text(0)).arg(item->text(1)), 
+                          QMessageBox::Ok, 
+                          QMessageBox::NoButton, 
+                          QMessageBox::NoButton );
+      myThread->clearCommands();
+      myWC.wakeAll();
+      setNextEnabled( true );
+      setBackEnabled( true );
+      productsView->setNone( item );
+      return;
+    }
+  }
+  if ( myThread->hasCommands() )
+    myWC.wakeAll();
+  else {
+    WarnDialog::showWarnDlg( 0, false );
+    InstallWizard::processValidateEvent( val, data );
+  }
+}