]> SALOME platform Git repositories - tools/install.git/blob - src/SALOME_InstallWizard.cxx
Salome HOME
Update for version 2.2.3
[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** ) image0_data ) );
307   // enable sizegrip
308   setSizeGripEnabled( true );
309   
310   // add logo
311   addLogo( QPixmap( (const char**)image1_data ) );
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   nextButton()->disconnect();
1343   connect( nextButton(), SIGNAL( clicked() ), this, SLOT( next() ) );
1344   // <Back> button
1345   setBackEnabled( true );
1346   // script parameters
1347   passedParams->clear();
1348   passedParams->setEnabled( false );
1349   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1350   if ( isMinimized() )
1351     showNormal();
1352   raise();
1353 }
1354 // ================================================================
1355 /*!
1356  *  SALOME_InstallWizard::onMoreBtn
1357  *  <More...> button slot
1358  */
1359 // ================================================================
1360 void SALOME_InstallWizard::onMoreBtn()
1361 {
1362   if ( moreMode ) {
1363     moreBox->hide();
1364     moreBtn->setText( tr( "More..." ) );
1365   }
1366   else {
1367     moreBox->show();
1368     moreBtn->setText( tr( "Less..." ) );
1369   }
1370   qApp->processEvents();
1371   moreMode = !moreMode;
1372   InstallWizard::layOut();
1373   qApp->processEvents();
1374   if ( !isMaximized() ) {
1375     //setGeometry( geometry().x(), geometry().y(), geometry().width(), 0 );
1376     resize( geometry().width(), 0 );
1377     qApp->processEvents();
1378   }
1379   checkProductPage();
1380 }
1381 // ================================================================
1382 /*!
1383  *  SALOME_InstallWizard::onLaunchSalome
1384  *  <Launch Salome> button slot
1385  */
1386 // ================================================================
1387 void SALOME_InstallWizard::onLaunchSalome()
1388 {
1389   QString msg = tr( "You don't have SALOME binaries installed in the %1 directory!" ).arg( targetFolder->text() );
1390
1391   QCheckListItem* item = findItem( "KERNEL-Bin" );
1392   if ( item ) {
1393     QFileInfo fi( targetFolder->text() + "/KERNEL_" + item->text(1) + "/bin/salome/runSalome" );
1394     QFileInfo fienv( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.csh" );
1395     if ( fienv.exists() ) {
1396       if ( fi.exists() ) {
1397         QString script;
1398         script += "cd " + targetFolder->text() + "/KERNEL_" + item->text(1) + "; ";
1399         script += "source salome.csh; ";
1400         script += "cd bin/salome; ";
1401         script += "runSalome > /dev/null";
1402         script = "(csh -c '" + script + "')";
1403         ___MESSAGE___( "script: " << script.latin1() );
1404         if ( !system( script.latin1() ) )
1405           return;
1406         else
1407           msg = tr( "Can't launch SALOME." );
1408       }
1409       else
1410         msg = tr( "Can't launch SALOME." ) + "\n" + tr( "runSalome file can not be found." );
1411     }
1412     else
1413       msg = tr( "Can't launch SALOME." ) + "\n" + tr( "Can't find environment file." );
1414   }
1415   QMessageBox::warning( this, 
1416                         tr( "Error" ), 
1417                         msg,
1418                         QMessageBox::Ok, 
1419                         QMessageBox::NoButton,
1420                         QMessageBox::NoButton );
1421 }
1422 // ================================================================
1423 /*!
1424  *  SALOME_InstallWizard::findItem
1425  *  Searches product listview item with given symbolic name 
1426  */
1427 // ================================================================
1428 QCheckListItem* SALOME_InstallWizard::findItem( const QString& sName )
1429 {
1430   MapProducts::Iterator mapIter;
1431   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1432     if ( mapIter.data().getName() == sName )
1433       return mapIter.key();
1434   }
1435   return 0;
1436 }
1437 // ================================================================
1438 /*!
1439  *  SALOME_InstallWizard::abort
1440  *  Sets progress state to Aborted
1441  */
1442 // ================================================================
1443 void SALOME_InstallWizard::abort()
1444 {
1445   QString prod = progressView->findStatus( Processing );
1446   while ( !prod.isNull() ) {
1447     progressView->setStatus( prod, Aborted );
1448     prod = progressView->findStatus( Processing );
1449   }
1450   prod = progressView->findStatus( Waiting );
1451   while ( !prod.isNull() ) {
1452     progressView->setStatus( prod, Aborted );
1453     prod = progressView->findStatus( Waiting );
1454   }
1455 }
1456 // ================================================================
1457 /*!
1458  *  SALOME_InstallWizard::reject
1459  *  Reject slot, clears temporary directory and closes application
1460  */
1461 // ================================================================
1462 void SALOME_InstallWizard::reject()
1463 {
1464   ___MESSAGE___( "REJECTED" );
1465   if ( !exitConfirmed ) {
1466     if ( QMessageBox::information( this, 
1467                                    tr( "Exit" ), 
1468                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
1469                                    tr( "&Yes" ), 
1470                                    tr( "&No" ),
1471                                    QString::null,
1472                                    0,
1473                                    1 ) == 1 ) {
1474       return;
1475     }
1476     exitConfirmed = true;
1477   }
1478   clean(true);
1479   InstallWizard::reject();
1480 }
1481 // ================================================================
1482 /*!
1483  *  SALOME_InstallWizard::accept
1484  *  Accept slot, clears temporary directory and closes application
1485  */
1486 // ================================================================
1487 void SALOME_InstallWizard::accept()
1488 {
1489   ___MESSAGE___( "ACCEPTED" );
1490   clean(true);
1491   InstallWizard::accept();
1492 }
1493 // ================================================================
1494 /*!
1495  *  SALOME_InstallWizard::clean
1496  *  Clears and (optionally) removes temporary directory
1497  */
1498 // ================================================================
1499 void SALOME_InstallWizard::clean(bool rmDir)
1500 {
1501   WarnDialog::showWarnDlg( 0, false );
1502   myThread->clearCommands();
1503   myWC.wakeAll();
1504   while ( myThread->running() );
1505   // VSR: first remove temporary files
1506   QString script = "cd ./config_files/; remove_tmp.sh '";
1507   script += tempFolder->text().stripWhiteSpace() + TEMPDIRNAME;
1508   script += "' ";
1509   script += QUOTE(DefineDependeces(productsMap));
1510   script += " > /dev/null";
1511   ___MESSAGE___( "script = " << script );
1512   if ( system( script.latin1() ) ) {
1513   }
1514   // VSR: then try to remove created temporary directory
1515   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1516   if ( rmDir && !tmpCreated.isNull() ) {
1517     script = "rm -rf " + tmpCreated;
1518     script += " > /dev/null";
1519     if ( system( script.latin1() ) ) {
1520     }
1521     ___MESSAGE___( "script = " << script );
1522   }
1523 }
1524 // ================================================================
1525 /*!
1526  *  SALOME_InstallWizard::pageChanged
1527  *  Called when user moves from page to page
1528  */
1529 // ================================================================
1530 void SALOME_InstallWizard::pageChanged( const QString & mytitle)
1531 {
1532   nextButton()->setText( tr( "&Next >" ) );
1533   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1534   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1535   nextButton()->disconnect();
1536   connect( nextButton(), SIGNAL( clicked() ), this, SLOT( next() ) );
1537   cancelButton()->disconnect();
1538   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
1539
1540   QWidget* aPage = InstallWizard::page( mytitle );
1541   if ( !aPage )
1542     return;
1543   updateCaption();
1544   if ( aPage == productsPage ) {
1545     // products page
1546     onSelectionChanged();
1547     checkProductPage();
1548   }
1549   else if ( aPage == prestartPage ) {
1550     // prestart page
1551     showChoiceInfo();
1552   }
1553   else if ( aPage == progressPage ) {
1554     if ( previousPage == prestartPage ) {
1555       // progress page
1556       progressView->clear();
1557       installInfo->clear();
1558       passedParams->clear();
1559       passedParams->setEnabled( false );
1560       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1561       nextButton()->setText( tr( "&Start" ) );
1562       QWhatsThis::add( nextButton(), tr( "Starts installation process" ) );
1563       QToolTip::add  ( nextButton(), tr( "Starts installation process" ) );
1564       // reconnect Next button - to use it as Start button
1565       nextButton()->disconnect();
1566       connect( nextButton(), SIGNAL( clicked() ), this, SLOT( onStart() ) );
1567       setNextEnabled( true );
1568       // reconnect Cancel button to terminate process
1569       cancelButton()->disconnect();
1570       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
1571     }
1572   }
1573   else if ( aPage == readmePage ) {
1574     QCheckListItem* item = findItem( "KERNEL-Bin" );
1575     runSalomeBtn->setEnabled( item &&
1576                               QFileInfo( targetFolder->text() + "/KERNEL_" + item->text(1) + "/bin/salome/runSalome" ).exists() &&
1577                               QFileInfo( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.csh" ).exists() );
1578     finishButton()->setEnabled( true );
1579   }
1580   previousPage = aPage;
1581   ___MESSAGE___( "previousPage = " << previousPage );
1582 }
1583 // ================================================================
1584 /*!
1585  *  SALOME_InstallWizard::helpClicked
1586  *  Shows help window
1587  */
1588 // ================================================================
1589 void SALOME_InstallWizard::helpClicked()
1590 {
1591   if ( helpWindow == NULL ) {
1592     helpWindow = HelpWindow::openHelp( this );
1593     if ( helpWindow ) {
1594       helpWindow->show();
1595       helpWindow->installEventFilter( this );
1596     }
1597     else {
1598       QMessageBox::warning( this, 
1599                             tr( "Help file not found" ), 
1600                             tr( "Sorry, help is unavailable" ) );
1601     }
1602   }
1603   else {
1604     helpWindow->raise();
1605     helpWindow->setActiveWindow();
1606   }
1607 }
1608 // ================================================================
1609 /*!
1610  *  SALOME_InstallWizard::browseDirectory
1611  *  Shows directory selection dialog
1612  */
1613 // ================================================================
1614 void SALOME_InstallWizard::browseDirectory()
1615 {
1616   const QObject* theSender = sender();
1617   QLineEdit* theFolder;
1618   if ( theSender == targetBtn )
1619     theFolder = targetFolder;
1620   else if (theSender == tempBtn)
1621     theFolder = tempFolder;
1622   else
1623     return;
1624   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
1625   if ( !typedDir.isNull() ) {
1626     theFolder->setText( typedDir );
1627     theFolder->end( false );
1628   }
1629   checkProductPage();
1630 }
1631 // ================================================================
1632 /*!
1633  *  SALOME_InstallWizard::directoryChanged
1634  *  Called when directory path (target or temp) is changed
1635  */
1636 // ================================================================
1637 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
1638 {
1639   checkProductPage();
1640 }
1641 // ================================================================
1642 /*!
1643  *  SALOME_InstallWizard::onStart
1644  *  <Start> button's slot - runs installation
1645  */
1646 // ================================================================
1647 void SALOME_InstallWizard::onStart()
1648 {
1649   // clear list of products to install ...
1650   toInstall.clear();
1651   // ... and fill it for new process
1652   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1653   while( item ) {
1654 //    if ( productsView->isBinaries( item ) || productsView->isSources( item ) || productsView->isNative( item ) ) {
1655       if ( productsMap.contains( item ) )
1656         toInstall.append( productsMap[item].getName() );
1657 //    }
1658     item = (QCheckListItem*)( item->nextSibling() );
1659   }
1660   // if something at all is selected
1661   if ( !toInstall.isEmpty() ) {
1662     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
1663     // disable <Next> button
1664     setNextEnabled( false );
1665     // disable <Back> button
1666     setBackEnabled( false );
1667     // enable script parameters line edit
1668     // VSR commented: 18/09/03: passedParams->setEnabled( true );
1669     // VSR commented: 18/09/03: passedParams->setFocus();
1670     // set status for all products
1671     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
1672       item = findItem( toInstall[ i ] );
1673       QString type = "";
1674       if ( productsView->isBinaries( item ) )
1675         type = tr( "binaries" );
1676       else if ( productsView->isSources( item ) )
1677         type = tr( "sources" );
1678       else if ( productsView->isNative( item ) )
1679         type = tr( "native" );
1680       else 
1681         type = tr( "not install" );
1682       progressView->addProduct( item->text(0), type, item->text(2) );
1683     }
1684     // launch install script
1685     launchScript();
1686   }
1687 }
1688 // ================================================================
1689 /*!
1690  *  SALOME_InstallWizard::onReturnPressed
1691  *  Called when users tries to pass parameters for the script
1692  */
1693 // ================================================================
1694 void SALOME_InstallWizard::onReturnPressed()
1695 {
1696   QString txt = passedParams->text();
1697   installInfo->append( txt );
1698   txt += "\n";
1699   shellProcess->writeToStdin( txt );
1700   passedParams->clear();
1701   progressView->setFocus();
1702   passedParams->setEnabled( false );
1703   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1704 }
1705 /*!
1706   Callback function - as response for the script finishing
1707 */
1708 void SALOME_InstallWizard::productInstalled( )
1709 {
1710   ___MESSAGE___( "process exited" );
1711   if ( shellProcess->normalExit() ) {
1712     ___MESSAGE___( "...normal exit" );
1713     // normal exit - try to proceed installation further
1714     launchScript();
1715   }
1716   else {
1717     ___MESSAGE___( "...abnormal exit" );
1718     // installation aborted
1719     abort();
1720     // clear script passed parameters lineedit
1721     passedParams->clear();
1722     passedParams->setEnabled( false );
1723     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1724     // enable <Next> button
1725     setNextEnabled( true );
1726     nextButton()->setText( tr( "&Next >" ) );
1727     QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1728     QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1729     nextButton()->disconnect();
1730     connect( nextButton(), SIGNAL( clicked() ), this, SLOT( next() ) );
1731     // enable <Back> button
1732     setBackEnabled( true );
1733   }
1734 }
1735 // ================================================================
1736 /*!
1737  *  SALOME_InstallWizard::tryTerminate
1738  *  Slot, called when <Cancel> button is clicked during installation script running
1739  */
1740 // ================================================================
1741 void SALOME_InstallWizard::tryTerminate()
1742 {
1743   if ( shellProcess->isRunning() ) {
1744     if ( QMessageBox::information( this, 
1745                                    tr( "Exit" ), 
1746                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
1747                                    tr( "&Yes" ), 
1748                                    tr( "&No" ),
1749                                    QString::null,
1750                                    0,
1751                                    1 ) == 1 ) {
1752       return;
1753     }
1754     exitConfirmed = true;
1755     // if process still running try to terminate it first
1756     shellProcess->tryTerminate();
1757     abort();
1758     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
1759     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
1760   }
1761   else {
1762     // else just quit install wizard
1763     reject();
1764   }
1765 }
1766 // ================================================================
1767 /*!
1768  *  SALOME_InstallWizard::onCancel
1769  *  Kills installation process and quits application
1770  */
1771 // ================================================================
1772 void SALOME_InstallWizard::onCancel()
1773 {
1774   shellProcess->kill();
1775   reject();
1776 }
1777 // ================================================================
1778 /*!
1779  *  SALOME_InstallWizard::onSelectionChanged
1780  *  Called when selection is changed in the products list view
1781  */
1782 // ================================================================
1783 void SALOME_InstallWizard::onSelectionChanged()
1784 {
1785   productsInfo->clear();
1786   QListViewItem* item = productsView->selectedItem();
1787   if ( !item )
1788     return;
1789   if ( item->parent() )
1790     item = item->parent();
1791   QCheckListItem* aItem = (QCheckListItem*)item;
1792   if ( !productsMap.contains( aItem ) )
1793     return;
1794   Dependancies dep = productsMap[ aItem ];
1795   QString text = "<b>" + aItem->text(0) + "</b>" + "<br>";
1796   if ( !aItem->text(1).stripWhiteSpace().isEmpty() )
1797     text += tr( "Version" ) + ": " + aItem->text(1) + "<br>";
1798   text += "<br>";
1799   if ( !dep.getDescription().isEmpty() ) {
1800     text += "<i>" + dep.getDescription() + "</i><br><br>";
1801   }
1802   text += tr( "User choice" ) + ": ";
1803   long totSize = 0, tempSize = 0;
1804   if ( productsView->isBinaries( aItem ) ) {
1805     text += "<b>" + tr( "install binaries" ) + "</b>" + "<br>";
1806     totSize = dep.getSize();
1807   }
1808   else if ( productsView->isSources( aItem ) ) {
1809     text += "<b>" + tr( "install sources" ) + "</b>" + "<br>";
1810     totSize = dep.getSize( true );
1811     tempSize = dep.getTempSize();
1812   }
1813   else if ( productsView->isNative( aItem ) ) {
1814     text += "<b>" + tr( "use native" ) + "</b>" + "<br>";
1815   }
1816   else {
1817     text += "<b>" + tr( "not install" ) + "</b>" + "<br>";
1818   }
1819   
1820   text += tr( "Disk space required" ) + ": " + QString::number( totSize ) + " Kb<br>";
1821   text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " Kb<br>";
1822   text += "<br>";
1823   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
1824   text +=  tr( "Prerequisites" ) + ": " + req;
1825   productsInfo->setText( text );
1826 }
1827 // ================================================================
1828 /*!
1829  *  SALOME_InstallWizard::onItemToggled
1830  *  Called when user checks/unchecks any product item
1831  *  Recursively sets all prerequisites and updates "Next" button state
1832  */
1833 // ================================================================
1834 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
1835 {
1836   if ( prerequisites->isChecked() ) {
1837     if ( item->parent() )
1838       item = (QCheckListItem*)( item->parent() );
1839     if ( productsMap.contains( item ) ) {
1840       productsView->blockSignals( true );
1841       setPrerequisites( item );
1842       productsView->blockSignals( false );
1843     }
1844   }
1845   onSelectionChanged();
1846   checkProductPage();
1847 }
1848 // ================================================================
1849 /*!
1850  *  SALOME_InstallWizard::onProdBtn
1851  *  This slot is called when user clicks one of <Select Sources>,
1852  *  <Select Binaries>, <Unselect All> buttons ( products page )
1853  */
1854 // ================================================================
1855 void SALOME_InstallWizard::onProdBtn()
1856 {
1857   const QObject* snd = sender();
1858   productsView->blockSignals( true );
1859   selectSrcBtn->blockSignals( true );
1860   selectBinBtn->blockSignals( true );
1861   if ( snd == unselectBtn ) {
1862     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1863     while( item ) {
1864       productsView->setNone( item );
1865       item = (QCheckListItem*)( item->nextSibling() );
1866     }
1867   }
1868   else if ( snd == selectSrcBtn )  {
1869     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
1870     if ( checkBox->state() == QButton::NoChange )
1871       checkBox->setState( QButton::On );
1872     MapProducts::Iterator itProd;
1873     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1874       if ( itProd.data().getContext() == "salome sources" ) {
1875         if ( checkBox->state() == QButton::Off )
1876           productsView->setNone( itProd.key() );
1877         else
1878           productsView->setSources( itProd.key() );
1879       }
1880     }
1881   }
1882   else if ( snd == selectBinBtn )  {
1883     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
1884     if ( checkBox->state() == QButton::NoChange )
1885       checkBox->setState( QButton::On );
1886     MapProducts::Iterator itProd;
1887     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1888       if ( itProd.data().getContext() == "salome binaries" ) {
1889         if ( checkBox->state() == QButton::Off )
1890           productsView->setNone( itProd.key() );
1891         else
1892           productsView->setBinaries( itProd.key() );
1893       }
1894     }
1895   }
1896   selectSrcBtn->blockSignals( false );
1897   selectBinBtn->blockSignals( false );
1898   productsView->blockSignals( false );
1899   onSelectionChanged();
1900   checkProductPage();
1901 }
1902 // ================================================================
1903 /*!
1904  *  SALOME_InstallWizard::wroteToStdin
1905  *  QProcess slot: -->something was written to stdin
1906  */
1907 // ================================================================
1908 void SALOME_InstallWizard::wroteToStdin( )
1909 {
1910   ___MESSAGE___( "Something was sent to stdin" );
1911 }
1912 // ================================================================
1913 /*!
1914  *  SALOME_InstallWizard::readFromStdout
1915  *  QProcess slot: -->something was written to stdout
1916  */
1917 // ================================================================
1918 void SALOME_InstallWizard::readFromStdout( )
1919 {
1920   ___MESSAGE___( "Something was sent to stdout" );
1921   while ( shellProcess->canReadLineStdout() ) {
1922     installInfo->append( QString( shellProcess->readLineStdout() ) );
1923     installInfo->scrollToBottom();
1924   }
1925   QString str( shellProcess->readStdout() );
1926   if ( !str.isEmpty() ) {
1927     installInfo->append( str );
1928     installInfo->scrollToBottom();
1929   }
1930 }
1931 // ================================================================
1932 /*!
1933  *  SALOME_InstallWizard::readFromStderr
1934  *  QProcess slot: -->something was written to stderr
1935  */
1936 // ================================================================
1937 void SALOME_InstallWizard::readFromStderr( )
1938 {
1939   ___MESSAGE___( "Something was sent to stderr" );
1940   while ( shellProcess->canReadLineStderr() ) {
1941     installInfo->append( QString( shellProcess->readLineStderr() ) );
1942     installInfo->scrollToBottom();
1943   }
1944   QString str( shellProcess->readStderr() );
1945   if ( !str.isEmpty() ) {
1946     installInfo->append( str );
1947     installInfo->scrollToBottom();
1948   }
1949   passedParams->setEnabled( true );
1950   passedParams->setFocus();
1951   QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
1952 }
1953 // ================================================================
1954 /*!
1955  *  SALOME_InstallWizard::setDependancies
1956  *  Sets dependancies for the product item
1957  */
1958 // ================================================================
1959 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
1960 {
1961   productsMap[item] = dep;
1962 }
1963 // ================================================================
1964 /*!
1965  *  SALOME_InstallWizard::polish
1966  *  Polishing of the widget - to set right initial size
1967  */
1968 // ================================================================
1969 void SALOME_InstallWizard::polish()
1970 {
1971   resize( 0, 0 );
1972   InstallWizard::polish();
1973 }
1974 // ================================================================
1975 /*!
1976  *  SALOME_InstallWizard::updateCaption
1977  *  Updates caption according to the current page number
1978  */
1979 // ================================================================
1980 void SALOME_InstallWizard::updateCaption()
1981 {
1982   QWidget* aPage = InstallWizard::currentPage();
1983   if ( !aPage ) 
1984     return;
1985   InstallWizard::setCaption( tr( myCaption ) + " " +
1986                              tr( getIWName() ) + " - " +
1987                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
1988 }
1989
1990 // ================================================================
1991 /*!
1992  *  SALOME_InstallWizard::processValidateEvent
1993  *  Processes validation event (<val> is validation code)
1994  */
1995 // ================================================================
1996 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
1997 {
1998   QWidget* aPage = InstallWizard::currentPage();
1999   if ( aPage != productsPage ) {
2000     InstallWizard::processValidateEvent( val, data );
2001     return;
2002   }
2003   myMutex.lock();
2004   myMutex.unlock();
2005   QCheckListItem* item = (QCheckListItem*)data;
2006   if ( val > 0 ) {
2007     if ( val == 2 ) {
2008       WarnDialog::showWarnDlg( 0, false );
2009       // when try_native returns 2 it means that native product version is higher than that is prerequisited
2010       if ( QMessageBox::warning( this, 
2011                                  tr( "Warning" ), 
2012                                  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)),
2013                                 QMessageBox::Yes, 
2014                                 QMessageBox::No, 
2015                                 QMessageBox::NoButton ) == QMessageBox::No ) {
2016         myThread->clearCommands();
2017         myWC.wakeAll();
2018         setNextEnabled( true );
2019         setBackEnabled( true );
2020         return;
2021       }
2022       WarnDialog::showWarnDlg( this, true );
2023     }
2024     else {
2025       WarnDialog::showWarnDlg( 0, false );
2026       QMessageBox::warning( this, 
2027                            tr( "Warning" ), 
2028                            tr( "You don't have native %1 %2 installed").arg(item->text(0)).arg(item->text(1)), 
2029                            QMessageBox::Ok, 
2030                            QMessageBox::NoButton, 
2031                            QMessageBox::NoButton );
2032       myThread->clearCommands();
2033       myWC.wakeAll();
2034       setNextEnabled( true );
2035       setBackEnabled( true );
2036       productsView->setNone( item );
2037       return;
2038     }
2039   }
2040   if ( myThread->hasCommands() )
2041     myWC.wakeAll();
2042   else {
2043     WarnDialog::showWarnDlg( 0, false );
2044     InstallWizard::processValidateEvent( val, data );
2045   }
2046 }