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