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