Salome HOME
Merge fixes from SALOME_3 branch
[tools/install.git] / src / SALOME_InstallWizard.cxx
1 //  File      : SALOME_InstallWizard.cxx 
2 //  Created   : Thu Dec 18 12:01:00 2002
3 //  Author    : Vadim SANDLER
4 //  Project   : SALOME
5 //  Module    : Installation Wizard
6 //  Copyright : 2004-2005 CEA
7
8 #include "globals.h"
9
10 #include "SALOME_InstallWizard.hxx"
11 #include "SALOME_ProductsView.hxx"
12 #include "SALOME_ProgressView.hxx"
13 #include "SALOME_XmlHandler.hxx"
14 #include "SALOME_HelpWindow.hxx"
15
16 #include "icons.h"
17
18 #include <qlineedit.h>
19 #include <qpushbutton.h>
20 #include <qlistview.h>
21 #include <qlabel.h>
22 #include <qtextedit.h>
23 #include <qtextbrowser.h>
24 #include <qprocess.h>
25 #include <qcheckbox.h>
26 #include <qsplitter.h>
27 #include <qlayout.h>
28 #include <qfiledialog.h> 
29 #include <qapplication.h>
30 #include <qfileinfo.h> 
31 #include <qmessagebox.h> 
32 #include <qtimer.h> 
33 #include <qvbox.h>
34 #include <qwhatsthis.h> 
35 #include <qtooltip.h>
36 #include <qfile.h>
37 #include <qthread.h>
38 #include <qwaitcondition.h>
39 #include <qmutex.h>
40 #include <qstringlist.h>
41
42 #ifdef WNT
43 #include <iostream.h>
44 #include <process.h>
45 #else
46 #include <unistd.h>
47 #include <algo.h>
48 #endif
49
50 #ifdef WNT
51 #define max( x, y ) ( x ) > ( y ) ? ( x ) : ( y )
52 #endif
53
54 QString tmpDirName() { return QString(  "/INSTALLWORK" ) + QString::number( getpid() ); }
55 #define TEMPDIRNAME tmpDirName()
56
57 // ================================================================
58 /*!
59  *  QProcessThread
60  *  Class for executing systen commands
61  */
62 // ================================================================
63 static QMutex myMutex(false);
64 static QWaitCondition myWC;
65 class QProcessThread: public QThread
66 {
67   typedef QPtrList<QCheckListItem> ItemList;
68 public:
69   QProcessThread( SALOME_InstallWizard* iw ) : QThread(), myWizard( iw ) { myItems.setAutoDelete( false ); }
70
71   void addCommand( QCheckListItem* item, const QString& cmd ) {
72     myItems.append( item );
73     myCommands.push_back( cmd );
74   }
75
76   bool hasCommands() const { return myCommands.count() > 0; }
77   void clearCommands()     { myCommands.clear(); myItems.clear(); }
78
79   virtual void run() {
80     while ( hasCommands() ) {
81       ___MESSAGE___( "QProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() );
82       int result = system( myCommands[ 0 ] ) / 256; // return code is <errno> * 256 
83       ___MESSAGE___( "QProcessThread::run - Result : " << result );
84       QCheckListItem* item = myItems.first();
85       myCommands.pop_front();
86       myItems.removeFirst();
87       myMutex.lock();
88       SALOME_InstallWizard::postValidateEvent( myWizard, result, (void*)item );
89       if ( hasCommands() )
90         myWC.wait(&myMutex);
91       myMutex.unlock();
92     };
93   }
94
95 private:
96   QStringList           myCommands;
97   ItemList              myItems;
98   SALOME_InstallWizard* myWizard;
99 };
100
101 // ================================================================
102 /*!
103  *  WarnDialog
104  *  Warning dialog box
105  */
106 // ================================================================
107 class WarnDialog: public QDialog
108 {
109   static WarnDialog* myDlg;
110   bool myCloseFlag;
111
112   WarnDialog( QWidget* parent ) 
113   : QDialog( parent, "WarnDialog", true, WDestructiveClose ) {
114     setCaption( tr( "Information" ) );
115     myCloseFlag = false;
116     QLabel* lab = new QLabel( tr( "Please, wait while checking native products configuration ..." ), this );
117     lab->setAlignment( AlignCenter );
118     lab->setFrameStyle( QFrame::Box | QFrame::Plain ); 
119     QVBoxLayout* l = new QVBoxLayout( this );
120     l->setMargin( 0 );
121     l->add( lab );
122     this->setFixedSize( lab->sizeHint().width()  + 50, 
123                         lab->sizeHint().height() * 5 );
124   }
125   void accept() { return; }
126   void reject() { return; }
127   void closeEvent( QCloseEvent* e) { if ( !myCloseFlag ) return; QDialog::closeEvent( e ); }
128   
129   ~WarnDialog() { myDlg = 0; }
130 public:
131   static void showWarnDlg( QWidget* parent, bool show ) {
132     if ( show ) {
133       if ( !myDlg ) {
134         myDlg = new WarnDialog( parent );
135         QSize sh = myDlg->size();
136         myDlg->move( parent->x() + (parent->width()-sh.width())/2, 
137                      parent->y() + (parent->height()-sh.height())/2 );
138         myDlg->show();
139       }
140       myDlg->raise();
141       myDlg->setFocus();
142     }
143     else {
144       if ( myDlg ) {
145         myDlg->myCloseFlag = true;
146         myDlg->close();
147       }
148     }
149   }
150   static bool isWarnDlgShown() { return myDlg != 0; }
151 };
152 WarnDialog* WarnDialog::myDlg = 0;
153
154 // ================================================================
155 /*!
156  *  DefineDependeces [ static ]
157  *  Defines list of dependancies as string separated by space symbols
158  */
159 // ================================================================
160 static QString DefineDependeces(MapProducts& theProductsMap) 
161 {
162   QStringList aProducts;
163   for ( MapProducts::Iterator mapIter = theProductsMap.begin(); mapIter != theProductsMap.end(); ++mapIter ) {
164     QCheckListItem* item = mapIter.key();
165     Dependancies dep = mapIter.data();
166     QStringList deps = dep.getDependancies();
167     for (int i = 0; i<(int)deps.count(); i++ ) {
168       if ( !aProducts.contains( deps[i] ) )
169         aProducts.append( deps[i] );
170     }
171     if ( !aProducts.contains( item->text(0) ) )
172       aProducts.append( item->text(0) );
173   }
174   return aProducts.join(" ");
175 }
176
177 #define QUOTE(arg) QString("'") + QString(arg) + QString("'")
178
179 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
180                T H E   O L D   I M P L E M E N T A T I O N 
181 static QString DefineDependeces(MapProducts& theProductsMap, QCheckListItem* product ){
182   QStringList aProducts;
183   if ( theProductsMap.contains( product ) ) {
184     Dependancies dep = theProductsMap[ product ];
185     QStringList deps = dep.getDependancies();
186     for (int i = 0; i<(int)deps.count(); i++ ) {
187       aProducts.append( deps[i] );
188     }
189   }
190   return QString("\"") + aProducts.join(" ") + QString("\"");
191 }
192 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
193
194 // ================================================================
195 /*!
196  *  makeDir [ static ]
197  *  Makes directory recursively, returns false if not succedes
198  */
199 // ================================================================
200 static bool makeDir( const QString& theDir, QString& theCreated )
201 {
202   if ( theDir.isEmpty() )
203     return false;
204   QString aDir = QDir::cleanDirPath( QFileInfo( theDir ).absFilePath() );
205   int start = 1;
206   while ( start > 0 ) {
207     start = aDir.find( QDir::separator(), start );
208     if ( start > 0 ) {
209       QFileInfo fi( aDir.left( start ) );
210       if ( !fi.exists() ) {
211         // VSR: Create directory and set permissions to allow other users to remove it
212         QString script = "mkdir " + fi.absFilePath();
213         script += "; chmod 777 " + fi.absFilePath();
214         script += " > /dev/null";
215         if ( system( script.latin1() ) )
216           return false;
217         // VSR: Remember the top of the created directory (to remove it in the end of the installation)
218         if ( theCreated.isNull() )
219           theCreated = fi.absFilePath();
220       }
221     }
222     start++;
223   }
224   if ( !QFileInfo( aDir ).exists() ) {
225     // VSR: Create directory, other users should NOT have possibility to remove it!!!
226     QString script = "mkdir " + aDir;
227     script += " > /dev/null";
228     if ( system( script.latin1() ) )
229       return false;
230     // VSR: Remember the top of the created directory (to remove it in the end of the installation)
231     if ( theCreated.isNull() )
232       theCreated = aDir;
233   }
234   return true;
235 }
236 // ================================================================
237 /*!
238  *  readFile [ static ]
239  *  Reads the file, returns false if can't open it
240  */
241 // ================================================================
242 static bool readFile( const QString& fileName, QString& text )
243 {
244   if ( QFile::exists( fileName ) ) {
245     QFile file( fileName );
246     if ( file.open( IO_ReadOnly ) ) {
247       QTextStream stream( &file );
248       QString line;
249       while ( !stream.eof() ) {
250         line = stream.readLine(); // line of text excluding '\n'
251         text += line + "\n";
252       }
253       file.close();
254       return true;
255     }
256   }
257   return false;
258 }
259 // ================================================================
260 /*!
261  *  hasSpace [ static ]
262  *  Checks if string contains spaces; used to check directory paths
263  */
264 // ================================================================
265 static bool hasSpace( const QString& dir )
266 {
267   for ( int i = 0; i < (int)dir.length(); i++ ) {
268     if ( dir[ i ].isSpace() )
269       return true;
270   }
271   return false;
272 }
273
274 // ================================================================
275 /*!
276  *  QMyCheckBox class : custom check box
277  *  The only goal is to give access to the protected setState() method
278  */
279 // ================================================================
280 class QMyCheckBox: public QCheckBox
281 {
282 public:
283   QMyCheckBox( const QString& text, QWidget* parent, const char* name = 0 ) : QCheckBox ( text, parent, name ) {}
284   void setState ( ToggleState s ) { QCheckBox::setState( s ); }
285 };
286
287 // ================================================================
288 /*!
289  *  SALOME_InstallWizard::SALOME_InstallWizard
290  *  Constructor
291  */
292 // ================================================================
293 SALOME_InstallWizard::SALOME_InstallWizard(QString aXmlFileName)
294      : InstallWizard( qApp->desktop(), "SALOME_InstallWizard", false, 0 ), 
295        helpWindow( NULL ), 
296        moreMode( false ), 
297        previousPage( 0 ), 
298        exitConfirmed( false )
299 {
300   myIWName = tr( "Installation Wizard" );
301   tmpCreated = QString::null;
302   xmlFileName = aXmlFileName;
303   QFont fnt = font(); fnt.setPointSize( 14 ); fnt.setBold( true );
304   setTitleFont( fnt );
305
306   // set icon
307   setIcon( QPixmap( ( const char** ) image_icon ) );
308   // enable sizegrip
309   setSizeGripEnabled( true );
310   
311   // add logo
312   addLogo( QPixmap( (const char**)image_logo ) );
313   
314   // set defaults
315   setVersion( "1.2" );
316   setCaption( tr( "PAL/SALOME %1" ).arg( myVersion ) );
317   setCopyright( tr( "Copyright (C) 2004 CEA" ) );
318   setLicense( tr( "All right reserved" ) );
319   setOS( "" );
320
321   ___MESSAGE___( "Config. file : " << xmlFileName );
322
323   // xml reader
324   QFile xmlfile(xmlFileName);
325   if ( xmlfile.exists() ) {
326     QXmlInputSource source( &xmlfile );
327     QXmlSimpleReader reader;
328
329     StructureParser* handler = new StructureParser( this );
330     reader.setContentHandler( handler );
331     reader.parse( source );  
332   }
333
334   // create instance of class for starting shell install script
335   shellProcess = new QProcess( this, "shellProcess" );
336
337   // create introduction page
338   setupIntroPage();
339   // create products page
340   setupProductsPage();
341   // create prestart page
342   setupCheckPage();
343   // create progress page
344   setupProgressPage();
345   // create readme page
346   setupReadmePage();
347   
348   // common buttons
349   QWhatsThis::add( backButton(),   tr( "Returns to the previous step of the installation procedure" ) );
350   QToolTip::add  ( backButton(),   tr( "Returns to the previous step of the installation procedure" ) );
351   QWhatsThis::add( nextButton(),   tr( "Moves to the next step of the installation procedure" ) );
352   QToolTip::add  ( nextButton(),   tr( "Moves to the next step of the installation procedure" ) );
353   QWhatsThis::add( finishButton(), tr( "Finishes installation and quits program" ) );
354   QToolTip::add  ( finishButton(), tr( "Finishes installation and quits program" ) );
355   QWhatsThis::add( cancelButton(), tr( "Cancels installation and quits program" ) );
356   QToolTip::add  ( cancelButton(), tr( "Cancels installation and quits program" ) );
357   QWhatsThis::add( helpButton(),   tr( "Displays help information window" ) );
358   QToolTip::add  ( helpButton(),   tr( "Displays help information window" ) );
359   
360   // common signals connections
361   connect( this, SIGNAL( selected( const QString& ) ),
362                                           this, SLOT( pageChanged( const QString& ) ) );
363   connect( this, SIGNAL( helpClicked() ), this, SLOT( helpClicked() ) );
364   // catch signals from launched script
365   connect(shellProcess, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout() ) );
366   connect(shellProcess, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr() ) );
367   connect(shellProcess, SIGNAL( processExited() ),   this, SLOT( productInstalled() ) );
368   connect(shellProcess, SIGNAL( wroteToStdin() ),    this, SLOT( wroteToStdin() ) );
369
370   // create validation thread
371   myThread = new QProcessThread( this );
372 }
373 // ================================================================
374 /*!
375  *  SALOME_InstallWizard::~SALOME_InstallWizard
376  *  Destructor
377  */
378 // ================================================================
379 SALOME_InstallWizard::~SALOME_InstallWizard()
380 {
381   shellProcess->kill(); // kill it for sure
382   QString script = "kill -9 ";
383   int PID = (int)shellProcess->processIdentifier();
384   if ( PID > 0 ) {
385     script += QString::number( PID );
386     script += " > /dev/null";
387     ___MESSAGE___( "script: " << script.latin1() );
388     if ( system( script.latin1() ) ) { 
389     }
390   }
391   delete myThread;
392 }
393 // ================================================================
394 /*!
395  *  SALOME_InstallWizard::eventFilter
396  *  Event filter, spies for Help window closing
397  */
398 // ================================================================
399 bool SALOME_InstallWizard::eventFilter( QObject* object, QEvent* event )
400 {
401   if ( object && object == helpWindow && event->type() == QEvent::Close )
402     helpWindow = NULL;
403   return InstallWizard::eventFilter( object, event );
404 }
405 // ================================================================
406 /*!
407  *  SALOME_InstallWizard::closeEvent
408  *  Close event handler
409  */
410 // ================================================================
411 void SALOME_InstallWizard::closeEvent( QCloseEvent* ce )
412 {
413   if ( WarnDialog::isWarnDlgShown() ) {
414     ce->ignore();
415     return;
416   }
417   if ( !exitConfirmed ) {
418     if ( QMessageBox::information( this, 
419                                    tr( "Exit" ), 
420                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
421                                    tr( "&Yes" ), 
422                                    tr( "&No" ),
423                                    QString::null,
424                                    0,
425                                    1 ) == 1 ) {
426       ce->ignore();
427     }
428     else {
429       ce->accept();
430       exitConfirmed = true;
431       reject();
432     }
433   }
434 }
435 // ================================================================
436 /*!
437  *  SALOME_InstallWizard::setupIntroPage
438  *  Creates introduction page
439  */
440 // ================================================================
441 void SALOME_InstallWizard::setupIntroPage()
442 {
443   // create page
444   introPage = new QWidget( this, "IntroPage" );
445   QGridLayout* pageLayout = new QGridLayout( introPage ); 
446   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
447   // create logo picture
448   QPixmap logo( (const char**)SALOME_Logo_xpm );
449   logoLab = new QLabel( introPage );
450   logoLab->setPixmap( logo );
451   logoLab->setScaledContents( false );
452   logoLab->setFrameStyle( QLabel::Plain | QLabel::Box );
453   logoLab->setAlignment( AlignCenter );
454   // create version box
455   QVBox* versionBox = new QVBox( introPage ); versionBox->setSpacing( 6 );
456   versionBox->setFrameStyle( QVBox::Panel | QVBox::Sunken );
457   QWidget* stretch1 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch1, 5 );
458   versionLab = new QLabel( QString("%1 %2").arg( tr( "Version" ) ).arg(myVersion), versionBox );
459   versionLab->setAlignment( AlignCenter );
460   copyrightLab = new QLabel( myCopyright, versionBox );
461   copyrightLab->setAlignment( AlignCenter );
462   licenseLab = new QLabel( myLicense, versionBox );
463   licenseLab->setAlignment( AlignCenter );
464   QWidget* stretch2 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch2, 5 );
465   // create info box
466   info = new QLabel( introPage );
467   info->setText( tr( "This program will install <b>%1</b>."
468                      "<br><br>The wizard will also help you to install all products "
469                      "which are necessary for <b>%2</b> and setup "
470                      "your environment.<br><br>Click <code>Cancel</code> button to abort "
471                      "installation and quit. Click <code>Next</code> button to continue with the "
472                      "installation program." ).arg( myCaption ).arg( myCaption ) );
473   info->setFrameStyle( QLabel::WinPanel | QLabel::Sunken );
474   info->setMargin( 6 );
475   info->setAlignment( WordBreak );
476   info->setMinimumWidth( 250 );
477   QPalette pal = info->palette();
478   pal.setColor( QColorGroup::Background, QApplication::palette().active().base() );
479   info->setPalette( pal );
480   info->setLineWidth( 2 );
481   // layouting
482   pageLayout->addWidget( logoLab, 0, 0 );
483   pageLayout->addWidget( versionBox, 1, 0 );
484   pageLayout->addMultiCellWidget( info, 0, 1, 1, 1 );
485   pageLayout->setColStretch( 1, 5 );
486   pageLayout->setRowStretch( 1, 5 );
487   // adding page
488   addPage( introPage, tr( "Introduction" ) );
489 }
490 // ================================================================
491 /*!
492  *  SALOME_InstallWizard::setupProductsPage
493  *  Creates products page
494  */
495 // ================================================================
496 void SALOME_InstallWizard::setupProductsPage()
497 {
498   // create page
499   productsPage = new QWidget( this, "ProductsPage" );
500   QGridLayout* pageLayout = new QGridLayout( productsPage ); 
501   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
502   // target directory
503   QLabel* targetLab = new QLabel( tr( "Type the target directory:" ), productsPage );
504   targetFolder = new QLineEdit( productsPage );
505   QWhatsThis::add( targetFolder, tr( "Enter target root directory where products will be installed" ) );
506   QToolTip::add  ( targetFolder, tr( "Enter target root directory where products will be installed" ) );
507   targetBtn = new QPushButton( tr( "Browse..." ), productsPage );
508   QWhatsThis::add( targetBtn, tr( "Click this to browse target directory" ) );
509   QToolTip::add  ( targetBtn, tr( "Click this to browse target directory" ) );
510   // create advanced mode widgets container
511   moreBox = new QWidget( productsPage );
512   QGridLayout* moreBoxLayout = new QGridLayout( moreBox );
513   moreBoxLayout->setMargin( 0 ); moreBoxLayout->setSpacing( 6 );
514   // temp directory
515   QLabel* tempLab = new QLabel( tr( "Type the directory for the temporary files:" ), moreBox );
516   tempFolder = new QLineEdit( moreBox );
517   //  tempFolder->setText( "/tmp" ); // default is /tmp directory
518   QWhatsThis::add( tempFolder, tr( "Enter directory where to put temporary files" ) );
519   QToolTip::add  ( tempFolder, tr( "Enter directory where to put temporary files" ) );
520   tempBtn = new QPushButton( tr( "Browse..." ), moreBox );
521   tempBtn->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
522   QWhatsThis::add( tempBtn, tr( "Click this to browse temporary directory" ) );
523   QToolTip::add  ( tempBtn, tr( "Click this to browse temporary directory" ) );
524   // create products list
525   productsView = new ProductsView( moreBox );
526   productsView->setMinimumSize( 250, 180 );
527   QWhatsThis::add( productsView, tr( "This view lists the products you wish to be installed" ) );
528   QToolTip::add  ( productsView, tr( "This view lists the products you wish to be installed" ) );
529   // products info box
530   productsInfo = new QTextBrowser( moreBox );
531   productsInfo->setMinimumSize( 270, 135 );
532   QWhatsThis::add( productsInfo, tr( "Shows info about the product: required disk space and prerequisites" ) );
533   QToolTip::add  ( productsInfo, tr( "Shows info about the product: required disk space and prerequisites" ) );
534   // disk space labels
535   QLabel* reqLab1 = new QLabel( tr( "Total disk space required:" ), moreBox );
536   QWhatsThis::add( reqLab1, tr( "Shows total disk space required for installing selected products" ) );
537   QToolTip::add  ( reqLab1, tr( "Shows total disk space required for installing selected products" ) );
538   requiredSize = new QLabel( moreBox );
539   requiredSize->setMinimumWidth( 100 );
540   QWhatsThis::add( requiredSize, tr( "Shows total disk space required for installing selected products" ) );
541   QToolTip::add  ( requiredSize, tr( "Shows total disk space required for installing selected products" ) );
542   QLabel* reqLab2 = new QLabel( tr( "Space for temporary files:" ), moreBox );
543   QWhatsThis::add( reqLab2, tr( "Shows additional disk space which is required for temporary files" ) );
544   QToolTip::add  ( reqLab2, tr( "Shows additional disk space which is required for temporary files" ) );
545   requiredTemp = new QLabel( moreBox );
546   requiredTemp->setMinimumWidth( 100 );
547   QWhatsThis::add( requiredTemp, tr( "Shows additional disk space which is required for temporary files" ) );
548   QToolTip::add  ( requiredTemp, tr( "Shows additional disk space which is required for temporary files" ) );
549   QFont fnt = reqLab1->font();
550   fnt.setBold( true );
551   reqLab1->setFont( fnt );
552   requiredSize->setFont( fnt );
553   reqLab2->setFont( fnt );
554   requiredTemp->setFont( fnt );
555   QGridLayout* sizeLayout = new QGridLayout; sizeLayout->setMargin( 0 ); sizeLayout->setSpacing( 6 );
556   sizeLayout->addWidget( reqLab1,      0, 0 );
557   sizeLayout->addWidget( requiredSize, 0, 1 );
558   sizeLayout->addWidget( reqLab2,      1, 0 );
559   sizeLayout->addWidget( requiredTemp, 1, 1 );
560   // prerequisites checkbox
561   prerequisites = new QCheckBox( tr( "Auto set prerequisites products" ), moreBox );
562   prerequisites->setChecked( true );
563   QWhatsThis::add( prerequisites, tr( "Check this if you want prerequisites products to be set on automatically" ) );
564   QToolTip::add  ( prerequisites, tr( "Check this if you want prerequisites products to be set on automatically" ) );
565   // <Unselect All> button
566   unselectBtn  = new QPushButton( tr( "&Unselect All" ), moreBox );
567   QWhatsThis::add( unselectBtn, tr( "Unselects all products" ) );
568   QToolTip::add  ( unselectBtn, tr( "Unselects all products" ) );
569   // <SALOME sources> / <SALOME binaries> tri-state checkboxes
570   selectSrcBtn  = new QMyCheckBox( tr( "SALOME sources" ), moreBox );
571   selectSrcBtn->setTristate( true );
572   QWhatsThis::add( selectSrcBtn, tr( "Selects/unselects SALOME sources" ) );
573   QToolTip::add  ( selectSrcBtn, tr( "Selects/unselects SALOME sources" ) );
574   selectBinBtn  = new QMyCheckBox( tr( "SALOME binaries" ), moreBox );
575   selectBinBtn->setTristate( true );
576   QWhatsThis::add( selectBinBtn, tr( "Selects/unselects SALOME binaries" ) );
577   QToolTip::add  ( selectBinBtn, tr( "Selects/unselects SALOME binaries" ) );
578   QVBoxLayout* btnLayout = new QVBoxLayout; btnLayout->setMargin( 0 ); btnLayout->setSpacing( 6 );
579   btnLayout->addWidget( unselectBtn );
580   btnLayout->addWidget( selectSrcBtn );
581   btnLayout->addWidget( selectBinBtn );
582   // layouting advancet mode widgets
583   moreBoxLayout->addMultiCellWidget( tempLab,      0, 0, 0, 2 );
584   moreBoxLayout->addMultiCellWidget( tempFolder,   1, 1, 0, 1 );
585   moreBoxLayout->addWidget         ( tempBtn,      1,    2    );
586   moreBoxLayout->addMultiCellWidget( productsView, 2, 5, 0, 0 );
587   moreBoxLayout->addMultiCellWidget( productsInfo, 2, 2, 1, 2 );
588   moreBoxLayout->addMultiCellWidget( prerequisites,3, 3, 1, 2 );
589   moreBoxLayout->addMultiCellLayout( btnLayout,    4, 4, 1, 2 );
590   moreBoxLayout->addMultiCellLayout( sizeLayout,   5, 5, 1, 2 );
591   // <More...> button
592   moreBtn = new QPushButton( tr( "More..." ), productsPage );
593   // layouting
594   pageLayout->addMultiCellWidget( targetLab,    0, 0, 0, 1 );
595   pageLayout->addWidget         ( targetFolder, 1,    0    );
596   pageLayout->addWidget         ( targetBtn,    1,    1    );
597   pageLayout->addMultiCellWidget( moreBox,      2, 2, 0, 1 );
598   pageLayout->addWidget         ( moreBtn,      3,    1    );
599   pageLayout->setRowStretch( 2, 5 );
600   //pageLayout->addRowSpacing( 6, 10 );
601   // xml reader
602   QFile xmlfile(xmlFileName);
603   if ( xmlfile.exists() ) {
604     QXmlInputSource source( &xmlfile );
605     QXmlSimpleReader reader;
606
607     StructureParser* handler = new StructureParser( this );
608     handler->setProductsList(productsView);
609     handler->setTargetDir(targetFolder);
610     handler->setTempDir(tempFolder);
611     reader.setContentHandler( handler );
612     reader.parse( source );  
613   }
614   // set first item to be selected
615   if ( productsView->childCount() > 0 ) {
616     productsView->setSelected( productsView->firstChild(), true );
617     onSelectionChanged();
618   }
619   // adding page
620   addPage( productsPage, tr( "Installation settings" ) );
621   // connecting signals
622   connect( productsView, SIGNAL( selectionChanged() ), 
623                                               this, SLOT( onSelectionChanged() ) );
624   connect( productsView, SIGNAL( itemToggled( QCheckListItem* ) ), 
625                                               this, SLOT( onItemToggled( QCheckListItem* ) ) );
626   connect( unselectBtn,  SIGNAL( clicked() ), this, SLOT( onProdBtn() ) );
627   connect( selectSrcBtn, SIGNAL( stateChanged(int) ), 
628                                               this, SLOT( onProdBtn() ) );
629   connect( selectBinBtn, SIGNAL( stateChanged(int) ), 
630                                               this, SLOT( onProdBtn() ) );
631   // connecting signals
632   connect( targetFolder, SIGNAL( textChanged( const QString& ) ),
633                                               this, SLOT( directoryChanged( const QString& ) ) );
634   connect( targetBtn,    SIGNAL( clicked() ), this, SLOT( browseDirectory() ) );
635   connect( tempFolder,   SIGNAL( textChanged( const QString& ) ),
636                                               this, SLOT( directoryChanged( const QString& ) ) );
637   connect( tempBtn,      SIGNAL( clicked() ), this, SLOT( browseDirectory() ) );
638   connect( moreBtn,      SIGNAL( clicked() ), this, SLOT( onMoreBtn() ) );
639   // start on default - non-advanced - mode
640   moreBox->hide();
641 }
642 // ================================================================
643 /*!
644  *  SALOME_InstallWizard::setupCheckPage
645  *  Creates prestart page
646  */
647 // ================================================================
648 void SALOME_InstallWizard::setupCheckPage()
649 {
650   // create page
651   prestartPage = new QWidget( this, "PrestartPage" );
652   QVBoxLayout* pageLayout = new QVBoxLayout( prestartPage ); 
653   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
654   // choice text view
655   choices = new QTextEdit( prestartPage );
656   choices->setReadOnly( true );
657   choices->setTextFormat( RichText );
658   choices->setUndoRedoEnabled ( false );
659   QWhatsThis::add( choices, tr( "Displays information about installation settings you made" ) );
660   QToolTip::add  ( choices, tr( "Displays information about installation settings you made" ) );
661   QPalette pal = choices->palette();
662   pal.setColor( QColorGroup::Base, QApplication::palette().active().background() );
663   choices->setPalette( pal );
664   choices->setMinimumHeight( 10 );
665   // layouting
666   pageLayout->addWidget( choices );
667   pageLayout->setStretchFactor( choices, 5 );
668   // adding page
669   addPage( prestartPage, tr( "Check your choice" ) );
670 }
671 // ================================================================
672 /*!
673  *  SALOME_InstallWizard::setupProgressPage
674  *  Creates progress page
675  */
676 // ================================================================
677 void SALOME_InstallWizard::setupProgressPage()
678 {
679   // create page
680   progressPage = new QWidget( this, "progressPage" );
681   QGridLayout* pageLayout = new QGridLayout( progressPage ); 
682   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
683   // top splitter
684   splitter = new QSplitter( Vertical, progressPage );
685   splitter->setOpaqueResize( true );
686   // the parent for the widgets
687   QWidget* widget = new QWidget( splitter );
688   QGridLayout* layout = new QGridLayout( widget ); 
689   layout->setMargin( 0 ); layout->setSpacing( 6 );
690   // installation progress view box
691   installInfo = new QTextEdit( widget );
692   installInfo->setReadOnly( true );
693   installInfo->setTextFormat( RichText );
694   installInfo->setUndoRedoEnabled ( false );
695   installInfo->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
696   installInfo->setMinimumSize( 100, 10 );
697   QWhatsThis::add( installInfo, tr( "Displays installation process" ) );
698   QToolTip::add  ( installInfo, tr( "Displays installation process" ) );
699   // parameters for the script
700   parametersLab = new QLabel( tr( "Enter your answer here:" ), widget );
701   passedParams = new QLineEdit ( widget );
702   QWhatsThis::add( passedParams, tr( "Use this field to enter answer for the running script when it is necessary") );
703   QToolTip::add  ( passedParams, tr( "Use this field to enter answer for the running script when it is necessary") );
704   // VSR: 10/11/05 - disable answer mode ==>
705   parametersLab->hide();
706   passedParams->hide();
707   // VSR: 10/11/05 - disable answer mode <==
708   // layouting
709   layout->addWidget( installInfo,   0, 0 );
710   layout->addWidget( parametersLab, 1, 0 );
711   layout->addWidget( passedParams,  2, 0 );
712   layout->addRowSpacing( 3, 6 );
713   // the parent for the widgets
714   widget = new QWidget( splitter );
715   layout = new QGridLayout( widget ); 
716   layout->setMargin( 0 ); layout->setSpacing( 6 );
717   // installation results view box
718   QLabel* resultLab = new QLabel( tr( "Installation Status:" ), widget );
719   progressView = new ProgressView( widget );
720   progressView->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
721   progressView->setMinimumSize( 100, 10 );
722   QWhatsThis::add( progressView, tr( "Displays installation status" ) );
723   QToolTip::add  ( progressView, tr( "Displays installation status" ) );
724   // layouting
725   layout->addRowSpacing( 0, 6 );
726   layout->addWidget( resultLab,    1, 0 );
727   layout->addWidget( progressView, 2, 0 );
728   // layouting
729   pageLayout->addWidget( splitter, 0, 0 );
730   // adding page
731   addPage( progressPage, tr( "Installation progress" ) );
732   // connect signals
733   connect( passedParams, SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) ) ;
734 }
735 // ================================================================
736 /*!
737  *  SALOME_InstallWizard::setupReadmePage
738  *  Creates readme page
739  */
740 // ================================================================
741 void SALOME_InstallWizard::setupReadmePage()
742 {
743   // create page
744   readmePage = new QWidget( this, "ReadmePage" );
745   QVBoxLayout* pageLayout = new QVBoxLayout( readmePage ); 
746   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
747   // README info text box
748   readme = new QTextEdit( readmePage );
749   readme->setReadOnly( true );
750   readme->setTextFormat( PlainText );
751   readme->setFont( QFont( "Fixed", 10 ) );
752   readme->setUndoRedoEnabled ( false );
753   QWhatsThis::add( readme, tr( "Displays README information" ) );
754   QToolTip::add  ( readme, tr( "Displays README information" ) );
755   QPalette pal = readme->palette();
756   pal.setColor( QColorGroup::Base, QApplication::palette().active().background() );
757   readme->setPalette( pal );
758   readme->setMinimumHeight( 10 );
759   // <Launch SALOME> button
760   runSalomeBtn = new QPushButton( tr( "Launch SALOME" ), readmePage );
761   QWhatsThis::add( runSalomeBtn, tr( "Click this button to run SALOME desktop" ) );
762   QToolTip::add  ( runSalomeBtn, tr( "Click this button to run SALOME desktop" ) );
763   QHBoxLayout* hLayout = new QHBoxLayout;
764   hLayout->addWidget( runSalomeBtn ); hLayout->addStretch();
765   // layouting
766   pageLayout->addWidget( readme );
767   pageLayout->setStretchFactor( readme, 5 );
768   pageLayout->addLayout( hLayout );
769   // connecting signals
770   connect( runSalomeBtn, SIGNAL( clicked() ), this, SLOT( onLaunchSalome() ) );
771   // loading README file
772   QString readmeFile = QDir::currentDirPath() + "/README";
773   QString text;
774   if ( readFile( readmeFile, text ) )
775     readme->setText( text );
776   else
777     readme->setText( tr( "README file has not been found" ) );
778   // adding page
779   addPage( readmePage, tr( "Finish installation" ) );
780 }
781 // ================================================================
782 /*!
783  *  SALOME_InstallWizard::showChoiceInfo
784  *  Displays choice info
785  */
786 // ================================================================
787 void SALOME_InstallWizard::showChoiceInfo()
788 {
789   choices->clear();
790
791   long totSize, tempSize;
792   checkSize( &totSize, &tempSize );
793   int nbProd = 0;
794   QString text;
795
796   if ( !xmlFileName.isEmpty() ) {
797     text += tr( "Configuration file" )+ ": <b>" + xmlFileName + "</b><br>";
798     text += "<br>";
799   }
800   if ( !myOS.isEmpty() ) {
801     text += tr( "Target platform" ) + ": <b>" + myOS + "</b><br>";
802     text += "<br>";
803   }
804   text += tr( "Products to be used" ) + ":<ul>";
805   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
806   while( item ) {
807     if ( productsMap.contains( item ) ) {
808       if ( item->childCount() > 0 ) {
809         if ( productsView->isNative( item ) ) {
810           text += "<li><b>" + item->text() + "</b> " + tr( "as native" ) + "<br>";
811           nbProd++;
812         }
813       }
814     }
815     item = (QCheckListItem*)( item->nextSibling() );
816   }
817   if ( nbProd == 0 ) {
818     text += "<li><b>" + tr( "none" ) + "</b><br>";
819   }
820   text += "</ul>";
821   nbProd = 0;
822   text += tr( "Products to be installed" ) + ":<ul>";
823   item = (QCheckListItem*)( productsView->firstChild() );
824   while( item ) {
825     if ( productsMap.contains( item ) ) {
826       if ( item->childCount() > 0 ) {
827         if ( productsView->isBinaries( item ) ) {
828           text += "<li><b>" + item->text() + "</b> " + tr( "as binaries" ) + "<br>";
829           nbProd++;
830         }
831         else if ( productsView->isSources( item ) ) {
832           text+= "<li><b>" + item->text() + "</b> " + tr( "as sources" ) + "<br>";
833           nbProd++;
834         }
835       }
836       else if ( item->isOn() ) {
837         text+= "<li><b>" + item->text() + "</b><br>";
838         nbProd++;
839       }
840     }
841     item = (QCheckListItem*)( item->nextSibling() );
842   }
843   if ( nbProd == 0 ) {
844     text += "<li><b>" + tr( "none" ) + "</b><br>";
845   }
846   text += "</ul>";
847   text += tr( "Total disk space required:" ) + " <b>" + QString::number( totSize ) + " Kb</b><br>" ;
848   text += tr( "Space for temporary files required:" ) + " <b>" + QString::number( tempSize ) + " Kb</b><br>" ;
849   text += "<br>";
850   text += tr( "Target directory:" ) + " <b>" + QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) + "</b><br>";
851   // VSR: Temporary folder is used always now and it is not necessary to disable it -->
852   // if ( tempSize > 0 )
853   // VSR: <----------------------------------------------------------------------------
854   text += tr( "Temp directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
855   text += "<br>";
856   choices->setText( text );
857 }
858 // ================================================================
859 /*!
860  *  SALOME_InstallWizard::acceptData
861  *  Validates page when <Next> button is clicked
862  */
863 // ================================================================
864 bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
865 {
866   QString tmpstr;
867   QWidget* aPage = InstallWizard::page( pageTitle );
868   if ( aPage == productsPage ) {
869     // ########## check if any products are selected to be installed
870     long totSize, tempSize;
871     bool anySelected = checkSize( &totSize, &tempSize );
872     if ( !anySelected ) {
873       QMessageBox::warning( this, 
874                             tr( "Warning" ), 
875                             tr( "Select one or more products to install" ), 
876                             QMessageBox::Ok, 
877                             QMessageBox::NoButton,
878                             QMessageBox::NoButton );
879       return false;
880     }
881     // ########## check target and temp directories (existence and available disk space)
882     // get dirs
883     QString targetDir = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
884     QString tempDir   = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() );
885     // directories should differ
886 //    if (!targetDir.isEmpty() && tempDir == targetDir) {
887 //      QMessageBox::warning( this, 
888 //                          tr( "Warning" ), 
889 //                          tr( "Target and temporary directories must be different"), 
890 //                          QMessageBox::Ok, 
891 //                          QMessageBox::NoButton, 
892 //                          QMessageBox::NoButton );
893 //      return false;
894 //    }
895     // check target directory
896     if ( targetDir.isEmpty() ) {
897       QMessageBox::warning( this, 
898                             tr( "Warning" ), 
899                             tr( "Please, enter valid target directory path" ), 
900                             QMessageBox::Ok, 
901                             QMessageBox::NoButton,
902                             QMessageBox::NoButton );
903       return false;
904     }
905     QFileInfo fi( QDir::cleanDirPath( targetDir ) );
906     if ( !fi.exists() ) {
907       bool toCreate = 
908         QMessageBox::warning( this, 
909                               tr( "Warning" ), 
910                               tr( "The directory %1 doesn't exist.\n"
911                                   "Do you want to create directory?" ).arg( fi.absFilePath() ), 
912                               QMessageBox::Yes, 
913                               QMessageBox::No,
914                               QMessageBox::NoButton ) == QMessageBox::Yes;
915       if ( !toCreate) 
916         return false;
917       if ( !makeDir( fi.absFilePath(), tmpstr ) ) {
918         QMessageBox::critical( this, 
919                                tr( "Error" ), 
920                                tr( "Can't create the directory\n%1").arg( fi.absFilePath() ), 
921                                QMessageBox::Ok, 
922                                QMessageBox::NoButton, 
923                                QMessageBox::NoButton );
924         return false;
925       }
926     }
927     if ( !fi.isDir() ) {
928       QMessageBox::warning( this, 
929                             tr( "Warning" ), 
930                             tr( "The directory %1 is not a directory.\n"
931                                 "Please, enter valid target directory path" ).arg( fi.absFilePath() ), 
932                             QMessageBox::Ok, 
933                             QMessageBox::NoButton,
934                             QMessageBox::NoButton );
935       return false;
936     }
937     if ( !fi.isWritable() ) {
938       QMessageBox::warning( this, 
939                             tr( "Warning" ), 
940                             tr( "The directory %1 is not writeable.\n"
941                                 "Please, enter valid target directory path or change permissions" ).arg( fi.absFilePath() ), 
942                             QMessageBox::Ok, 
943                             QMessageBox::NoButton,
944                             QMessageBox::NoButton );
945       return false;
946     }
947     if ( hasSpace( fi.absFilePath() ) &&
948          QMessageBox::warning( this,
949                                tr( "Warning" ),
950                                tr( "The target directory contains space symbols.\n"
951                                    "This may cause problems with compiling or installing of products.\n\n"
952                                    "Do you want to continue?"),
953                                QMessageBox::Yes,
954                                QMessageBox::No,
955                                QMessageBox::NoButton ) == QMessageBox::No ) {
956       return false;
957     }
958     QString binDir = "./Products/BINARIES";
959     if ( !myOS.isEmpty() )
960       binDir += "/" + myOS;
961     QFileInfo fib( QDir::cleanDirPath( binDir ) );
962     if ( !fib.exists() ) {
963       QMessageBox::warning( this, 
964                             tr( "Warning" ), 
965                             tr( "The directory %1 doesn't exist.\n"
966                                 "This directory must contain binaries archives." ).arg( fib.absFilePath() ));
967     }
968     // run script that checks available disk space for installing of products    // returns 1 in case of error
969     QString script = "./config_files/checkSize.sh '";
970     script += fi.absFilePath();
971     script += "' ";
972     script += QString( "%1" ).arg( totSize );
973     ___MESSAGE___( "script = " << script );
974     if ( system( script ) ) {
975       QMessageBox::critical( this, 
976                              tr( "Out of space" ), 
977                              tr( "There is not available disk space for installing of selected products" ), 
978                              QMessageBox::Ok, 
979                              QMessageBox::NoButton, 
980                              QMessageBox::NoButton );
981       return false;
982     }
983     // check temp directory
984     if ( tempDir.isEmpty() ) {
985       if ( moreMode ) {
986         QMessageBox::warning( this, 
987                               tr( "Warning" ), 
988                               tr( "Please, enter valid temp directory path" ), 
989                               QMessageBox::Ok, 
990                               QMessageBox::NoButton,
991                               QMessageBox::NoButton );
992         return false; 
993       }
994       else {
995         tempDir = "/tmp";
996         tempFolder->setText( tempDir );
997       }
998     }
999     QFileInfo fit( QDir::cleanDirPath( tempDir ) );
1000     if ( !makeDir( fit.absFilePath() + TEMPDIRNAME, tmpCreated ) ) {
1001       QMessageBox::critical( this, 
1002                              tr( "Error" ), 
1003                              tr( "Can't use temporary directory.\nCheck permissions for the %1 directory.").arg( fit.absFilePath() ), 
1004                              QMessageBox::Ok, 
1005                              QMessageBox::NoButton, 
1006                              QMessageBox::NoButton );
1007       return false;
1008     }
1009     // run script that check available disk space for temporary files
1010     // returns 1 in case of error
1011     QString tscript = "./config_files/checkSize.sh '";
1012     tscript += fit.absFilePath();
1013     tscript += "' ";
1014     tscript += QString( "%1" ).arg( tempSize );
1015     ___MESSAGE___( "script = " << tscript );
1016     if ( system( tscript ) ) {
1017       QMessageBox::critical( this, 
1018                              tr( "Out of space" ), 
1019                              tr( "There is not available disk space for the temporary files" ), 
1020                              QMessageBox::Ok, 
1021                              QMessageBox::NoButton, 
1022                              QMessageBox::NoButton );
1023       return false;
1024     }
1025 // VSR: <------------------------------------------------------------------------------
1026     // ########## check native products
1027     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1028     QStringList natives;
1029     while( item ) {
1030       if ( productsMap.contains( item ) ) {
1031         if ( item->childCount() > 0 ) {
1032           if ( !productsView->isNone( item ) ) {
1033             if ( item->text(2).isEmpty() || item->text(2).isNull() ) {
1034               QMessageBox::warning( this, 
1035                                     tr( "Error" ), 
1036                                     tr( "You don't have a defined script for %1").arg(item->text(0)), 
1037                                     QMessageBox::Ok, 
1038                                     QMessageBox::NoButton, 
1039                                     QMessageBox::NoButton );
1040               if ( !moreMode )
1041                 onMoreBtn();
1042               productsView->setCurrentItem( item );
1043               productsView->setSelected( item, true );
1044               productsView->ensureItemVisible( item );
1045               //productsView->setNone( item );
1046               return false;
1047             } else {
1048               QFileInfo fi( QString("./config_files/") + item->text(2) );
1049               if ( !fi.exists() ) {
1050                 QMessageBox::warning( this, 
1051                                       tr( "Error" ),  
1052                                       tr( "%1 required for %2 doesn't exist.").arg("./config_files/" + item->text(2)).arg(item->text(0)),  
1053                                       QMessageBox::Ok, 
1054                                       QMessageBox::NoButton, 
1055                                       QMessageBox::NoButton );
1056                 if ( !moreMode )
1057                   onMoreBtn();
1058                 productsView->setCurrentItem( item );
1059                 productsView->setSelected( item, true );
1060                 productsView->ensureItemVisible( item );
1061                 //productsView->setNone( item );
1062                 return false;
1063               }       
1064             }
1065           }
1066           // collect native products
1067           if ( productsView->isNative( item ) ) {
1068             if ( natives.find( item->text(0) ) == natives.end() )
1069               natives.append( item->text(0) );
1070           } 
1071           else if ( productsView->isBinaries( item ) || productsView->isSources( item ) ) {
1072             QStringList dependOn = productsMap[ item ].getDependancies();
1073             for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1074               QCheckListItem* depitem = findItem( dependOn[ i ] );
1075               if ( depitem ) {
1076                 if ( productsView->isNative( depitem ) && natives.find( depitem->text(0) ) == natives.end() )
1077                   natives.append( depitem->text(0) );
1078               } 
1079               else {
1080                 QMessageBox::warning( this, 
1081                                       tr( "Warning" ), 
1082                                       tr( "%1 is required for %2 %3 installation.\n"
1083                                           "Please, add this product in config.xml file.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)), 
1084                                       QMessageBox::Ok, 
1085                                       QMessageBox::NoButton, 
1086                                       QMessageBox::NoButton );
1087                 return false;
1088               }
1089             }
1090           }
1091         }
1092       }
1093       item = (QCheckListItem*)( item->nextSibling() );
1094     }
1095     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1096     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1097     myThread->clearCommands();
1098     if ( natives.count() > 0 ) {
1099       for ( unsigned i = 0; i < natives.count(); i++ ) {
1100         item = findItem( natives[ i ] );
1101         if ( item ) {
1102           QString dependOn = productsMap[ item ].getDependancies().join(" ");
1103           QString script = "cd ./config_files/;" + item->text(2) + " try_native " +
1104                   QFileInfo( tmpFolder ).absFilePath() + " " + QDir::currentDirPath() + "/Products " + QFileInfo( tgtFolder ).absFilePath() + " " +
1105                   QUOTE(dependOn) + " " + item->text(0);
1106
1107           myThread->addCommand( item, script );
1108         }
1109         else {
1110           QMessageBox::warning( this, 
1111                                 tr( "Warning" ), 
1112                                 tr( "%The product %1 %2 required for installation.\n"
1113                                     "Please, add this product in config.xml file.").arg(item->text(0)).arg(item->text(1)),
1114                                 QMessageBox::Ok, 
1115                                 QMessageBox::NoButton, 
1116                                 QMessageBox::NoButton );
1117           return false;
1118         }
1119       }
1120       WarnDialog::showWarnDlg( this, true );
1121       myThread->start();
1122       return true; // return in order to avoid default postValidateEvent() action
1123     }
1124   }
1125   return InstallWizard::acceptData( pageTitle );
1126 }
1127 // ================================================================
1128 /*!
1129  *  SALOME_InstallWizard::checkSize
1130  *  Calculates disk space required for the installation
1131  */
1132 // ================================================================
1133 bool SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
1134 {
1135   long tots = 0, temps = 0;
1136   int nbSelected = 0;
1137
1138   MapProducts::Iterator mapIter;
1139   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1140     QCheckListItem* item = mapIter.key();
1141     Dependancies dep = mapIter.data();
1142     if ( productsView->isBinaries( item ) ) {
1143       tots += dep.getSize();
1144     }
1145     else if ( productsView->isSources( item ) ) {
1146       tots += dep.getSize(true);
1147       temps = max( temps, dep.getTempSize() );
1148     }
1149     if ( !productsView->isNone( item ) )
1150       nbSelected++;
1151   }
1152  
1153   if ( totSize )
1154     *totSize = tots;
1155   if ( tempSize )
1156     *tempSize = temps;
1157   return ( nbSelected > 0 );
1158 }
1159 // ================================================================
1160 /*!
1161  *  SALOME_InstallWizard::checkProductPage
1162  *  Checks products page validity (directories and products selection) and
1163  *  enabled/disables "Next" button for the Products page
1164  */
1165 // ================================================================
1166 void SALOME_InstallWizard::checkProductPage()
1167 {
1168   long tots = 0, temps = 0;
1169
1170   // check if any product is selected;
1171   bool isAnyProductSelected = checkSize( &tots, &temps );
1172   // check if target directory is valid
1173   bool isTargetDirValid = !targetFolder->text().stripWhiteSpace().isEmpty();
1174   // check if temp directory is valid
1175   bool isTempDirValid = !moreMode || !tempFolder->text().stripWhiteSpace().isEmpty();
1176
1177   // update required size information
1178   requiredSize->setText( QString::number( tots )  + " Kb");
1179   requiredTemp->setText( QString::number( temps ) + " Kb");
1180   
1181   // update <SALOME sources>, <SALOME binaries> check boxes state
1182   int totSrc = 0, selSrc = 0;
1183   int totBin = 0, selBin = 0;
1184   MapProducts::Iterator itProd;
1185   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1186     if ( itProd.data().getContext() == "salome sources" ) {
1187       totSrc++;
1188       if ( productsView->isSources( itProd.key() ) )
1189         selSrc++;
1190     }
1191     if ( itProd.data().getContext() == "salome binaries" ) {
1192       totBin++;
1193       if ( productsView->isBinaries( itProd.key() ) )
1194         selBin++;
1195     }
1196   }
1197   selectSrcBtn->blockSignals( true );
1198   selectBinBtn->blockSignals( true );
1199   selectSrcBtn->setState( selSrc == 0 ? QButton::Off : ( selSrc == totSrc ? QButton::On : QButton::NoChange  ) );
1200   selectBinBtn->setState( selBin == 0 ? QButton::Off : ( selBin == totBin ? QButton::On : QButton::NoChange  ) );
1201   selectSrcBtn->blockSignals( false );
1202   selectBinBtn->blockSignals( false );
1203
1204   // enable/disable "Next" button
1205   setNextEnabled( productsPage, isAnyProductSelected && isTargetDirValid && isTempDirValid );
1206 }
1207 // ================================================================
1208 /*!
1209  *  SALOME_InstallWizard::setPrerequisites
1210  *  Sets the product and all products this one depends on to be checked ( recursively )
1211  */
1212 // ================================================================
1213 void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
1214 {
1215   if ( !productsMap.contains( item ) )
1216     return;
1217   if ( productsView->isNone( item ) )
1218     return;
1219   // get all prerequisites
1220   QStringList dependOn = productsMap[ item ].getDependancies();
1221   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1222     MapProducts::Iterator itProd;
1223     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1224       if ( itProd.data().getName() == dependOn[ i ] ) {
1225         if ( productsView->isNone( itProd.key() ) ) {
1226           QString defMode = itProd.data().getDefault();
1227           if ( defMode.isEmpty() )
1228             defMode = tr( "install binaries" );
1229           if ( defMode == tr( "install binaries" ) )
1230             productsView->setBinaries( itProd.key() );
1231           else if ( defMode == tr( "install sources" ) )
1232             productsView->setSources( itProd.key() );
1233           else if ( defMode == tr( "use native" ) )
1234             productsView->setNative( itProd.key() );
1235           setPrerequisites( itProd.key() );
1236         }
1237       }
1238     }
1239   }
1240 }
1241 // ================================================================
1242 /*!
1243  *  SALOME_InstallWizard::launchScript
1244  *  Runs installation script
1245  */
1246 // ================================================================
1247 void SALOME_InstallWizard::launchScript()
1248 {
1249   // try to find product being processed now
1250   QString prodProc = progressView->findStatus( Processing );
1251   if ( !prodProc.isNull() ) {
1252     ___MESSAGE___( "Found <Processing>: " );
1253
1254     // if found - set status to "completed"
1255     progressView->setStatus( prodProc, Completed );
1256     // ... and call this method again
1257     launchScript();
1258     return;
1259   }
1260   // else try to find next product which is not processed yet
1261   prodProc = progressView->findStatus( Waiting );
1262   if ( !prodProc.isNull() ) {
1263     ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
1264     // if found - set status to "processed" and run script
1265     progressView->setStatus( prodProc, Processing );
1266     progressView->ensureVisible( prodProc );
1267
1268     QCheckListItem* item = findItem( prodProc );
1269     // fill in script parameters
1270     shellProcess->clearArguments();
1271     // ... script name
1272     shellProcess->setWorkingDirectory( QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() ) );
1273     shellProcess->addArgument( item->text(2) );
1274
1275     // ... temp folder
1276     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1277     //if( !tempFolder->isEnabled() )
1278     //tmpFolder = "/tmp";
1279
1280     // ... binaries ?
1281     if ( productsView->isBinaries( item ) ) {
1282       shellProcess->addArgument( "install_binary" );
1283       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1284       QString binDir = QDir::currentDirPath() + "/Products/BINARIES";
1285       if ( !myOS.isEmpty() )
1286         binDir += "/" + myOS;
1287       shellProcess->addArgument( binDir );
1288     }
1289     // ... sources ?
1290     else if ( productsView->isSources( item ) ) {
1291       shellProcess->addArgument( "install_source" );
1292       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1293       shellProcess->addArgument( QDir::currentDirPath() + "/Products/SOURCES" );
1294     }
1295     // ... native ?
1296     else if ( productsView->isNative( item ) ) {
1297       shellProcess->addArgument( "try_native" );
1298       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1299       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1300     }
1301     // ... not install : try to find preinstalled
1302     else {
1303       shellProcess->addArgument( "try_preinstalled" );
1304       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1305       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1306     }
1307     // ... target folder
1308     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1309     shellProcess->addArgument( QFileInfo( tgtFolder ).absFilePath() );
1310     
1311
1312     QString depproducts = DefineDependeces(productsMap); 
1313     ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
1314
1315     shellProcess->addArgument( depproducts );
1316     // ... product name - currently instaled product
1317     shellProcess->addArgument( item->text(0) );
1318
1319     // run script
1320     if ( !shellProcess->start() ) {
1321       // error handling can be here
1322       ___MESSAGE___( "error" );
1323     }
1324     return;
1325   }
1326   ___MESSAGE___( "All products have been installed successfully" );
1327   // all products are installed successfully
1328   QString workDir = QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() );
1329   MapProducts::Iterator mapIter;
1330   ___MESSAGE___( "starting pick-up environment" );
1331   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1332     QCheckListItem* item = mapIter.key();
1333     Dependancies dep = mapIter.data();
1334     QString depproducts = QUOTE( DefineDependeces(productsMap) ); 
1335     if ( dep.pickUpEnvironment() ) {
1336       ___MESSAGE___( "... for " << dep.getName() );
1337       QString script;
1338       script += "cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
1339       script += item->text(2) + " ";
1340       script += "pickup_env ";
1341       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
1342       script += QUOTE( QFileInfo( QDir::cleanDirPath( QDir::currentDirPath() + "/Products" ) ).absFilePath() ) + " ";
1343       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
1344       script += depproducts + " ";
1345       script += item->text(0);
1346       ___MESSAGE___( "... --> " << script.latin1() );
1347       if ( system( script.latin1() ) ) { 
1348         ___MESSAGE___( "ERROR" ); 
1349       }
1350     }
1351   }
1352   // <Next> button
1353   setNextEnabled( true );
1354   nextButton()->setText( tr( "&Next >" ) );
1355   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1356   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1357   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1358   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1359   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1360   // <Back> button
1361   setBackEnabled( true );
1362   // script parameters
1363   passedParams->clear();
1364   passedParams->setEnabled( false );
1365   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1366   if ( isMinimized() )
1367     showNormal();
1368   raise();
1369 }
1370 // ================================================================
1371 /*!
1372  *  SALOME_InstallWizard::onMoreBtn
1373  *  <More...> button slot
1374  */
1375 // ================================================================
1376 void SALOME_InstallWizard::onMoreBtn()
1377 {
1378   if ( moreMode ) {
1379     moreBox->hide();
1380     moreBtn->setText( tr( "More..." ) );
1381   }
1382   else {
1383     moreBox->show();
1384     moreBtn->setText( tr( "Less..." ) );
1385   }
1386   qApp->processEvents();
1387   moreMode = !moreMode;
1388   InstallWizard::layOut();
1389   qApp->processEvents();
1390   if ( !isMaximized() ) {
1391     //setGeometry( geometry().x(), geometry().y(), geometry().width(), 0 );
1392     resize( geometry().width(), 0 );
1393     qApp->processEvents();
1394   }
1395   checkProductPage();
1396 }
1397 // ================================================================
1398 /*!
1399  *  SALOME_InstallWizard::onLaunchSalome
1400  *  <Launch Salome> button slot
1401  */
1402 // ================================================================
1403 void SALOME_InstallWizard::onLaunchSalome()
1404 {
1405   QString msg = tr( "You don't have SALOME binaries installed in the %1 directory!" ).arg( targetFolder->text() );
1406
1407   QCheckListItem* item = findItem( "KERNEL-Bin" );
1408   if ( item ) {
1409     QFileInfo fi( targetFolder->text() + "/KERNEL_" + item->text(1) + "/bin/salome/runSalome" );
1410     QFileInfo fienv( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.csh" );
1411     if ( fienv.exists() ) {
1412       if ( fi.exists() ) {
1413         QString script;
1414         script += "cd " + targetFolder->text() + "/KERNEL_" + item->text(1) + "; ";
1415         script += "source salome.csh; ";
1416         script += "cd bin/salome; ";
1417         script += "runSalome > /dev/null";
1418         script = "(csh -c '" + script + "')";
1419         ___MESSAGE___( "script: " << script.latin1() );
1420         if ( !system( script.latin1() ) )
1421           return;
1422         else
1423           msg = tr( "Can't launch SALOME." );
1424       }
1425       else
1426         msg = tr( "Can't launch SALOME." ) + "\n" + tr( "runSalome file can not be found." );
1427     }
1428     else
1429       msg = tr( "Can't launch SALOME." ) + "\n" + tr( "Can't find environment file." );
1430   }
1431   QMessageBox::warning( this, 
1432                         tr( "Error" ), 
1433                         msg,
1434                         QMessageBox::Ok, 
1435                         QMessageBox::NoButton,
1436                         QMessageBox::NoButton );
1437 }
1438 // ================================================================
1439 /*!
1440  *  SALOME_InstallWizard::findItem
1441  *  Searches product listview item with given symbolic name 
1442  */
1443 // ================================================================
1444 QCheckListItem* SALOME_InstallWizard::findItem( const QString& sName )
1445 {
1446   MapProducts::Iterator mapIter;
1447   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1448     if ( mapIter.data().getName() == sName )
1449       return mapIter.key();
1450   }
1451   return 0;
1452 }
1453 // ================================================================
1454 /*!
1455  *  SALOME_InstallWizard::abort
1456  *  Sets progress state to Aborted
1457  */
1458 // ================================================================
1459 void SALOME_InstallWizard::abort()
1460 {
1461   QString prod = progressView->findStatus( Processing );
1462   while ( !prod.isNull() ) {
1463     progressView->setStatus( prod, Aborted );
1464     prod = progressView->findStatus( Processing );
1465   }
1466   prod = progressView->findStatus( Waiting );
1467   while ( !prod.isNull() ) {
1468     progressView->setStatus( prod, Aborted );
1469     prod = progressView->findStatus( Waiting );
1470   }
1471 }
1472 // ================================================================
1473 /*!
1474  *  SALOME_InstallWizard::reject
1475  *  Reject slot, clears temporary directory and closes application
1476  */
1477 // ================================================================
1478 void SALOME_InstallWizard::reject()
1479 {
1480   ___MESSAGE___( "REJECTED" );
1481   if ( !exitConfirmed ) {
1482     if ( QMessageBox::information( this, 
1483                                    tr( "Exit" ), 
1484                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
1485                                    tr( "&Yes" ), 
1486                                    tr( "&No" ),
1487                                    QString::null,
1488                                    0,
1489                                    1 ) == 1 ) {
1490       return;
1491     }
1492     exitConfirmed = true;
1493   }
1494   clean(true);
1495   InstallWizard::reject();
1496 }
1497 // ================================================================
1498 /*!
1499  *  SALOME_InstallWizard::accept
1500  *  Accept slot, clears temporary directory and closes application
1501  */
1502 // ================================================================
1503 void SALOME_InstallWizard::accept()
1504 {
1505   ___MESSAGE___( "ACCEPTED" );
1506   clean(true);
1507   InstallWizard::accept();
1508 }
1509 // ================================================================
1510 /*!
1511  *  SALOME_InstallWizard::clean
1512  *  Clears and (optionally) removes temporary directory
1513  */
1514 // ================================================================
1515 void SALOME_InstallWizard::clean(bool rmDir)
1516 {
1517   WarnDialog::showWarnDlg( 0, false );
1518   myThread->clearCommands();
1519   myWC.wakeAll();
1520   while ( myThread->running() );
1521   // VSR: first remove temporary files
1522   QString script = "cd ./config_files/; remove_tmp.sh '";
1523   script += tempFolder->text().stripWhiteSpace() + TEMPDIRNAME;
1524   script += "' ";
1525   script += QUOTE(DefineDependeces(productsMap));
1526   script += " > /dev/null";
1527   ___MESSAGE___( "script = " << script );
1528   if ( system( script.latin1() ) ) {
1529   }
1530   // VSR: then try to remove created temporary directory
1531   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1532   if ( rmDir && !tmpCreated.isNull() ) {
1533     script = "rm -rf " + tmpCreated;
1534     script += " > /dev/null";
1535     if ( system( script.latin1() ) ) {
1536     }
1537     ___MESSAGE___( "script = " << script );
1538   }
1539 }
1540 // ================================================================
1541 /*!
1542  *  SALOME_InstallWizard::pageChanged
1543  *  Called when user moves from page to page
1544  */
1545 // ================================================================
1546 void SALOME_InstallWizard::pageChanged( const QString & mytitle)
1547 {
1548   nextButton()->setText( tr( "&Next >" ) );
1549   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1550   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1551   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1552   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1553   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1554   cancelButton()->disconnect();
1555   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
1556
1557   QWidget* aPage = InstallWizard::page( mytitle );
1558   if ( !aPage )
1559     return;
1560   updateCaption();
1561   if ( aPage == productsPage ) {
1562     // products page
1563     onSelectionChanged();
1564     checkProductPage();
1565   }
1566   else if ( aPage == prestartPage ) {
1567     // prestart page
1568     showChoiceInfo();
1569   }
1570   else if ( aPage == progressPage ) {
1571     if ( previousPage == prestartPage ) {
1572       // progress page
1573       progressView->clear();
1574       installInfo->clear();
1575       passedParams->clear();
1576       passedParams->setEnabled( false );
1577       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1578       nextButton()->setText( tr( "&Start" ) );
1579       QWhatsThis::add( nextButton(), tr( "Starts installation process" ) );
1580       QToolTip::add  ( nextButton(), tr( "Starts installation process" ) );
1581       // reconnect Next button - to use it as Start button
1582       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1583       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1584       connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1585       setNextEnabled( true );
1586       // reconnect Cancel button to terminate process
1587       cancelButton()->disconnect();
1588       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
1589     }
1590   }
1591   else if ( aPage == readmePage ) {
1592     QCheckListItem* item = findItem( "KERNEL-Bin" );
1593     runSalomeBtn->setEnabled( item &&
1594                               QFileInfo( targetFolder->text() + "/KERNEL_" + item->text(1) + "/bin/salome/runSalome" ).exists() &&
1595                               QFileInfo( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.csh" ).exists() );
1596     finishButton()->setEnabled( true );
1597   }
1598   previousPage = aPage;
1599   ___MESSAGE___( "previousPage = " << previousPage );
1600 }
1601 // ================================================================
1602 /*!
1603  *  SALOME_InstallWizard::helpClicked
1604  *  Shows help window
1605  */
1606 // ================================================================
1607 void SALOME_InstallWizard::helpClicked()
1608 {
1609   if ( helpWindow == NULL ) {
1610     helpWindow = HelpWindow::openHelp( this );
1611     if ( helpWindow ) {
1612       helpWindow->show();
1613       helpWindow->installEventFilter( this );
1614     }
1615     else {
1616       QMessageBox::warning( this, 
1617                             tr( "Help file not found" ), 
1618                             tr( "Sorry, help is unavailable" ) );
1619     }
1620   }
1621   else {
1622     helpWindow->raise();
1623     helpWindow->setActiveWindow();
1624   }
1625 }
1626 // ================================================================
1627 /*!
1628  *  SALOME_InstallWizard::browseDirectory
1629  *  Shows directory selection dialog
1630  */
1631 // ================================================================
1632 void SALOME_InstallWizard::browseDirectory()
1633 {
1634   const QObject* theSender = sender();
1635   QLineEdit* theFolder;
1636   if ( theSender == targetBtn )
1637     theFolder = targetFolder;
1638   else if (theSender == tempBtn)
1639     theFolder = tempFolder;
1640   else
1641     return;
1642   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
1643   if ( !typedDir.isNull() ) {
1644     theFolder->setText( typedDir );
1645     theFolder->end( false );
1646   }
1647   checkProductPage();
1648 }
1649 // ================================================================
1650 /*!
1651  *  SALOME_InstallWizard::directoryChanged
1652  *  Called when directory path (target or temp) is changed
1653  */
1654 // ================================================================
1655 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
1656 {
1657   checkProductPage();
1658 }
1659 // ================================================================
1660 /*!
1661  *  SALOME_InstallWizard::onStart
1662  *  <Start> button's slot - runs installation
1663  */
1664 // ================================================================
1665 void SALOME_InstallWizard::onStart()
1666 {
1667   // clear list of products to install ...
1668   toInstall.clear();
1669   // ... and fill it for new process
1670   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1671   while( item ) {
1672 //    if ( productsView->isBinaries( item ) || productsView->isSources( item ) || productsView->isNative( item ) ) {
1673       if ( productsMap.contains( item ) )
1674         toInstall.append( productsMap[item].getName() );
1675 //    }
1676     item = (QCheckListItem*)( item->nextSibling() );
1677   }
1678   // if something at all is selected
1679   if ( !toInstall.isEmpty() ) {
1680     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
1681     // disable <Next> button
1682     setNextEnabled( false );
1683     // disable <Back> button
1684     setBackEnabled( false );
1685     // enable script parameters line edit
1686     // VSR commented: 18/09/03: passedParams->setEnabled( true );
1687     // VSR commented: 18/09/03: passedParams->setFocus();
1688     // set status for all products
1689     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
1690       item = findItem( toInstall[ i ] );
1691       QString type = "";
1692       if ( productsView->isBinaries( item ) )
1693         type = tr( "binaries" );
1694       else if ( productsView->isSources( item ) )
1695         type = tr( "sources" );
1696       else if ( productsView->isNative( item ) )
1697         type = tr( "native" );
1698       else 
1699         type = tr( "not install" );
1700       progressView->addProduct( item->text(0), type, item->text(2) );
1701     }
1702     // launch install script
1703     launchScript();
1704   }
1705 }
1706 // ================================================================
1707 /*!
1708  *  SALOME_InstallWizard::onReturnPressed
1709  *  Called when users tries to pass parameters for the script
1710  */
1711 // ================================================================
1712 void SALOME_InstallWizard::onReturnPressed()
1713 {
1714   QString txt = passedParams->text();
1715   installInfo->append( txt );
1716   txt += "\n";
1717   shellProcess->writeToStdin( txt );
1718   passedParams->clear();
1719   progressView->setFocus();
1720   passedParams->setEnabled( false );
1721   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1722 }
1723 /*!
1724   Callback function - as response for the script finishing
1725 */
1726 void SALOME_InstallWizard::productInstalled( )
1727 {
1728   ___MESSAGE___( "process exited" );
1729   if ( shellProcess->normalExit() ) {
1730     ___MESSAGE___( "...normal exit" );
1731     // normal exit - try to proceed installation further
1732     launchScript();
1733   }
1734   else {
1735     ___MESSAGE___( "...abnormal exit" );
1736     // installation aborted
1737     abort();
1738     // clear script passed parameters lineedit
1739     passedParams->clear();
1740     passedParams->setEnabled( false );
1741     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1742     // enable <Next> button
1743     setNextEnabled( true );
1744     nextButton()->setText( tr( "&Next >" ) );
1745     QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1746     QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1747     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1748     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1749     connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1750     // enable <Back> button
1751     setBackEnabled( true );
1752   }
1753 }
1754 // ================================================================
1755 /*!
1756  *  SALOME_InstallWizard::tryTerminate
1757  *  Slot, called when <Cancel> button is clicked during installation script running
1758  */
1759 // ================================================================
1760 void SALOME_InstallWizard::tryTerminate()
1761 {
1762   if ( shellProcess->isRunning() ) {
1763     if ( QMessageBox::information( this, 
1764                                    tr( "Exit" ), 
1765                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
1766                                    tr( "&Yes" ), 
1767                                    tr( "&No" ),
1768                                    QString::null,
1769                                    0,
1770                                    1 ) == 1 ) {
1771       return;
1772     }
1773     exitConfirmed = true;
1774     // if process still running try to terminate it first
1775     shellProcess->tryTerminate();
1776     abort();
1777     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
1778     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
1779   }
1780   else {
1781     // else just quit install wizard
1782     reject();
1783   }
1784 }
1785 // ================================================================
1786 /*!
1787  *  SALOME_InstallWizard::onCancel
1788  *  Kills installation process and quits application
1789  */
1790 // ================================================================
1791 void SALOME_InstallWizard::onCancel()
1792 {
1793   shellProcess->kill();
1794   reject();
1795 }
1796 // ================================================================
1797 /*!
1798  *  SALOME_InstallWizard::onSelectionChanged
1799  *  Called when selection is changed in the products list view
1800  */
1801 // ================================================================
1802 void SALOME_InstallWizard::onSelectionChanged()
1803 {
1804   productsInfo->clear();
1805   QListViewItem* item = productsView->selectedItem();
1806   if ( !item )
1807     return;
1808   if ( item->parent() )
1809     item = item->parent();
1810   QCheckListItem* aItem = (QCheckListItem*)item;
1811   if ( !productsMap.contains( aItem ) )
1812     return;
1813   Dependancies dep = productsMap[ aItem ];
1814   QString text = "<b>" + aItem->text(0) + "</b>" + "<br>";
1815   if ( !aItem->text(1).stripWhiteSpace().isEmpty() )
1816     text += tr( "Version" ) + ": " + aItem->text(1) + "<br>";
1817   text += "<br>";
1818   if ( !dep.getDescription().isEmpty() ) {
1819     text += "<i>" + dep.getDescription() + "</i><br><br>";
1820   }
1821   text += tr( "User choice" ) + ": ";
1822   long totSize = 0, tempSize = 0;
1823   if ( productsView->isBinaries( aItem ) ) {
1824     text += "<b>" + tr( "install binaries" ) + "</b>" + "<br>";
1825     totSize = dep.getSize();
1826   }
1827   else if ( productsView->isSources( aItem ) ) {
1828     text += "<b>" + tr( "install sources" ) + "</b>" + "<br>";
1829     totSize = dep.getSize( true );
1830     tempSize = dep.getTempSize();
1831   }
1832   else if ( productsView->isNative( aItem ) ) {
1833     text += "<b>" + tr( "use native" ) + "</b>" + "<br>";
1834   }
1835   else {
1836     text += "<b>" + tr( "not install" ) + "</b>" + "<br>";
1837   }
1838   
1839   text += tr( "Disk space required" ) + ": " + QString::number( totSize ) + " Kb<br>";
1840   text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " Kb<br>";
1841   text += "<br>";
1842   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
1843   text +=  tr( "Prerequisites" ) + ": " + req;
1844   productsInfo->setText( text );
1845 }
1846 // ================================================================
1847 /*!
1848  *  SALOME_InstallWizard::onItemToggled
1849  *  Called when user checks/unchecks any product item
1850  *  Recursively sets all prerequisites and updates "Next" button state
1851  */
1852 // ================================================================
1853 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
1854 {
1855   if ( prerequisites->isChecked() ) {
1856     if ( item->parent() )
1857       item = (QCheckListItem*)( item->parent() );
1858     if ( productsMap.contains( item ) ) {
1859       productsView->blockSignals( true );
1860       setPrerequisites( item );
1861       productsView->blockSignals( false );
1862     }
1863   }
1864   onSelectionChanged();
1865   checkProductPage();
1866 }
1867 // ================================================================
1868 /*!
1869  *  SALOME_InstallWizard::onProdBtn
1870  *  This slot is called when user clicks one of <Select Sources>,
1871  *  <Select Binaries>, <Unselect All> buttons ( products page )
1872  */
1873 // ================================================================
1874 void SALOME_InstallWizard::onProdBtn()
1875 {
1876   const QObject* snd = sender();
1877   productsView->blockSignals( true );
1878   selectSrcBtn->blockSignals( true );
1879   selectBinBtn->blockSignals( true );
1880   if ( snd == unselectBtn ) {
1881     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1882     while( item ) {
1883       productsView->setNone( item );
1884       item = (QCheckListItem*)( item->nextSibling() );
1885     }
1886   }
1887   else if ( snd == selectSrcBtn )  {
1888     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
1889     if ( checkBox->state() == QButton::NoChange )
1890       checkBox->setState( QButton::On );
1891     MapProducts::Iterator itProd;
1892     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1893       if ( itProd.data().getContext() == "salome sources" ) {
1894         if ( checkBox->state() == QButton::Off )
1895           productsView->setNone( itProd.key() );
1896         else
1897           productsView->setSources( itProd.key() );
1898       }
1899     }
1900   }
1901   else if ( snd == selectBinBtn )  {
1902     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
1903     if ( checkBox->state() == QButton::NoChange )
1904       checkBox->setState( QButton::On );
1905     MapProducts::Iterator itProd;
1906     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1907       if ( itProd.data().getContext() == "salome binaries" ) {
1908         if ( checkBox->state() == QButton::Off )
1909           productsView->setNone( itProd.key() );
1910         else
1911           productsView->setBinaries( itProd.key() );
1912       }
1913     }
1914   }
1915   selectSrcBtn->blockSignals( false );
1916   selectBinBtn->blockSignals( false );
1917   productsView->blockSignals( false );
1918   onSelectionChanged();
1919   checkProductPage();
1920 }
1921 // ================================================================
1922 /*!
1923  *  SALOME_InstallWizard::wroteToStdin
1924  *  QProcess slot: -->something was written to stdin
1925  */
1926 // ================================================================
1927 void SALOME_InstallWizard::wroteToStdin( )
1928 {
1929   ___MESSAGE___( "Something was sent to stdin" );
1930 }
1931 // ================================================================
1932 /*!
1933  *  SALOME_InstallWizard::readFromStdout
1934  *  QProcess slot: -->something was written to stdout
1935  */
1936 // ================================================================
1937 void SALOME_InstallWizard::readFromStdout( )
1938 {
1939   ___MESSAGE___( "Something was sent to stdout" );
1940   while ( shellProcess->canReadLineStdout() ) {
1941     installInfo->append( QString( shellProcess->readLineStdout() ) );
1942     installInfo->scrollToBottom();
1943   }
1944   QString str( shellProcess->readStdout() );
1945   if ( !str.isEmpty() ) {
1946     installInfo->append( str );
1947     installInfo->scrollToBottom();
1948   }
1949 }
1950
1951 #define OUTLINE_TEXT(x) QString( "<font color=#FF0000><b>" ) + QString( x ) + QString( "</b></font>" )
1952
1953 // ================================================================
1954 /*!
1955  *  SALOME_InstallWizard::readFromStderr
1956  *  QProcess slot: -->something was written to stderr
1957  */
1958 // ================================================================
1959 void SALOME_InstallWizard::readFromStderr( )
1960 {
1961   ___MESSAGE___( "Something was sent to stderr" );
1962   while ( shellProcess->canReadLineStderr() ) {
1963     installInfo->append( OUTLINE_TEXT( QString( shellProcess->readLineStderr() ) ) );
1964     installInfo->scrollToBottom();
1965   }
1966   QString str( shellProcess->readStderr() );
1967   if ( !str.isEmpty() ) {
1968     installInfo->append( OUTLINE_TEXT( str ) );
1969     installInfo->scrollToBottom();
1970   }
1971   // VSR: 10/11/05 - disable answer mode ==>
1972   // passedParams->setEnabled( true );
1973   // passedParams->setFocus();
1974   // QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
1975   // VSR: 10/11/05 - disable answer mode <==
1976 }
1977 // ================================================================
1978 /*!
1979  *  SALOME_InstallWizard::setDependancies
1980  *  Sets dependancies for the product item
1981  */
1982 // ================================================================
1983 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
1984 {
1985   productsMap[item] = dep;
1986 }
1987 // ================================================================
1988 /*!
1989  *  SALOME_InstallWizard::polish
1990  *  Polishing of the widget - to set right initial size
1991  */
1992 // ================================================================
1993 void SALOME_InstallWizard::polish()
1994 {
1995   resize( 0, 0 );
1996   InstallWizard::polish();
1997 }
1998 // ================================================================
1999 /*!
2000  *  SALOME_InstallWizard::updateCaption
2001  *  Updates caption according to the current page number
2002  */
2003 // ================================================================
2004 void SALOME_InstallWizard::updateCaption()
2005 {
2006   QWidget* aPage = InstallWizard::currentPage();
2007   if ( !aPage ) 
2008     return;
2009   InstallWizard::setCaption( tr( myCaption ) + " " +
2010                              tr( getIWName() ) + " - " +
2011                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
2012 }
2013
2014 // ================================================================
2015 /*!
2016  *  SALOME_InstallWizard::processValidateEvent
2017  *  Processes validation event (<val> is validation code)
2018  */
2019 // ================================================================
2020 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
2021 {
2022   QWidget* aPage = InstallWizard::currentPage();
2023   if ( aPage != productsPage ) {
2024     InstallWizard::processValidateEvent( val, data );
2025     return;
2026   }
2027   myMutex.lock();
2028   myMutex.unlock();
2029   QCheckListItem* item = (QCheckListItem*)data;
2030   if ( val > 0 ) {
2031     if ( val == 2 ) {
2032       WarnDialog::showWarnDlg( 0, false );
2033       // when try_native returns 2 it means that native product version is higher than that is prerequisited
2034       if ( QMessageBox::warning( this, 
2035                                  tr( "Warning" ), 
2036                                  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)),
2037                                 QMessageBox::Yes, 
2038                                 QMessageBox::No, 
2039                                 QMessageBox::NoButton ) == QMessageBox::No ) {
2040         myThread->clearCommands();
2041         myWC.wakeAll();
2042         setNextEnabled( true );
2043         setBackEnabled( true );
2044         return;
2045       }
2046       WarnDialog::showWarnDlg( this, true );
2047     }
2048     else {
2049       WarnDialog::showWarnDlg( 0, false );
2050       bool binMode = productsView->hasBinaries( item );
2051       bool srcMode = productsView->hasSources( item );
2052       QStringList buttons;
2053       buttons.append( binMode ? tr( "Install binaries" ) : ( srcMode ? tr( "Install sources" ) : 
2054                                                                        tr( "Select manually" ) ) );
2055       buttons.append( binMode ? ( srcMode ? tr( "Install sources" ) : tr( "Select manually" ) ) :
2056                                 ( srcMode ? tr( "Select manually" ) : QString::null ) );
2057       buttons.append( binMode && srcMode ? tr( "Select manually" ) : QString::null );
2058       int answer = QMessageBox::warning( this, 
2059                                          tr( "Warning" ), 
2060                                          tr( "You don't have native %1 %2 on your computer.\nPlease, change your installation settings.").arg(item->text(0)).arg(item->text(1)), 
2061                                          buttons[0],
2062                                          buttons[1],
2063                                          buttons[2] );
2064       if ( buttons[ answer ] == tr( "Install binaries" ) )
2065         productsView->setBinaries( item );
2066       else if ( buttons[ answer ] == tr( "Install sources" ) )
2067         productsView->setSources( item );
2068       else {
2069         if ( !moreMode )
2070           onMoreBtn();
2071         productsView->setCurrentItem( item );
2072         productsView->setSelected( item, true );
2073         productsView->ensureItemVisible( item );
2074         myThread->clearCommands();
2075         myWC.wakeAll();
2076         setNextEnabled( true );
2077         setBackEnabled( true );
2078         return;
2079       }
2080       WarnDialog::showWarnDlg( this, true );
2081     }
2082   }
2083   if ( myThread->hasCommands() )
2084     myWC.wakeAll();
2085   else {
2086     WarnDialog::showWarnDlg( 0, false );
2087     InstallWizard::processValidateEvent( val, data );
2088   }
2089 }