Salome HOME
update config files
[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( pixmap( pxIcon ) );
307   // enable sizegrip
308   setSizeGripEnabled( true );
309   
310   // add logo
311   addLogo( pixmap( pxLogo ) );
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   logoLab = new QLabel( introPage );
448   logoLab->setPixmap( pixmap( pxBigLogo ) );
449   logoLab->setScaledContents( false );
450   logoLab->setFrameStyle( QLabel::Plain | QLabel::NoFrame );
451   logoLab->setAlignment( AlignCenter );
452   // create version box
453   QVBox* versionBox = new QVBox( introPage ); versionBox->setSpacing( 6 );
454   versionBox->setFrameStyle( QVBox::Panel | QVBox::Sunken );
455   QWidget* stretch1 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch1, 5 );
456   versionLab = new QLabel( QString("%1 %2").arg( tr( "Version" ) ).arg(myVersion), versionBox );
457   versionLab->setAlignment( AlignCenter );
458   copyrightLab = new QLabel( myCopyright, versionBox );
459   copyrightLab->setAlignment( AlignCenter );
460   licenseLab = new QLabel( myLicense, versionBox );
461   licenseLab->setAlignment( AlignCenter );
462   QWidget* stretch2 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch2, 5 );
463   // create info box
464   info = new QLabel( introPage );
465   info->setText( tr( "This program will install <b>%1</b>."
466                      "<br><br>The wizard will also help you to install all products "
467                      "which are necessary for <b>%2</b> and setup "
468                      "your environment.<br><br>Click <code>Cancel</code> button to abort "
469                      "installation and quit. Click <code>Next</code> button to continue with the "
470                      "installation program." ).arg( myCaption ).arg( myCaption ) );
471   info->setFrameStyle( QLabel::WinPanel | QLabel::Sunken );
472   info->setMargin( 6 );
473   info->setAlignment( WordBreak );
474   info->setMinimumWidth( 250 );
475   QPalette pal = info->palette();
476   pal.setColor( QColorGroup::Background, QApplication::palette().active().base() );
477   info->setPalette( pal );
478   info->setLineWidth( 2 );
479   // layouting
480   pageLayout->addWidget( logoLab, 0, 0 );
481   pageLayout->addWidget( versionBox, 1, 0 );
482   pageLayout->addMultiCellWidget( info, 0, 1, 1, 1 );
483   pageLayout->setColStretch( 1, 5 );
484   pageLayout->setRowStretch( 1, 5 );
485   // adding page
486   addPage( introPage, tr( "Introduction" ) );
487 }
488 // ================================================================
489 /*!
490  *  SALOME_InstallWizard::setupProductsPage
491  *  Creates products page
492  */
493 // ================================================================
494 void SALOME_InstallWizard::setupProductsPage()
495 {
496   // create page
497   productsPage = new QWidget( this, "ProductsPage" );
498   QGridLayout* pageLayout = new QGridLayout( productsPage ); 
499   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
500   // target directory
501   QLabel* targetLab = new QLabel( tr( "Type the target directory:" ), productsPage );
502   targetFolder = new QLineEdit( productsPage );
503   QWhatsThis::add( targetFolder, tr( "Enter target root directory where products will be installed" ) );
504   QToolTip::add  ( targetFolder, tr( "Enter target root directory where products will be installed" ) );
505   targetBtn = new QPushButton( tr( "Browse..." ), productsPage );
506   QWhatsThis::add( targetBtn, tr( "Click this to browse target directory" ) );
507   QToolTip::add  ( targetBtn, tr( "Click this to browse target directory" ) );
508   // create advanced mode widgets container
509   moreBox = new QWidget( productsPage );
510   QGridLayout* moreBoxLayout = new QGridLayout( moreBox );
511   moreBoxLayout->setMargin( 0 ); moreBoxLayout->setSpacing( 6 );
512   // temp directory
513   QLabel* tempLab = new QLabel( tr( "Type the directory for the temporary files:" ), moreBox );
514   tempFolder = new QLineEdit( moreBox );
515   //  tempFolder->setText( "/tmp" ); // default is /tmp directory
516   QWhatsThis::add( tempFolder, tr( "Enter directory where to put temporary files" ) );
517   QToolTip::add  ( tempFolder, tr( "Enter directory where to put temporary files" ) );
518   tempBtn = new QPushButton( tr( "Browse..." ), moreBox );
519   tempBtn->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
520   QWhatsThis::add( tempBtn, tr( "Click this to browse temporary directory" ) );
521   QToolTip::add  ( tempBtn, tr( "Click this to browse temporary directory" ) );
522   // create products list
523   productsView = new ProductsView( moreBox );
524   productsView->setMinimumSize( 250, 180 );
525   QWhatsThis::add( productsView, tr( "This view lists the products you wish to be installed" ) );
526   QToolTip::add  ( productsView, tr( "This view lists the products you wish to be installed" ) );
527   // products info box
528   productsInfo = new QTextBrowser( moreBox );
529   productsInfo->setMinimumSize( 270, 135 );
530   QWhatsThis::add( productsInfo, tr( "Shows info about the product: required disk space and prerequisites" ) );
531   QToolTip::add  ( productsInfo, tr( "Shows info about the product: required disk space and prerequisites" ) );
532   // disk space labels
533   QLabel* reqLab1 = new QLabel( tr( "Total disk space required:" ), moreBox );
534   QWhatsThis::add( reqLab1, tr( "Shows total disk space required for installing selected products" ) );
535   QToolTip::add  ( reqLab1, tr( "Shows total disk space required for installing selected products" ) );
536   requiredSize = new QLabel( moreBox );
537   requiredSize->setMinimumWidth( 100 );
538   QWhatsThis::add( requiredSize, tr( "Shows total disk space required for installing selected products" ) );
539   QToolTip::add  ( requiredSize, tr( "Shows total disk space required for installing selected products" ) );
540   QLabel* reqLab2 = new QLabel( tr( "Space for temporary files:" ), moreBox );
541   QWhatsThis::add( reqLab2, tr( "Shows additional disk space which is required for temporary files" ) );
542   QToolTip::add  ( reqLab2, tr( "Shows additional disk space which is required for temporary files" ) );
543   requiredTemp = new QLabel( moreBox );
544   requiredTemp->setMinimumWidth( 100 );
545   QWhatsThis::add( requiredTemp, tr( "Shows additional disk space which is required for temporary files" ) );
546   QToolTip::add  ( requiredTemp, tr( "Shows additional disk space which is required for temporary files" ) );
547   QFont fnt = reqLab1->font();
548   fnt.setBold( true );
549   reqLab1->setFont( fnt );
550   requiredSize->setFont( fnt );
551   reqLab2->setFont( fnt );
552   requiredTemp->setFont( fnt );
553   QGridLayout* sizeLayout = new QGridLayout; sizeLayout->setMargin( 0 ); sizeLayout->setSpacing( 6 );
554   sizeLayout->addWidget( reqLab1,      0, 0 );
555   sizeLayout->addWidget( requiredSize, 0, 1 );
556   sizeLayout->addWidget( reqLab2,      1, 0 );
557   sizeLayout->addWidget( requiredTemp, 1, 1 );
558   // prerequisites checkbox
559   prerequisites = new QCheckBox( tr( "Auto set prerequisites products" ), moreBox );
560   prerequisites->setChecked( true );
561   QWhatsThis::add( prerequisites, tr( "Check this if you want prerequisites products to be set on automatically" ) );
562   QToolTip::add  ( prerequisites, tr( "Check this if you want prerequisites products to be set on automatically" ) );
563   // <Unselect All> button
564   unselectBtn  = new QPushButton( tr( "&Unselect All" ), moreBox );
565   QWhatsThis::add( unselectBtn, tr( "Unselects all products" ) );
566   QToolTip::add  ( unselectBtn, tr( "Unselects all products" ) );
567   // <SALOME sources> / <SALOME binaries> tri-state checkboxes
568   selectSrcBtn  = new QMyCheckBox( tr( "SALOME sources" ), moreBox );
569   selectSrcBtn->setTristate( true );
570   QWhatsThis::add( selectSrcBtn, tr( "Selects/unselects SALOME sources" ) );
571   QToolTip::add  ( selectSrcBtn, tr( "Selects/unselects SALOME sources" ) );
572   selectBinBtn  = new QMyCheckBox( tr( "SALOME binaries" ), moreBox );
573   selectBinBtn->setTristate( true );
574   QWhatsThis::add( selectBinBtn, tr( "Selects/unselects SALOME binaries" ) );
575   QToolTip::add  ( selectBinBtn, tr( "Selects/unselects SALOME binaries" ) );
576   QVBoxLayout* btnLayout = new QVBoxLayout; btnLayout->setMargin( 0 ); btnLayout->setSpacing( 6 );
577   btnLayout->addWidget( unselectBtn );
578   btnLayout->addWidget( selectSrcBtn );
579   btnLayout->addWidget( selectBinBtn );
580   // layouting advancet mode widgets
581   moreBoxLayout->addMultiCellWidget( tempLab,      0, 0, 0, 2 );
582   moreBoxLayout->addMultiCellWidget( tempFolder,   1, 1, 0, 1 );
583   moreBoxLayout->addWidget         ( tempBtn,      1,    2    );
584   moreBoxLayout->addMultiCellWidget( productsView, 2, 5, 0, 0 );
585   moreBoxLayout->addMultiCellWidget( productsInfo, 2, 2, 1, 2 );
586   moreBoxLayout->addMultiCellWidget( prerequisites,3, 3, 1, 2 );
587   moreBoxLayout->addMultiCellLayout( btnLayout,    4, 4, 1, 2 );
588   moreBoxLayout->addMultiCellLayout( sizeLayout,   5, 5, 1, 2 );
589   // <More...> button
590   moreBtn = new QPushButton( tr( "More..." ), productsPage );
591   // layouting
592   pageLayout->addMultiCellWidget( targetLab,    0, 0, 0, 1 );
593   pageLayout->addWidget         ( targetFolder, 1,    0    );
594   pageLayout->addWidget         ( targetBtn,    1,    1    );
595   pageLayout->addMultiCellWidget( moreBox,      2, 2, 0, 1 );
596   pageLayout->addWidget         ( moreBtn,      3,    1    );
597   pageLayout->setRowStretch( 2, 5 );
598   //pageLayout->addRowSpacing( 6, 10 );
599   // xml reader
600   QFile xmlfile(xmlFileName);
601   if ( xmlfile.exists() ) {
602     QXmlInputSource source( &xmlfile );
603     QXmlSimpleReader reader;
604
605     StructureParser* handler = new StructureParser( this );
606     handler->setProductsList(productsView);
607     handler->setTargetDir(targetFolder);
608     handler->setTempDir(tempFolder);
609     reader.setContentHandler( handler );
610     reader.parse( source );  
611   }
612   // set first item to be selected
613   if ( productsView->childCount() > 0 ) {
614     productsView->setSelected( productsView->firstChild(), true );
615     onSelectionChanged();
616   }
617   // adding page
618   addPage( productsPage, tr( "Installation settings" ) );
619   // connecting signals
620   connect( productsView, SIGNAL( selectionChanged() ), 
621                                               this, SLOT( onSelectionChanged() ) );
622   connect( productsView, SIGNAL( itemToggled( QCheckListItem* ) ), 
623                                               this, SLOT( onItemToggled( QCheckListItem* ) ) );
624   connect( unselectBtn,  SIGNAL( clicked() ), this, SLOT( onProdBtn() ) );
625   connect( selectSrcBtn, SIGNAL( stateChanged(int) ), 
626                                               this, SLOT( onProdBtn() ) );
627   connect( selectBinBtn, SIGNAL( stateChanged(int) ), 
628                                               this, SLOT( onProdBtn() ) );
629   // connecting signals
630   connect( targetFolder, SIGNAL( textChanged( const QString& ) ),
631                                               this, SLOT( directoryChanged( const QString& ) ) );
632   connect( targetBtn,    SIGNAL( clicked() ), this, SLOT( browseDirectory() ) );
633   connect( tempFolder,   SIGNAL( textChanged( const QString& ) ),
634                                               this, SLOT( directoryChanged( const QString& ) ) );
635   connect( tempBtn,      SIGNAL( clicked() ), this, SLOT( browseDirectory() ) );
636   connect( moreBtn,      SIGNAL( clicked() ), this, SLOT( onMoreBtn() ) );
637   // start on default - non-advanced - mode
638   moreBox->hide();
639 }
640 // ================================================================
641 /*!
642  *  SALOME_InstallWizard::setupCheckPage
643  *  Creates prestart page
644  */
645 // ================================================================
646 void SALOME_InstallWizard::setupCheckPage()
647 {
648   // create page
649   prestartPage = new QWidget( this, "PrestartPage" );
650   QVBoxLayout* pageLayout = new QVBoxLayout( prestartPage ); 
651   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
652   // choice text view
653   choices = new QTextEdit( prestartPage );
654   choices->setReadOnly( true );
655   choices->setTextFormat( RichText );
656   choices->setUndoRedoEnabled ( false );
657   QWhatsThis::add( choices, tr( "Displays information about installation settings you made" ) );
658   QToolTip::add  ( choices, tr( "Displays information about installation settings you made" ) );
659   QPalette pal = choices->palette();
660   pal.setColor( QColorGroup::Base, QApplication::palette().active().background() );
661   choices->setPalette( pal );
662   choices->setMinimumHeight( 10 );
663   // layouting
664   pageLayout->addWidget( choices );
665   pageLayout->setStretchFactor( choices, 5 );
666   // adding page
667   addPage( prestartPage, tr( "Check your choice" ) );
668 }
669 // ================================================================
670 /*!
671  *  SALOME_InstallWizard::setupProgressPage
672  *  Creates progress page
673  */
674 // ================================================================
675 void SALOME_InstallWizard::setupProgressPage()
676 {
677   // create page
678   progressPage = new QWidget( this, "progressPage" );
679   QGridLayout* pageLayout = new QGridLayout( progressPage ); 
680   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
681   // top splitter
682   splitter = new QSplitter( Vertical, progressPage );
683   splitter->setOpaqueResize( true );
684   // the parent for the widgets
685   QWidget* widget = new QWidget( splitter );
686   QGridLayout* layout = new QGridLayout( widget ); 
687   layout->setMargin( 0 ); layout->setSpacing( 6 );
688   // installation progress view box
689   installInfo = new QTextEdit( widget );
690   installInfo->setReadOnly( true );
691   installInfo->setTextFormat( RichText );
692   installInfo->setUndoRedoEnabled ( false );
693   installInfo->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
694   installInfo->setMinimumSize( 100, 10 );
695   QWhatsThis::add( installInfo, tr( "Displays installation process" ) );
696   QToolTip::add  ( installInfo, tr( "Displays installation process" ) );
697   // parameters for the script
698   parametersLab = new QLabel( tr( "Enter your answer here:" ), widget );
699   passedParams = new QLineEdit ( widget );
700   QWhatsThis::add( passedParams, tr( "Use this field to enter answer for the running script when it is necessary") );
701   QToolTip::add  ( passedParams, tr( "Use this field to enter answer for the running script when it is necessary") );
702   // layouting
703   layout->addWidget( installInfo,   0, 0 );
704   layout->addWidget( parametersLab, 1, 0 );
705   layout->addWidget( passedParams,  2, 0 );
706   layout->addRowSpacing( 3, 6 );
707   // the parent for the widgets
708   widget = new QWidget( splitter );
709   layout = new QGridLayout( widget ); 
710   layout->setMargin( 0 ); layout->setSpacing( 6 );
711   // installation results view box
712   QLabel* resultLab = new QLabel( tr( "Installation Status:" ), widget );
713   progressView = new ProgressView( widget );
714   progressView->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
715   progressView->setMinimumSize( 100, 10 );
716   QWhatsThis::add( progressView, tr( "Displays installation status" ) );
717   QToolTip::add  ( progressView, tr( "Displays installation status" ) );
718   // layouting
719   layout->addRowSpacing( 0, 6 );
720   layout->addWidget( resultLab,    1, 0 );
721   layout->addWidget( progressView, 2, 0 );
722   // layouting
723   pageLayout->addWidget( splitter, 0, 0 );
724   // adding page
725   addPage( progressPage, tr( "Installation progress" ) );
726   // connect signals
727   connect( passedParams, SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) ) ;
728 }
729 // ================================================================
730 /*!
731  *  SALOME_InstallWizard::setupReadmePage
732  *  Creates readme page
733  */
734 // ================================================================
735 void SALOME_InstallWizard::setupReadmePage()
736 {
737   // create page
738   readmePage = new QWidget( this, "ReadmePage" );
739   QVBoxLayout* pageLayout = new QVBoxLayout( readmePage ); 
740   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
741   // README info text box
742   readme = new QTextEdit( readmePage );
743   readme->setReadOnly( true );
744   readme->setTextFormat( PlainText );
745   readme->setFont( QFont( "Fixed", 10 ) );
746   readme->setUndoRedoEnabled ( false );
747   QWhatsThis::add( readme, tr( "Displays README information" ) );
748   QToolTip::add  ( readme, tr( "Displays README information" ) );
749   QPalette pal = readme->palette();
750   pal.setColor( QColorGroup::Base, QApplication::palette().active().background() );
751   readme->setPalette( pal );
752   readme->setMinimumHeight( 10 );
753   // <Launch SALOME> button
754   runSalomeBtn = new QPushButton( tr( "Launch SALOME" ), readmePage );
755   QWhatsThis::add( runSalomeBtn, tr( "Click this button to run SALOME desktop" ) );
756   QToolTip::add  ( runSalomeBtn, tr( "Click this button to run SALOME desktop" ) );
757   QHBoxLayout* hLayout = new QHBoxLayout;
758   hLayout->addWidget( runSalomeBtn ); hLayout->addStretch();
759   // layouting
760   pageLayout->addWidget( readme );
761   pageLayout->setStretchFactor( readme, 5 );
762   pageLayout->addLayout( hLayout );
763   // connecting signals
764   connect( runSalomeBtn, SIGNAL( clicked() ), this, SLOT( onLaunchSalome() ) );
765   // loading README file
766   QString readmeFile = QDir::currentDirPath() + "/README";
767   QString text;
768   if ( readFile( readmeFile, text ) )
769     readme->setText( text );
770   else
771     readme->setText( tr( "README file has not been found" ) );
772   // adding page
773   addPage( readmePage, tr( "Finish installation" ) );
774 }
775 // ================================================================
776 /*!
777  *  SALOME_InstallWizard::showChoiceInfo
778  *  Displays choice info
779  */
780 // ================================================================
781 void SALOME_InstallWizard::showChoiceInfo()
782 {
783   choices->clear();
784
785   long totSize, tempSize;
786   checkSize( &totSize, &tempSize );
787   int nbProd = 0;
788   QString text;
789
790   if ( !xmlFileName.isEmpty() ) {
791     text += tr( "Configuration file" )+ ": <b>" + xmlFileName + "</b><br>";
792     text += "<br>";
793   }
794   if ( !myOS.isEmpty() ) {
795     text += tr( "Target platform" ) + ": <b>" + myOS + "</b><br>";
796     text += "<br>";
797   }
798   text += tr( "Products to be used" ) + ":<ul>";
799   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
800   while( item ) {
801     if ( productsMap.contains( item ) ) {
802       if ( item->childCount() > 0 ) {
803         if ( productsView->isNative( item ) ) {
804           text += "<li><b>" + item->text() + "</b> " + tr( "as native" ) + "<br>";
805           nbProd++;
806         }
807       }
808     }
809     item = (QCheckListItem*)( item->nextSibling() );
810   }
811   if ( nbProd == 0 ) {
812     text += "<li><b>" + tr( "none" ) + "</b><br>";
813   }
814   text += "</ul>";
815   nbProd = 0;
816   text += tr( "Products to be installed" ) + ":<ul>";
817   item = (QCheckListItem*)( productsView->firstChild() );
818   while( item ) {
819     if ( productsMap.contains( item ) ) {
820       if ( item->childCount() > 0 ) {
821         if ( productsView->isBinaries( item ) ) {
822           text += "<li><b>" + item->text() + "</b> " + tr( "as binaries" ) + "<br>";
823           nbProd++;
824         }
825         else if ( productsView->isSources( item ) ) {
826           text+= "<li><b>" + item->text() + "</b> " + tr( "as sources" ) + "<br>";
827           nbProd++;
828         }
829       }
830       else if ( item->isOn() ) {
831         text+= "<li><b>" + item->text() + "</b><br>";
832         nbProd++;
833       }
834     }
835     item = (QCheckListItem*)( item->nextSibling() );
836   }
837   if ( nbProd == 0 ) {
838     text += "<li><b>" + tr( "none" ) + "</b><br>";
839   }
840   text += "</ul>";
841   text += tr( "Total disk space required:" ) + " <b>" + QString::number( totSize ) + " Kb</b><br>" ;
842   text += tr( "Space for temporary files required:" ) + " <b>" + QString::number( tempSize ) + " Kb</b><br>" ;
843   text += "<br>";
844   text += tr( "Target directory:" ) + " <b>" + QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) + "</b><br>";
845   // VSR: Temporary folder is used always now and it is not necessary to disable it -->
846   // if ( tempSize > 0 )
847   // VSR: <----------------------------------------------------------------------------
848   text += tr( "Temp directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
849   text += "<br>";
850   choices->setText( text );
851 }
852 // ================================================================
853 /*!
854  *  SALOME_InstallWizard::acceptData
855  *  Validates page when <Next> button is clicked
856  */
857 // ================================================================
858 bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
859 {
860   QString tmpstr;
861   QWidget* aPage = InstallWizard::page( pageTitle );
862   if ( aPage == productsPage ) {
863     // ########## check if any products are selected to be installed
864     long totSize, tempSize;
865     bool anySelected = checkSize( &totSize, &tempSize );
866     if ( !anySelected ) {
867       QMessageBox::warning( this, 
868                             tr( "Warning" ), 
869                             tr( "Select one or more products to install" ), 
870                             QMessageBox::Ok, 
871                             QMessageBox::NoButton,
872                             QMessageBox::NoButton );
873       return false;
874     }
875     // ########## check target and temp directories (existence and available disk space)
876     // get dirs
877     QString targetDir = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
878     QString tempDir   = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() );
879     // directories should differ
880 //    if (!targetDir.isEmpty() && tempDir == targetDir) {
881 //      QMessageBox::warning( this, 
882 //                          tr( "Warning" ), 
883 //                          tr( "Target and temporary directories must be different"), 
884 //                          QMessageBox::Ok, 
885 //                          QMessageBox::NoButton, 
886 //                          QMessageBox::NoButton );
887 //      return false;
888 //    }
889     // check target directory
890     if ( targetDir.isEmpty() ) {
891       QMessageBox::warning( this, 
892                             tr( "Warning" ), 
893                             tr( "Please, enter valid target directory path" ), 
894                             QMessageBox::Ok, 
895                             QMessageBox::NoButton,
896                             QMessageBox::NoButton );
897       return false;
898     }
899     QFileInfo fi( QDir::cleanDirPath( targetDir ) );
900     if ( !fi.exists() ) {
901       bool toCreate = 
902         QMessageBox::warning( this, 
903                               tr( "Warning" ), 
904                               tr( "The directory %1 doesn't exist.\n"
905                                   "Do you want to create directory?" ).arg( fi.absFilePath() ), 
906                               QMessageBox::Yes, 
907                               QMessageBox::No,
908                               QMessageBox::NoButton ) == QMessageBox::Yes;
909       if ( !toCreate) 
910         return false;
911       if ( !makeDir( fi.absFilePath(), tmpstr ) ) {
912         QMessageBox::critical( this, 
913                                tr( "Error" ), 
914                                tr( "Can't create the directory\n%1").arg( fi.absFilePath() ), 
915                                QMessageBox::Ok, 
916                                QMessageBox::NoButton, 
917                                QMessageBox::NoButton );
918         return false;
919       }
920     }
921     if ( !fi.isDir() ) {
922       QMessageBox::warning( this, 
923                             tr( "Warning" ), 
924                             tr( "The directory %1 is not a directory.\n"
925                                 "Please, enter valid target directory path" ).arg( fi.absFilePath() ), 
926                             QMessageBox::Ok, 
927                             QMessageBox::NoButton,
928                             QMessageBox::NoButton );
929       return false;
930     }
931     if ( !fi.isWritable() ) {
932       QMessageBox::warning( this, 
933                             tr( "Warning" ), 
934                             tr( "The directory %1 is not writeable.\n"
935                                 "Please, enter valid target directory path or change permissions" ).arg( fi.absFilePath() ), 
936                             QMessageBox::Ok, 
937                             QMessageBox::NoButton,
938                             QMessageBox::NoButton );
939       return false;
940     }
941     if ( hasSpace( fi.absFilePath() ) &&
942          QMessageBox::warning( this,
943                                tr( "Warning" ),
944                                tr( "The target directory contains space symbols.\n"
945                                    "This may cause problems with compiling or installing of products.\n\n"
946                                    "Do you want to continue?"),
947                                QMessageBox::Yes,
948                                QMessageBox::No,
949                                QMessageBox::NoButton ) == QMessageBox::No ) {
950       return false;
951     }
952     QString binDir = "./Products/BINARIES";
953     if ( !myOS.isEmpty() )
954       binDir += "/" + myOS;
955     QFileInfo fib( QDir::cleanDirPath( binDir ) );
956     if ( !fib.exists() ) {
957       QMessageBox::warning( this, 
958                             tr( "Warning" ), 
959                             tr( "The directory %1 doesn't exist.\n"
960                                 "This directory must contain binaries archives." ).arg( fib.absFilePath() ));
961     }
962     // run script that checks available disk space for installing of products    // returns 1 in case of error
963     QString script = "./config_files/checkSize.sh '";
964     script += fi.absFilePath();
965     script += "' ";
966     script += QString( "%1" ).arg( totSize );
967     ___MESSAGE___( "script = " << script );
968     if ( system( script ) ) {
969       QMessageBox::critical( this, 
970                              tr( "Out of space" ), 
971                              tr( "There is not available disk space for installing of selected products" ), 
972                              QMessageBox::Ok, 
973                              QMessageBox::NoButton, 
974                              QMessageBox::NoButton );
975       return false;
976     }
977     // check temp directory
978     if ( tempDir.isEmpty() ) {
979       if ( moreMode ) {
980         QMessageBox::warning( this, 
981                               tr( "Warning" ), 
982                               tr( "Please, enter valid temp directory path" ), 
983                               QMessageBox::Ok, 
984                               QMessageBox::NoButton,
985                               QMessageBox::NoButton );
986         return false; 
987       }
988       else {
989         tempDir = "/tmp";
990         tempFolder->setText( tempDir );
991       }
992     }
993     QFileInfo fit( QDir::cleanDirPath( tempDir ) );
994     if ( !makeDir( fit.absFilePath() + TEMPDIRNAME, tmpCreated ) ) {
995       QMessageBox::critical( this, 
996                              tr( "Error" ), 
997                              tr( "Can't use temporary directory.\nCheck permissions for the %1 directory.").arg( fit.absFilePath() ), 
998                              QMessageBox::Ok, 
999                              QMessageBox::NoButton, 
1000                              QMessageBox::NoButton );
1001       return false;
1002     }
1003     // run script that check available disk space for temporary files
1004     // returns 1 in case of error
1005     QString tscript = "./config_files/checkSize.sh '";
1006     tscript += fit.absFilePath();
1007     tscript += "' ";
1008     tscript += QString( "%1" ).arg( tempSize );
1009     ___MESSAGE___( "script = " << tscript );
1010     if ( system( tscript ) ) {
1011       QMessageBox::critical( this, 
1012                              tr( "Out of space" ), 
1013                              tr( "There is not available disk space for the temporary files" ), 
1014                              QMessageBox::Ok, 
1015                              QMessageBox::NoButton, 
1016                              QMessageBox::NoButton );
1017       return false;
1018     }
1019 // VSR: <------------------------------------------------------------------------------
1020     // ########## check native products
1021     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1022     QStringList natives;
1023     while( item ) {
1024       if ( productsMap.contains( item ) ) {
1025         if ( item->childCount() > 0 ) {
1026           if ( !productsView->isNone( item ) ) {
1027             if ( item->text(2).isEmpty() || item->text(2).isNull() ) {
1028               QMessageBox::warning( this, 
1029                                     tr( "Warning" ), 
1030                                     tr( "You don't have a defined script for %1").arg(item->text(0)), 
1031                                     QMessageBox::Ok, 
1032                                     QMessageBox::NoButton, 
1033                                     QMessageBox::NoButton );
1034               productsView->setNone( item );
1035               return false;
1036             } else {
1037               QFileInfo fi( QString("./config_files/") + item->text(2) );
1038               if ( !fi.exists() ) {
1039                 QMessageBox::warning( this, 
1040                                       tr( "Warning" ),  
1041                                       tr( "%1 required for %2 doesn't exist.").arg("./config_files/" + item->text(2)).arg(item->text(0)),  
1042                                       QMessageBox::Ok, 
1043                                       QMessageBox::NoButton, 
1044                                       QMessageBox::NoButton );
1045                 productsView->setNone( item );
1046                 return false;
1047               }       
1048             }
1049           }
1050           // collect native products
1051           if ( productsView->isNative( item ) ) {
1052             if ( natives.find( item->text(0) ) == natives.end() )
1053               natives.append( item->text(0) );
1054           } 
1055           else if ( productsView->isBinaries( item ) || productsView->isSources( item ) ) {
1056             QStringList dependOn = productsMap[ item ].getDependancies();
1057             for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1058               QCheckListItem* depitem = findItem( dependOn[ i ] );
1059               if ( depitem ) {
1060                 if ( productsView->isNative( depitem ) && natives.find( depitem->text(0) ) == natives.end() )
1061                   natives.append( depitem->text(0) );
1062               } 
1063               else {
1064                 QMessageBox::warning( this, 
1065                                       tr( "Warning" ), 
1066                                       tr( "%1 is required for %2 %3 installation.\n"
1067                                           "Please, add this product in config.xml file.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)), 
1068                                       QMessageBox::Ok, 
1069                                       QMessageBox::NoButton, 
1070                                       QMessageBox::NoButton );
1071                 return false;
1072               }
1073             }
1074           }
1075         }
1076       }
1077       item = (QCheckListItem*)( item->nextSibling() );
1078     }
1079     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1080     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1081     myThread->clearCommands();
1082     if ( natives.count() > 0 ) {
1083       for ( unsigned i = 0; i < natives.count(); i++ ) {
1084         item = findItem( natives[ i ] );
1085         if ( item ) {
1086           QString dependOn = productsMap[ item ].getDependancies().join(" ");
1087           QString script = "cd ./config_files/;" + item->text(2) + " try_native " +
1088                   QFileInfo( tmpFolder ).absFilePath() + " " + QDir::currentDirPath() + "/Products " + QFileInfo( tgtFolder ).absFilePath() + " " +
1089                   QUOTE(dependOn) + " " + item->text(0);
1090
1091           myThread->addCommand( item, script );
1092         }
1093         else {
1094           QMessageBox::warning( this, 
1095                                 tr( "Warning" ), 
1096                                 tr( "%The product %1 %2 required for installation.\n"
1097                                     "Please, add this product in config.xml file.").arg(item->text(0)).arg(item->text(1)),
1098                                 QMessageBox::Ok, 
1099                                 QMessageBox::NoButton, 
1100                                 QMessageBox::NoButton );
1101           return false;
1102         }
1103       }
1104       WarnDialog::showWarnDlg( this, true );
1105       myThread->start();
1106       return true; // return in order to avoid default postValidateEvent() action
1107     }
1108   }
1109   return InstallWizard::acceptData( pageTitle );
1110 }
1111 // ================================================================
1112 /*!
1113  *  SALOME_InstallWizard::checkSize
1114  *  Calculates disk space required for the installation
1115  */
1116 // ================================================================
1117 bool SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
1118 {
1119   long tots = 0, temps = 0;
1120   int nbSelected = 0;
1121
1122   MapProducts::Iterator mapIter;
1123   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1124     QCheckListItem* item = mapIter.key();
1125     Dependancies dep = mapIter.data();
1126     if ( productsView->isBinaries( item ) ) {
1127       tots += dep.getSize();
1128     }
1129     else if ( productsView->isSources( item ) ) {
1130       tots += dep.getSize(true);
1131       temps = max( temps, dep.getTempSize() );
1132     }
1133     if ( !productsView->isNone( item ) )
1134       nbSelected++;
1135   }
1136  
1137   if ( totSize )
1138     *totSize = tots;
1139   if ( tempSize )
1140     *tempSize = temps;
1141   return ( nbSelected > 0 );
1142 }
1143 // ================================================================
1144 /*!
1145  *  SALOME_InstallWizard::checkProductPage
1146  *  Checks products page validity (directories and products selection) and
1147  *  enabled/disables "Next" button for the Products page
1148  */
1149 // ================================================================
1150 void SALOME_InstallWizard::checkProductPage()
1151 {
1152   long tots = 0, temps = 0;
1153
1154   // check if any product is selected;
1155   bool isAnyProductSelected = checkSize( &tots, &temps );
1156   // check if target directory is valid
1157   bool isTargetDirValid = !targetFolder->text().stripWhiteSpace().isEmpty();
1158   // check if temp directory is valid
1159   bool isTempDirValid = !moreMode || !tempFolder->text().stripWhiteSpace().isEmpty();
1160
1161   // update required size information
1162   requiredSize->setText( QString::number( tots )  + " Kb");
1163   requiredTemp->setText( QString::number( temps ) + " Kb");
1164   
1165   // update <SALOME sources>, <SALOME binaries> check boxes state
1166   int totSrc = 0, selSrc = 0;
1167   int totBin = 0, selBin = 0;
1168   MapProducts::Iterator itProd;
1169   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1170     if ( itProd.data().getContext() == "salome sources" ) {
1171       totSrc++;
1172       if ( productsView->isSources( itProd.key() ) )
1173         selSrc++;
1174     }
1175     if ( itProd.data().getContext() == "salome binaries" ) {
1176       totBin++;
1177       if ( productsView->isBinaries( itProd.key() ) )
1178         selBin++;
1179     }
1180   }
1181   selectSrcBtn->blockSignals( true );
1182   selectBinBtn->blockSignals( true );
1183   selectSrcBtn->setState( selSrc == 0 ? QButton::Off : ( selSrc == totSrc ? QButton::On : QButton::NoChange  ) );
1184   selectBinBtn->setState( selBin == 0 ? QButton::Off : ( selBin == totBin ? QButton::On : QButton::NoChange  ) );
1185   selectSrcBtn->blockSignals( false );
1186   selectBinBtn->blockSignals( false );
1187
1188   // enable/disable "Next" button
1189   setNextEnabled( productsPage, isAnyProductSelected && isTargetDirValid && isTempDirValid );
1190 }
1191 // ================================================================
1192 /*!
1193  *  SALOME_InstallWizard::setPrerequisites
1194  *  Sets the product and all products this one depends on to be checked ( recursively )
1195  */
1196 // ================================================================
1197 void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
1198 {
1199   if ( !productsMap.contains( item ) )
1200     return;
1201   if ( productsView->isNone( item ) )
1202     return;
1203   // get all prerequisites
1204   QStringList dependOn = productsMap[ item ].getDependancies();
1205   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1206     MapProducts::Iterator itProd;
1207     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1208       if ( itProd.data().getName() == dependOn[ i ] ) {
1209         if ( productsView->isNone( itProd.key() ) ) {
1210           QString defMode = itProd.data().getDefault();
1211           if ( defMode.isEmpty() )
1212             defMode = tr( "install binaries" );
1213           if ( defMode == tr( "install binaries" ) )
1214             productsView->setBinaries( itProd.key() );
1215           else if ( defMode == tr( "install sources" ) )
1216             productsView->setSources( itProd.key() );
1217           else if ( defMode == tr( "use native" ) )
1218             productsView->setNative( itProd.key() );
1219           setPrerequisites( itProd.key() );
1220         }
1221       }
1222     }
1223   }
1224 }
1225 // ================================================================
1226 /*!
1227  *  SALOME_InstallWizard::launchScript
1228  *  Runs installation script
1229  */
1230 // ================================================================
1231 void SALOME_InstallWizard::launchScript()
1232 {
1233   // try to find product being processed now
1234   QString prodProc = progressView->findStatus( Processing );
1235   if ( !prodProc.isNull() ) {
1236     ___MESSAGE___( "Found <Processing>: " );
1237
1238     // if found - set status to "completed"
1239     progressView->setStatus( prodProc, Completed );
1240     // ... and call this method again
1241     launchScript();
1242     return;
1243   }
1244   // else try to find next product which is not processed yet
1245   prodProc = progressView->findStatus( Waiting );
1246   if ( !prodProc.isNull() ) {
1247     ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
1248     // if found - set status to "processed" and run script
1249     progressView->setStatus( prodProc, Processing );
1250     progressView->ensureVisible( prodProc );
1251
1252     QCheckListItem* item = findItem( prodProc );
1253     // fill in script parameters
1254     shellProcess->clearArguments();
1255     // ... script name
1256     shellProcess->setWorkingDirectory( QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() ) );
1257     shellProcess->addArgument( item->text(2) );
1258
1259     // ... temp folder
1260     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1261     //if( !tempFolder->isEnabled() )
1262     //tmpFolder = "/tmp";
1263
1264     // ... binaries ?
1265     if ( productsView->isBinaries( item ) ) {
1266       shellProcess->addArgument( "install_binary" );
1267       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1268       QString binDir = QDir::currentDirPath() + "/Products/BINARIES";
1269       if ( !myOS.isEmpty() )
1270         binDir += "/" + myOS;
1271       shellProcess->addArgument( binDir );
1272     }
1273     // ... sources ?
1274     else if ( productsView->isSources( item ) ) {
1275       shellProcess->addArgument( "install_source" );
1276       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1277       shellProcess->addArgument( QDir::currentDirPath() + "/Products/SOURCES" );
1278     }
1279     // ... native ?
1280     else if ( productsView->isNative( item ) ) {
1281       shellProcess->addArgument( "try_native" );
1282       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1283       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1284     }
1285     // ... not install : try to find preinstalled
1286     else {
1287       shellProcess->addArgument( "try_preinstalled" );
1288       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1289       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1290     }
1291     // ... target folder
1292     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1293     shellProcess->addArgument( QFileInfo( tgtFolder ).absFilePath() );
1294     
1295
1296     QString depproducts = DefineDependeces(productsMap); 
1297     ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
1298
1299     shellProcess->addArgument( depproducts );
1300     // ... product name - currently instaled product
1301     shellProcess->addArgument( item->text(0) );
1302
1303     // run script
1304     if ( !shellProcess->start() ) {
1305       // error handling can be here
1306       ___MESSAGE___( "error" );
1307     }
1308     return;
1309   }
1310   ___MESSAGE___( "All products have been installed successfully" );
1311   // all products are installed successfully
1312   QString workDir = QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() );
1313   MapProducts::Iterator mapIter;
1314   ___MESSAGE___( "starting pick-up environment" );
1315   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1316     QCheckListItem* item = mapIter.key();
1317     Dependancies dep = mapIter.data();
1318     QString depproducts = QUOTE( DefineDependeces(productsMap) ); 
1319     if ( dep.pickUpEnvironment() ) {
1320       ___MESSAGE___( "... for " << dep.getName() );
1321       QString script;
1322       script += "cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
1323       script += item->text(2) + " ";
1324       script += "pickup_env ";
1325       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
1326       script += QUOTE( QFileInfo( QDir::cleanDirPath( QDir::currentDirPath() + "/Products" ) ).absFilePath() ) + " ";
1327       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
1328       script += depproducts + " ";
1329       script += item->text(0);
1330       ___MESSAGE___( "... --> " << script.latin1() );
1331       if ( system( script.latin1() ) ) { 
1332         ___MESSAGE___( "ERROR" ); 
1333       }
1334     }
1335   }
1336   // <Next> button
1337   setNextEnabled( true );
1338   nextButton()->setText( tr( "&Next >" ) );
1339   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1340   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1341   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1342   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1343   connect(    this, SIGNAL( nextClicked() ), 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   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1536   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1537   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1538   cancelButton()->disconnect();
1539   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
1540
1541   QWidget* aPage = InstallWizard::page( mytitle );
1542   if ( !aPage )
1543     return;
1544   updateCaption();
1545   if ( aPage == productsPage ) {
1546     // products page
1547     onSelectionChanged();
1548     checkProductPage();
1549   }
1550   else if ( aPage == prestartPage ) {
1551     // prestart page
1552     showChoiceInfo();
1553   }
1554   else if ( aPage == progressPage ) {
1555     if ( previousPage == prestartPage ) {
1556       // progress page
1557       progressView->clear();
1558       installInfo->clear();
1559       passedParams->clear();
1560       passedParams->setEnabled( false );
1561       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1562       nextButton()->setText( tr( "&Start" ) );
1563       QWhatsThis::add( nextButton(), tr( "Starts installation process" ) );
1564       QToolTip::add  ( nextButton(), tr( "Starts installation process" ) );
1565       // reconnect Next button - to use it as Start button
1566       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1567       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1568       connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1569       setNextEnabled( true );
1570       // reconnect Cancel button to terminate process
1571       cancelButton()->disconnect();
1572       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
1573     }
1574   }
1575   else if ( aPage == readmePage ) {
1576     QCheckListItem* item = findItem( "KERNEL-Bin" );
1577     runSalomeBtn->setEnabled( item &&
1578                               QFileInfo( targetFolder->text() + "/KERNEL_" + item->text(1) + "/bin/salome/runSalome" ).exists() &&
1579                               QFileInfo( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.csh" ).exists() );
1580     finishButton()->setEnabled( true );
1581   }
1582   previousPage = aPage;
1583   ___MESSAGE___( "previousPage = " << previousPage );
1584 }
1585 // ================================================================
1586 /*!
1587  *  SALOME_InstallWizard::helpClicked
1588  *  Shows help window
1589  */
1590 // ================================================================
1591 void SALOME_InstallWizard::helpClicked()
1592 {
1593   if ( helpWindow == NULL ) {
1594     helpWindow = HelpWindow::openHelp( this );
1595     if ( helpWindow ) {
1596       helpWindow->show();
1597       helpWindow->installEventFilter( this );
1598     }
1599     else {
1600       QMessageBox::warning( this, 
1601                             tr( "Help file not found" ), 
1602                             tr( "Sorry, help is unavailable" ) );
1603     }
1604   }
1605   else {
1606     helpWindow->raise();
1607     helpWindow->setActiveWindow();
1608   }
1609 }
1610 // ================================================================
1611 /*!
1612  *  SALOME_InstallWizard::browseDirectory
1613  *  Shows directory selection dialog
1614  */
1615 // ================================================================
1616 void SALOME_InstallWizard::browseDirectory()
1617 {
1618   const QObject* theSender = sender();
1619   QLineEdit* theFolder;
1620   if ( theSender == targetBtn )
1621     theFolder = targetFolder;
1622   else if (theSender == tempBtn)
1623     theFolder = tempFolder;
1624   else
1625     return;
1626   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
1627   if ( !typedDir.isNull() ) {
1628     theFolder->setText( typedDir );
1629     theFolder->end( false );
1630   }
1631   checkProductPage();
1632 }
1633 // ================================================================
1634 /*!
1635  *  SALOME_InstallWizard::directoryChanged
1636  *  Called when directory path (target or temp) is changed
1637  */
1638 // ================================================================
1639 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
1640 {
1641   checkProductPage();
1642 }
1643 // ================================================================
1644 /*!
1645  *  SALOME_InstallWizard::onStart
1646  *  <Start> button's slot - runs installation
1647  */
1648 // ================================================================
1649 void SALOME_InstallWizard::onStart()
1650 {
1651   // clear list of products to install ...
1652   toInstall.clear();
1653   // ... and fill it for new process
1654   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1655   while( item ) {
1656 //    if ( productsView->isBinaries( item ) || productsView->isSources( item ) || productsView->isNative( item ) ) {
1657       if ( productsMap.contains( item ) )
1658         toInstall.append( productsMap[item].getName() );
1659 //    }
1660     item = (QCheckListItem*)( item->nextSibling() );
1661   }
1662   // if something at all is selected
1663   if ( !toInstall.isEmpty() ) {
1664     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
1665     // disable <Next> button
1666     setNextEnabled( false );
1667     // disable <Back> button
1668     setBackEnabled( false );
1669     // enable script parameters line edit
1670     // VSR commented: 18/09/03: passedParams->setEnabled( true );
1671     // VSR commented: 18/09/03: passedParams->setFocus();
1672     // set status for all products
1673     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
1674       item = findItem( toInstall[ i ] );
1675       QString type = "";
1676       if ( productsView->isBinaries( item ) )
1677         type = tr( "binaries" );
1678       else if ( productsView->isSources( item ) )
1679         type = tr( "sources" );
1680       else if ( productsView->isNative( item ) )
1681         type = tr( "native" );
1682       else 
1683         type = tr( "not install" );
1684       progressView->addProduct( item->text(0), type, item->text(2) );
1685     }
1686     // launch install script
1687     launchScript();
1688   }
1689 }
1690 // ================================================================
1691 /*!
1692  *  SALOME_InstallWizard::onReturnPressed
1693  *  Called when users tries to pass parameters for the script
1694  */
1695 // ================================================================
1696 void SALOME_InstallWizard::onReturnPressed()
1697 {
1698   QString txt = passedParams->text();
1699   installInfo->append( txt );
1700   txt += "\n";
1701   shellProcess->writeToStdin( txt );
1702   passedParams->clear();
1703   progressView->setFocus();
1704   passedParams->setEnabled( false );
1705   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1706 }
1707 /*!
1708   Callback function - as response for the script finishing
1709 */
1710 void SALOME_InstallWizard::productInstalled( )
1711 {
1712   ___MESSAGE___( "process exited" );
1713   if ( shellProcess->normalExit() ) {
1714     ___MESSAGE___( "...normal exit" );
1715     // normal exit - try to proceed installation further
1716     launchScript();
1717   }
1718   else {
1719     ___MESSAGE___( "...abnormal exit" );
1720     // installation aborted
1721     abort();
1722     // clear script passed parameters lineedit
1723     passedParams->clear();
1724     passedParams->setEnabled( false );
1725     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1726     // enable <Next> button
1727     setNextEnabled( true );
1728     nextButton()->setText( tr( "&Next >" ) );
1729     QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1730     QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1731     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1732     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1733     connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1734     // enable <Back> button
1735     setBackEnabled( true );
1736   }
1737 }
1738 // ================================================================
1739 /*!
1740  *  SALOME_InstallWizard::tryTerminate
1741  *  Slot, called when <Cancel> button is clicked during installation script running
1742  */
1743 // ================================================================
1744 void SALOME_InstallWizard::tryTerminate()
1745 {
1746   if ( shellProcess->isRunning() ) {
1747     if ( QMessageBox::information( this, 
1748                                    tr( "Exit" ), 
1749                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
1750                                    tr( "&Yes" ), 
1751                                    tr( "&No" ),
1752                                    QString::null,
1753                                    0,
1754                                    1 ) == 1 ) {
1755       return;
1756     }
1757     exitConfirmed = true;
1758     // if process still running try to terminate it first
1759     shellProcess->tryTerminate();
1760     abort();
1761     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
1762     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
1763   }
1764   else {
1765     // else just quit install wizard
1766     reject();
1767   }
1768 }
1769 // ================================================================
1770 /*!
1771  *  SALOME_InstallWizard::onCancel
1772  *  Kills installation process and quits application
1773  */
1774 // ================================================================
1775 void SALOME_InstallWizard::onCancel()
1776 {
1777   shellProcess->kill();
1778   reject();
1779 }
1780 // ================================================================
1781 /*!
1782  *  SALOME_InstallWizard::onSelectionChanged
1783  *  Called when selection is changed in the products list view
1784  */
1785 // ================================================================
1786 void SALOME_InstallWizard::onSelectionChanged()
1787 {
1788   productsInfo->clear();
1789   QListViewItem* item = productsView->selectedItem();
1790   if ( !item )
1791     return;
1792   if ( item->parent() )
1793     item = item->parent();
1794   QCheckListItem* aItem = (QCheckListItem*)item;
1795   if ( !productsMap.contains( aItem ) )
1796     return;
1797   Dependancies dep = productsMap[ aItem ];
1798   QString text = "<b>" + aItem->text(0) + "</b>" + "<br>";
1799   if ( !aItem->text(1).stripWhiteSpace().isEmpty() )
1800     text += tr( "Version" ) + ": " + aItem->text(1) + "<br>";
1801   text += "<br>";
1802   if ( !dep.getDescription().isEmpty() ) {
1803     text += "<i>" + dep.getDescription() + "</i><br><br>";
1804   }
1805   text += tr( "User choice" ) + ": ";
1806   long totSize = 0, tempSize = 0;
1807   if ( productsView->isBinaries( aItem ) ) {
1808     text += "<b>" + tr( "install binaries" ) + "</b>" + "<br>";
1809     totSize = dep.getSize();
1810   }
1811   else if ( productsView->isSources( aItem ) ) {
1812     text += "<b>" + tr( "install sources" ) + "</b>" + "<br>";
1813     totSize = dep.getSize( true );
1814     tempSize = dep.getTempSize();
1815   }
1816   else if ( productsView->isNative( aItem ) ) {
1817     text += "<b>" + tr( "use native" ) + "</b>" + "<br>";
1818   }
1819   else {
1820     text += "<b>" + tr( "not install" ) + "</b>" + "<br>";
1821   }
1822   
1823   text += tr( "Disk space required" ) + ": " + QString::number( totSize ) + " Kb<br>";
1824   text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " Kb<br>";
1825   text += "<br>";
1826   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
1827   text +=  tr( "Prerequisites" ) + ": " + req;
1828   productsInfo->setText( text );
1829 }
1830 // ================================================================
1831 /*!
1832  *  SALOME_InstallWizard::onItemToggled
1833  *  Called when user checks/unchecks any product item
1834  *  Recursively sets all prerequisites and updates "Next" button state
1835  */
1836 // ================================================================
1837 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
1838 {
1839   if ( prerequisites->isChecked() ) {
1840     if ( item->parent() )
1841       item = (QCheckListItem*)( item->parent() );
1842     if ( productsMap.contains( item ) ) {
1843       productsView->blockSignals( true );
1844       setPrerequisites( item );
1845       productsView->blockSignals( false );
1846     }
1847   }
1848   onSelectionChanged();
1849   checkProductPage();
1850 }
1851 // ================================================================
1852 /*!
1853  *  SALOME_InstallWizard::onProdBtn
1854  *  This slot is called when user clicks one of <Select Sources>,
1855  *  <Select Binaries>, <Unselect All> buttons ( products page )
1856  */
1857 // ================================================================
1858 void SALOME_InstallWizard::onProdBtn()
1859 {
1860   const QObject* snd = sender();
1861   productsView->blockSignals( true );
1862   selectSrcBtn->blockSignals( true );
1863   selectBinBtn->blockSignals( true );
1864   if ( snd == unselectBtn ) {
1865     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1866     while( item ) {
1867       productsView->setNone( item );
1868       item = (QCheckListItem*)( item->nextSibling() );
1869     }
1870   }
1871   else if ( snd == selectSrcBtn )  {
1872     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
1873     if ( checkBox->state() == QButton::NoChange )
1874       checkBox->setState( QButton::On );
1875     MapProducts::Iterator itProd;
1876     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1877       if ( itProd.data().getContext() == "salome sources" ) {
1878         if ( checkBox->state() == QButton::Off )
1879           productsView->setNone( itProd.key() );
1880         else
1881           productsView->setSources( itProd.key() );
1882       }
1883     }
1884   }
1885   else if ( snd == selectBinBtn )  {
1886     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
1887     if ( checkBox->state() == QButton::NoChange )
1888       checkBox->setState( QButton::On );
1889     MapProducts::Iterator itProd;
1890     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1891       if ( itProd.data().getContext() == "salome binaries" ) {
1892         if ( checkBox->state() == QButton::Off )
1893           productsView->setNone( itProd.key() );
1894         else
1895           productsView->setBinaries( itProd.key() );
1896       }
1897     }
1898   }
1899   selectSrcBtn->blockSignals( false );
1900   selectBinBtn->blockSignals( false );
1901   productsView->blockSignals( false );
1902   onSelectionChanged();
1903   checkProductPage();
1904 }
1905 // ================================================================
1906 /*!
1907  *  SALOME_InstallWizard::wroteToStdin
1908  *  QProcess slot: -->something was written to stdin
1909  */
1910 // ================================================================
1911 void SALOME_InstallWizard::wroteToStdin( )
1912 {
1913   ___MESSAGE___( "Something was sent to stdin" );
1914 }
1915 // ================================================================
1916 /*!
1917  *  SALOME_InstallWizard::readFromStdout
1918  *  QProcess slot: -->something was written to stdout
1919  */
1920 // ================================================================
1921 void SALOME_InstallWizard::readFromStdout( )
1922 {
1923   ___MESSAGE___( "Something was sent to stdout" );
1924   while ( shellProcess->canReadLineStdout() ) {
1925     installInfo->append( QString( shellProcess->readLineStdout() ) );
1926     installInfo->scrollToBottom();
1927   }
1928   QString str( shellProcess->readStdout() );
1929   if ( !str.isEmpty() ) {
1930     installInfo->append( str );
1931     installInfo->scrollToBottom();
1932   }
1933 }
1934 // ================================================================
1935 /*!
1936  *  SALOME_InstallWizard::readFromStderr
1937  *  QProcess slot: -->something was written to stderr
1938  */
1939 // ================================================================
1940 void SALOME_InstallWizard::readFromStderr( )
1941 {
1942   ___MESSAGE___( "Something was sent to stderr" );
1943   while ( shellProcess->canReadLineStderr() ) {
1944     installInfo->append( QString( shellProcess->readLineStderr() ) );
1945     installInfo->scrollToBottom();
1946   }
1947   QString str( shellProcess->readStderr() );
1948   if ( !str.isEmpty() ) {
1949     installInfo->append( str );
1950     installInfo->scrollToBottom();
1951   }
1952   passedParams->setEnabled( true );
1953   passedParams->setFocus();
1954   QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
1955 }
1956 // ================================================================
1957 /*!
1958  *  SALOME_InstallWizard::setDependancies
1959  *  Sets dependancies for the product item
1960  */
1961 // ================================================================
1962 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
1963 {
1964   productsMap[item] = dep;
1965 }
1966 // ================================================================
1967 /*!
1968  *  SALOME_InstallWizard::polish
1969  *  Polishing of the widget - to set right initial size
1970  */
1971 // ================================================================
1972 void SALOME_InstallWizard::polish()
1973 {
1974   resize( 0, 0 );
1975   InstallWizard::polish();
1976 }
1977 // ================================================================
1978 /*!
1979  *  SALOME_InstallWizard::updateCaption
1980  *  Updates caption according to the current page number
1981  */
1982 // ================================================================
1983 void SALOME_InstallWizard::updateCaption()
1984 {
1985   QWidget* aPage = InstallWizard::currentPage();
1986   if ( !aPage ) 
1987     return;
1988   InstallWizard::setCaption( tr( myCaption ) + " " +
1989                              tr( getIWName() ) + " - " +
1990                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
1991 }
1992
1993 // ================================================================
1994 /*!
1995  *  SALOME_InstallWizard::processValidateEvent
1996  *  Processes validation event (<val> is validation code)
1997  */
1998 // ================================================================
1999 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
2000 {
2001   QWidget* aPage = InstallWizard::currentPage();
2002   if ( aPage != productsPage ) {
2003     InstallWizard::processValidateEvent( val, data );
2004     return;
2005   }
2006   myMutex.lock();
2007   myMutex.unlock();
2008   QCheckListItem* item = (QCheckListItem*)data;
2009   if ( val > 0 ) {
2010     if ( val == 2 ) {
2011       WarnDialog::showWarnDlg( 0, false );
2012       // when try_native returns 2 it means that native product version is higher than that is prerequisited
2013       if ( QMessageBox::warning( this, 
2014                                  tr( "Warning" ), 
2015                                  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)),
2016                                 QMessageBox::Yes, 
2017                                 QMessageBox::No, 
2018                                 QMessageBox::NoButton ) == QMessageBox::No ) {
2019         myThread->clearCommands();
2020         myWC.wakeAll();
2021         setNextEnabled( true );
2022         setBackEnabled( true );
2023         return;
2024       }
2025       WarnDialog::showWarnDlg( this, true );
2026     }
2027     else {
2028       WarnDialog::showWarnDlg( 0, false );
2029       QMessageBox::warning( this, 
2030                            tr( "Warning" ), 
2031                            tr( "You don't have native %1 %2 installed").arg(item->text(0)).arg(item->text(1)), 
2032                            QMessageBox::Ok, 
2033                            QMessageBox::NoButton, 
2034                            QMessageBox::NoButton );
2035       myThread->clearCommands();
2036       myWC.wakeAll();
2037       setNextEnabled( true );
2038       setBackEnabled( true );
2039       productsView->setNone( item );
2040       return;
2041     }
2042   }
2043   if ( myThread->hasCommands() )
2044     myWC.wakeAll();
2045   else {
2046     WarnDialog::showWarnDlg( 0, false );
2047     InstallWizard::processValidateEvent( val, data );
2048   }
2049 }