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