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