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