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