Salome HOME
Fix problem with incorrect application dir path
[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, Open CASCADE SAS (vadim.sandler@opencascade.com)
4 //  Project   : SALOME
5 //  Module    : Installation Wizard
6 //  Copyright : 2002-2008 CEA
7
8 #include "globals.h"
9
10 #include "SALOME_InstallWizard.hxx"
11 #include "SALOME_ProductsView.hxx"
12 #include "SALOME_ProgressView.hxx"
13 #include "SALOME_XmlHandler.hxx"
14 #include "SALOME_HelpWindow.hxx"
15
16 #include "icons.h"
17
18 #include <qlineedit.h>
19 #include <qpushbutton.h>
20 #include <qlistview.h>
21 #include <qlabel.h>
22 #include <qtextedit.h>
23 #include <qtextbrowser.h>
24 #include <qprocess.h>
25 #include <qcheckbox.h>
26 #include <qsplitter.h>
27 #include <qlayout.h>
28 #include <qfiledialog.h>
29 #include <qapplication.h>
30 #include <qfileinfo.h>
31 #include <qmessagebox.h>
32 #include <qtimer.h>
33 #include <qvbox.h>
34 #include <qwhatsthis.h>
35 #include <qtooltip.h>
36 #include <qfile.h>
37 #include <qthread.h>
38 #include <qwaitcondition.h>
39 #include <qmutex.h>
40 #include <qstringlist.h>
41 #include <qpopupmenu.h>
42 #include <qregexp.h>
43 #include <qradiobutton.h>
44 #include <qbuttongroup.h>
45 #include <qregexp.h>
46 #include <qdir.h>
47
48 #ifdef WNT
49 #include <iostream.h>
50 #include <process.h>
51 #else
52 #include <unistd.h>
53 #include <algo.h>
54 #include <sys/utsname.h>
55 #endif
56
57 #ifdef WNT
58 #define max( x, y ) ( x ) > ( y ) ? ( x ) : ( y )
59 #endif
60
61 QString tmpDirName() { return QString(  "/INSTALLWORK" ) + QString::number( getpid() ); }
62 #define TEMPDIRNAME tmpDirName()
63
64 // ================================================================
65 /*!
66  *  Script
67  *  Helper class to generate shell command
68  */
69 // ================================================================
70 class Script
71 {
72 public:
73   Script( const QString& cmd = QString::null, const QString& sep = " " ) : mySeparator( sep )
74   {
75     append( cmd );
76   }
77   void append( const QString& cmd )
78   {
79     if ( !cmd.isEmpty() ) myList.append( cmd );
80   }
81   Script& operator<<( const QString& cmd )
82   {
83     append( cmd );
84     return *this;
85   }
86   QString script() const
87   {
88     return myList.join( mySeparator );
89   }
90   void clear()
91   {
92     myList.clear();
93   }
94 private:
95   QStringList myList;
96   QString     mySeparator;
97 };
98
99 // ================================================================
100 /*!
101  *  ProcessThread
102  *  Class for executing system commands
103  */
104 // ================================================================
105 static QMutex myMutex(false);
106 static QWaitCondition myWC;
107 class ProcessThread: public QThread
108 {
109   typedef QPtrList<QCheckListItem> ItemList;
110 public:
111   ProcessThread( SALOME_InstallWizard* iw ) : QThread(), myWizard( iw ) { myItems.setAutoDelete( false ); }
112
113   void addCommand( QCheckListItem* item, const QString& cmd ) {
114     myItems.append( item );
115     myCommands.push_back( cmd );
116   }
117
118   bool hasCommands() const { return myCommands.count() > 0; }
119   void clearCommands()     { myCommands.clear(); myItems.clear(); }
120
121   virtual void run() {
122     while ( hasCommands() ) {
123       ___MESSAGE___( "ProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() );
124       int result = system( myCommands[ 0 ] ) / 256; // return code is <errno> * 256
125       ___MESSAGE___( "ProcessThread::run - Result : " << result );
126       QCheckListItem* item = myItems.first();
127       myCommands.pop_front();
128       myItems.removeFirst();
129       myMutex.lock();
130       SALOME_InstallWizard::postValidateEvent( myWizard, result, (void*)item );
131       if ( hasCommands() )
132         myWC.wait(&myMutex);
133       myMutex.unlock();
134     };
135   }
136
137 private:
138   QStringList           myCommands;
139   ItemList              myItems;
140   SALOME_InstallWizard* myWizard;
141 };
142
143 // ================================================================
144 /*!
145  *  WarnDialog
146  *  Warning dialog box
147  */
148 // ================================================================
149 class WarnDialog: public QDialog
150 {
151   static WarnDialog* myDlg;
152   bool myCloseFlag;
153
154   WarnDialog( QWidget* parent )
155   : QDialog( parent, "WarnDialog", true, WDestructiveClose ) {
156     setCaption( tr( "Information" ) );
157     myCloseFlag = false;
158     QLabel* lab = new QLabel( tr( "Please, wait while checking native products configuration ..." ), this );
159     lab->setAlignment( AlignCenter );
160     lab->setFrameStyle( QFrame::Box | QFrame::Plain );
161     QVBoxLayout* l = new QVBoxLayout( this );
162     l->setMargin( 0 );
163     l->add( lab );
164     this->setFixedSize( lab->sizeHint().width()  + 50,
165                         lab->sizeHint().height() * 5 );
166   }
167   void accept() { return; }
168   void reject() { return; }
169   void closeEvent( QCloseEvent* e )
170   { if ( !myCloseFlag ) return;
171     e->accept();
172     QDialog::closeEvent( e );
173   }
174   ~WarnDialog() { myDlg = 0; }
175 public:
176   static void showWarnDlg( QWidget* parent, bool show ) {
177     if ( show ) {
178       if ( !myDlg ) {
179         myDlg = new WarnDialog( parent );
180         QSize sh = myDlg->size();
181         myDlg->move( parent->x() + (parent->width()-sh.width())/2,
182                      parent->y() + (parent->height()-sh.height())/2 );
183         myDlg->show();
184       }
185       myDlg->raise();
186       myDlg->setFocus();
187     }
188     else {
189       if ( myDlg ) {
190         myDlg->myCloseFlag = true;
191         myDlg->close();
192       }
193     }
194   }
195   static bool isWarnDlgShown() { return myDlg != 0; }
196 };
197 WarnDialog* WarnDialog::myDlg = 0;
198
199 // ================================================================
200 /*!
201  *  InstallInfo
202  *  Installation progress info window class
203  */
204 // ================================================================
205 class InstallInfo : public QTextEdit
206 {
207 public:
208   InstallInfo( QWidget* parent ) : QTextEdit( parent ), finished( false ) {}
209   void setFinished( const bool f ) { finished = f; }
210 protected:
211   QPopupMenu* createPopupMenu( const QPoint& )
212   {
213     int para1, col1, para2, col2;
214     getSelection(&para1, &col1, &para2, &col2);
215     bool allSelected = hasSelectedText() &&
216       para1 == 0 && para2 == paragraphs()-1 && col1 == 0 && col2 == paragraphLength(para2);
217     QPopupMenu* popup = new QPopupMenu( this );
218     int id = popup->insertItem( tr( "&Copy" ) );
219     popup->setItemEnabled( id, hasSelectedText() );
220     popup->connectItem ( id, this, SLOT( copy() ) );
221     id = popup->insertItem( tr( "Select &All" ) );
222     popup->setItemEnabled( id, (bool)text().length() && !allSelected );
223     popup->connectItem ( id, this, SLOT( selectAll() ) );
224     if ( finished ) {
225       QWidget* p = parentWidget();
226       while ( p && !p->inherits( "SALOME_InstallWizard" ) )
227         p = p->parentWidget();
228       if ( p && p->inherits( "SALOME_InstallWizard" ) ) {
229         popup->insertSeparator();
230         id = popup->insertItem( tr( "&Save Log" ) );
231         popup->setItemEnabled( id, (bool)text().length() );
232         popup->connectItem ( id, (SALOME_InstallWizard*)p, SLOT( saveLog() ) );
233       }
234     }
235     return popup;
236   }
237 private:
238   bool finished;
239 };
240
241 // ================================================================
242 /*!
243  *  getAllProducts [ static ]
244  *  Defines list of all products as a string separated by space symbols
245  */
246 // ================================================================
247 static QString getAllProducts(MapProducts& theProductsMap)
248 {
249   QStringList aModules, aPrereqs;
250   for ( MapProducts::Iterator mapIter = theProductsMap.begin(); mapIter != theProductsMap.end(); ++mapIter ) {
251     QCheckListItem* item = mapIter.key();
252     Dependancies dep = mapIter.data();
253     QString curModule = item->text(0);
254     if ( !aModules.contains( curModule ) && !aPrereqs.contains( curModule ) ) {
255       if ( dep.getType() == "component" ) {
256         aModules.append( curModule );
257         aModules.append( curModule + "_src" );
258       }
259       else {
260         aPrereqs.append( curModule );
261         aPrereqs.append( curModule + "_src" );
262       }
263     }
264   }
265   return QStringList(aPrereqs+aModules).join(" ");
266 }
267
268 // ================================================================
269 /*!
270  *  setAboutInfo [ static ]
271  *  Sets 'what's this' and 'tooltip' information for the widget
272  */
273 // ================================================================
274 static void setAboutInfo( QWidget* widget, const QString& tip )
275 {
276   QWhatsThis::add( widget, tip );
277   QToolTip::add  ( widget, tip );
278 }
279
280 #define QUOTE(arg) QString("'") + QString(arg) + QString("'")
281
282 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
283                T H E   O L D   I M P L E M E N T A T I O N
284 static QString DefineDependeces(MapProducts& theProductsMap, QCheckListItem* product ){
285   QStringList aProducts;
286   if ( theProductsMap.contains( product ) ) {
287     Dependancies dep = theProductsMap[ product ];
288     QStringList deps = dep.getDependancies();
289     for (int i = 0; i<(int)deps.count(); i++ ) {
290       aProducts.append( deps[i] );
291     }
292   }
293   return QString("\"") + aProducts.join(" ") + QString("\"");
294 }
295 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
296
297 // ================================================================
298 /*!
299  *  makeDir [ static ]
300  *  Makes directory recursively, returns false if not succedes
301  */
302 // ================================================================
303 static bool makeDir( const QString& theDir, QString& theCreated )
304 {
305   if ( theDir.isEmpty() )
306     return false;
307   QString aDir = QDir::cleanDirPath( QFileInfo( theDir ).absFilePath() );
308   int start = 1;
309   while ( start > 0 ) {
310     start = aDir.find( QDir::separator(), start );
311     if ( start > 0 ) {
312       QFileInfo fi( aDir.left( start ) );
313       if ( !fi.exists() ) {
314         // VSR: Create directory and set permissions to allow other users to remove it
315         Script script;
316         script << "mkdir"     << QUOTE( fi.absFilePath() ) << ">& /dev/null" << "&&";
317         script << "chmod 777" << QUOTE( fi.absFilePath() ) << ">& /dev/null";
318         ___MESSAGE___( "script = " << script.script().latin1() );
319         if ( system( script.script().latin1() ) )
320           return false;
321         // VSR: Remember the top of the created directory (to remove it in the end of the installation)
322         if ( theCreated.isNull() )
323           theCreated = fi.absFilePath();
324       }
325     }
326     start++;
327   }
328   if ( !QFileInfo( aDir ).exists() ) {
329     // VSR: Create directory, other users should NOT have possibility to remove it!!!
330     Script script;
331     script << "mkdir" << QUOTE( aDir ) << ">& /dev/null";
332     ___MESSAGE___( "script = " << script.script().latin1() );
333     if ( system( script.script().latin1() ) )
334       return false;
335     // VSR: Remember the top of the created directory (to remove it in the end of the installation)
336     if ( theCreated.isNull() )
337       theCreated = aDir;
338   }
339   return true;
340 }
341 // ================================================================
342 /*!
343  *  readFile [ static ]
344  *  Reads the file, returns false if can't open it
345  */
346 // ================================================================
347 static bool readFile( const QString& fileName, QString& text )
348 {
349   if ( QFile::exists( fileName ) ) {
350     QFile file( fileName );
351     if ( file.open( IO_ReadOnly ) ) {
352       QTextStream stream( &file );
353       QString line;
354       while ( !stream.eof() ) {
355         line = stream.readLine(); // line of text excluding '\n'
356         text += line + "\n";
357       }
358       file.close();
359       return true;
360     }
361   }
362   return false;
363 }
364 // ================================================================
365 /*!
366  *  hasSpace [ static ]
367  *  Checks if string contains spaces; used to check directory paths
368  */
369 // ================================================================
370 static bool hasSpace( const QString& dir )
371 {
372   for ( int i = 0; i < (int)dir.length(); i++ ) {
373     if ( dir[ i ].isSpace() )
374       return true;
375   }
376   return false;
377 }
378
379 // ================================================================
380 /*!
381  *  makeTitle
382  *  Creates HTML-wrapped title text
383  */
384 // ================================================================
385 static QString makeTitle( const QString& text, const QString& separator = " ", bool fl = true )
386 {
387   QStringList words = QStringList::split( separator, text );
388   if ( fl ) {
389     for ( uint i = 0; i < words.count(); i++ )
390       words[i] = QString( "<font color=red>%1</font>" ).arg( words[i].left(1) ) + words[i].mid(1);
391   }
392   else {
393     if ( words.count() > 0 )
394       words[0] = QString( "<font color=red>%1</font>" ).arg( words[0] );
395     if ( words.count() > 1 )
396       words[words.count()-1] = QString( "<font color=red>%1</font>" ).arg( words[words.count()-1] );
397   }
398   QString res = words.join( separator );
399   if ( !res.isEmpty() )
400     res = QString( "<b>%1</b>" ).arg( res );
401   return res;
402 }
403
404 // ================================================================
405 /*!
406  *  QMyCheckBox class : custom check box
407  *  The only goal is to give access to the protected setState() method
408  */
409 // ================================================================
410 class QMyCheckBox: public QCheckBox
411 {
412 public:
413   QMyCheckBox( const QString& text, QWidget* parent, const char* name = 0 ) : QCheckBox ( text, parent, name ) {}
414   void setState ( ToggleState s ) { QCheckBox::setState( s ); }
415 };
416
417 // ================================================================
418 /*!
419  *  AboutDlg
420  *  "About dialog box.
421  */
422 // ================================================================
423 class AboutDlg: public QDialog
424 {
425 public:
426   AboutDlg( SALOME_InstallWizard* parent ) : QDialog( parent, "About dialog box", true )
427   {
428     // caption
429     setCaption( QString( "About %1" ).arg( parent->getIWName() ) );
430     // palette
431     QPalette pal = palette();
432     QColorGroup cg = pal.active();
433     cg.setColor( QColorGroup::Foreground, Qt::darkBlue );
434     cg.setColor( QColorGroup::Background, Qt::white );
435     pal.setActive( cg ); pal.setInactive( cg ); pal.setDisabled( cg );
436     setPalette( pal );
437     // layout
438     QGridLayout* main = new QGridLayout( this, 1, 1, 11, 6 );
439     // image
440     QLabel* logo = new QLabel( this, "logo" );
441     logo->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
442     logo->setMinimumSize( 32, 32 ); logo->setMaximumSize( 32, 32 );
443     logo->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
444     logo->setFrameStyle( QLabel::NoFrame | QLabel::Plain );
445     logo->setPixmap( pixmap( pxAbout ) );
446     logo->setScaledContents( false );
447     logo->setAlignment( QLabel::AlignCenter );
448     // decoration
449     QLabel* decorLeft = new QLabel( this, "decorLeft" );
450     decorLeft->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding ) );
451     decorLeft->setMinimumWidth( 32 ); decorLeft->setMaximumWidth( 32 );
452     decorLeft->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
453     decorLeft->setScaledContents( false );
454     QLabel* decorTop = new QLabel( this, "decorTop" );
455     decorTop->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
456     decorTop->setMinimumHeight( 32 ); decorTop->setMaximumHeight( 32 );
457     decorTop->setPaletteBackgroundColor( QColor( 234, 250, 234 ) );
458     decorTop->setScaledContents( false );
459     // contents
460     QLabel* title = new QLabel( this, "title" );
461     QString tlt = parent->getIWName();
462     title->setText( makeTitle( tlt ) );
463     QLabel* version = new QLabel( this, "version" );
464     version->setText( QString( "<b>Version</b>: %1.%1.%1" ).arg( __IW_VERSION_MAJOR__ ) \
465                       .arg( __IW_VERSION_MINOR__ ) \
466                       .arg( __IW_VERSION_PATCH__ ) );
467     QLabel* copyright = new QLabel( this, "copyright" );
468     copyright->setText( "<b>Copyright</b> &copy; 2007-2009 CEA/DEN" );
469     QFont font = title->font();
470     font.setPointSize( (int)( font.pointSize() * 1.8 ) );
471     title->setFont( font );
472     QFrame* line = new QFrame( this, "line" );
473     line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
474     QLabel* url = new QLabel( this, "url" );
475     url->setText( makeTitle( "www.salome-platform.org", ".", false ) );
476     url->setAlignment( AlignRight );
477     font = version->font();
478     font.setPointSize( (int)( font.pointSize() / 1.2 ) );
479     version->setFont( font );
480     copyright->setFont( font );
481     url->setFont( font );
482     // layout
483     main->addWidget( logo, 0, 0 );
484     main->addMultiCellWidget( decorLeft, 1, 5, 0, 0 );
485     main->addWidget( decorTop, 0, 1 );
486     main->addWidget( title, 1, 1 );
487     main->addWidget( version, 2, 1 );
488     main->addWidget( copyright, 3, 1 );
489     main->addWidget( line, 4, 1 );
490     main->addWidget( url, 5, 1 );
491     // resize
492     QFontMetrics fm( title->font() );
493     int width = (int)( fm.width( tlt ) * 1.5 );
494     title->setMinimumWidth( width );
495 //     setMaximumSize( minimumSize() );
496   }
497   void mousePressEvent( QMouseEvent* )
498   {
499     accept();
500   }
501 };
502
503 // ================================================================
504 /*!
505  *  SALOME_InstallWizard::SALOME_InstallWizard
506  *  Constructor
507  */
508 // ================================================================
509 SALOME_InstallWizard::SALOME_InstallWizard(const QString& aXmlFileName,
510                                            const QString& aTargetDir,
511                                            const QString& aTmpDir,
512                                            const bool     aForceSrc,
513                                            const bool     aSingleDir)
514      : InstallWizard( qApp->desktop(), "SALOME_InstallWizard", false, 0 ),
515        helpWindow( NULL ),
516        moreMode( false ),
517        previousPage( 0 ),
518        exitConfirmed( false ),
519        hasErrors( false )
520 {
521   myIWName     = tr( "Installation Wizard" );
522   tmpCreated   = QString::null;
523   xmlFileName  = aXmlFileName;
524   myTargetPath = aTargetDir;
525   myTmpPath    = aTmpDir;
526   forceSrc     = aForceSrc;
527   singleDir    = aSingleDir;
528   stateChanged = true;
529
530   QDir rootDir( rootDirPath() );
531   binPath = rootDir.filePath( "Products/BINARIES" );
532   srcPath = rootDir.filePath( "Products/SOURCES" );
533   oneProdDirName = "PRODUCTS";
534   
535   commonPlatform = "Debian 3.1";
536   
537   //
538   // get XML filename and current platform
539   //
540   // ... get current platform
541   curPlatform = currentPlatform().join(" ");
542   //cout << "curOS = " << curPlatform << endl;
543   refPlatform = "";
544   // ... check XML and platform definition
545   getXmlAndPlatform();
546
547   // set application font
548   QFont fnt = font();
549   fnt.setPointSize( 14 );
550   fnt.setBold( true );
551   setTitleFont( fnt );
552
553   // set icon
554   setIcon( pixmap( pxIcon ) );
555   // enable sizegrip
556   setSizeGripEnabled( true );
557
558   // add logo
559   addLogo( pixmap( pxLogo ) );
560
561   // set defaults
562   setVersion( "5.1.0" );
563   setCaption( tr( "SALOME %1" ).arg( myVersion ) );
564   setCopyright( tr( "<h5>Copyright &copy; 2007-2008 CEA/DEN, EDF R&amp;D, OPEN CASCADE<br></h5>"
565                 "<h5>Copyright &copy; 2003-2007 OPEN CASCADE,<br>EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&amp;D,<br>LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</h5>" ));
566   setLicense( tr( "<h5>GNU LGPL</h5>" ) );
567
568   ___MESSAGE___( "Configuration file : " << xmlFileName.latin1() );
569   ___MESSAGE___( "Target directory   : " << myTargetPath.latin1() );
570   ___MESSAGE___( "Temporary directory: " << myTmpPath.latin1() );
571
572   //
573   // xml reader
574   //
575   StructureParser* parser = new StructureParser( this );
576   parser->readXmlFile(xmlFileName);
577
578   // create instance of class for starting shell script to get available disk space
579   diskSpaceProc = new QProcess( this, "procDiskSpace" );
580   // create instance of class for starting shell install script
581   shellProcess = new QProcess( this, "shellProcess" );
582   // create instance of class for starting shell script to modify SALOME *.la files
583   modifyLaProc = new QProcess( this, "modifyLaProc" );
584   // create instance of class for starting shell script to check Fortran libraries
585   checkFLibProc = new QProcess( this, "checkFLibProc" );
586
587   // create introduction page
588   setupIntroPage();
589   // create page to select installation type
590   setupTypePage();
591   // create page to select the reference installation platform (if necessary)
592   setupPlatformPage();
593   // create directories page
594   setupDirPage();
595   // create products page
596   setupProductsPage();
597   // create prestart page
598   setupCheckPage();
599   // create progress page
600   setupProgressPage();
601   // create readme page
602   setupReadmePage();
603
604   // common buttons
605   setAboutInfo( backButton(),   tr( "Return to the previous step\nof the installation procedure" ) );
606   setAboutInfo( nextButton(),   tr( "Move to the next step\nof the installation procedure" ) );
607   setAboutInfo( finishButton(), tr( "Finish the installation and quit the program" ) );
608   setAboutInfo( cancelButton(), tr( "Cancel the installation and quit the program" ) );
609   setAboutInfo( helpButton(),   tr( "Show the help information" ) );
610
611   // common signals connections
612   connect( this, SIGNAL( selected( const QString& ) ),
613                                            this, SLOT( pageChanged( const QString& ) ) );
614   connect( this, SIGNAL( helpClicked() ),  this, SLOT( helpClicked() ) );
615   connect( this, SIGNAL( aboutClicked() ), this, SLOT( onAbout() ) );
616
617   // catch signals from launched diskSpaceProc
618   connect( diskSpaceProc, SIGNAL( processExited() ), this, SLOT( updateAvailableSpace() ) );
619   // catch signals from launched shellProcess
620   connect(shellProcess, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout() ) );
621   connect(shellProcess, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr() ) );
622   connect(shellProcess, SIGNAL( processExited() ),   this, SLOT( productInstalled() ) );
623   connect(shellProcess, SIGNAL( wroteToStdin() ),    this, SLOT( wroteToStdin() ) );
624   // catch signals from launched modifyLaProc
625   connect(modifyLaProc, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout() ) );
626   connect(modifyLaProc, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr() ) );
627   connect(modifyLaProc, SIGNAL( processExited() ), this, SLOT( checkModifyLaResult() ) );
628   // catch signals from launched checkFLibProc
629   connect(checkFLibProc, SIGNAL( processExited() ), this, SLOT( checkFLibResult() ) );
630
631   // create validation thread
632   myThread = new ProcessThread( this );
633
634   // show about button
635   setAboutIcon( pixmap( pxAbout ) );
636   showAboutBtn( true );
637 }
638 // ================================================================
639 /*!
640  *  SALOME_InstallWizard::~SALOME_InstallWizard
641  *  Destructor
642  */
643 // ================================================================
644 SALOME_InstallWizard::~SALOME_InstallWizard()
645 {
646   shellProcess->kill(); // kill it for sure
647   int PID = (int)shellProcess->processIdentifier();
648   if ( PID > 0 ) {
649     Script script;
650     script << "kill -9" << QString::number( PID ) << ">& /dev/null";
651     ___MESSAGE___( "script: " << script.script().latin1() );
652     if ( system( script.script().latin1() ) ) {
653       // error
654     }
655   }
656   delete myThread;
657 }
658 // ================================================================
659 /*!
660  *  SALOME_InstallWizard::getBasePlatform
661  *  Determine the base platform for binaries installation
662  */
663 // ================================================================
664 QString SALOME_InstallWizard::getBasePlatform()
665 {
666   QString aBasePlt = "";
667   if ( platformsMap.find( curPlatform ) != platformsMap.end() )
668     aBasePlt = curPlatform;
669   else
670     aBasePlt = commonPlatform;
671   return aBasePlt;
672 }
673 // ================================================================
674 /*!
675  *  SALOME_InstallWizard::currentPlatform
676  *  Tries to determine the current user's operating system
677  */
678 // ================================================================
679 QStringList SALOME_InstallWizard::currentPlatform()
680 {
681   // file parsing
682   QString platName, platVersion, platArch;
683   QString osFileName = "/etc/issue";
684   if ( QFile::exists( osFileName ) ) {
685     QFile file( osFileName );
686     if ( file.open( IO_ReadOnly ) ) {
687       QTextStream stream( &file );
688       QStringList lines = QStringList::split( "\n", stream.read() );
689       file.close();
690       for ( uint i = 0; i < lines.count(); i++ ) {
691         QString str = lines[i];
692         if ( str.isEmpty() ) continue;
693         // parse line
694         QRegExp regvar = QRegExp( "(.*)\\s+[^\\s]*[R|r]elease[^\\s]*\\s+([\\d.]*)" );
695         int pos = regvar.search( str );
696         if ( pos == -1 ) {
697           regvar = QRegExp( "(.*)\\s+[^\\s]*[L|l][I|i][N|n][U|u][X|x][^\\s]*(.*)\\s+([\\d.]*)\\s+" );
698           pos = regvar.search( str );
699         }
700         if ( pos >= 0 ) {
701           QStringList name;
702           for ( int i = 1; i < regvar.numCaptures(); i++ )
703             name.append( regvar.cap( i ) );
704
705           // retrieve platform name
706           platName = QStringList::split( " ", name.join( " " ) ).join( " " );
707           platName = platName.replace( "Linux", "" ).replace( "linux", "" ).replace( "LINUX", "" ).stripWhiteSpace();
708           platName = platName.replace( "Welcome to", "" ).stripWhiteSpace();
709           platName = QStringList::split( " ", platName ).join( " " );
710           // retrieve platform version number
711           platVersion = regvar.cap( regvar.numCaptures() );
712           // retrieve platform 
713           utsname uname_data;
714           uname( &uname_data );
715           if ( QString( uname_data.machine ) == "x86_64" )
716             platArch = "64bit";
717           break;
718         }
719       }
720     }
721   }
722   QStringList vals;
723   if ( !platName.isEmpty() )    vals.append( platName ); 
724   if ( !platVersion.isEmpty() ) vals.append( platVersion ); 
725   if ( !platArch.isEmpty() )    vals.append( platArch ); 
726   return vals;
727 }
728
729 // ================================================================
730 /*!
731  *  SALOME_InstallWizard::rootDirPath
732  *  Get application root dir
733  */
734 // ================================================================
735 QString SALOME_InstallWizard::rootDirPath()
736 {
737   static QString rootDir;
738   if ( rootDir.isEmpty() ) {
739     QDir appDir( qApp->applicationDirPath() );
740     appDir.cdUp();
741     rootDir = appDir.absPath();
742   }
743   return rootDir;
744 }
745
746 // ================================================================
747 /*!
748  *  SALOME_InstallWizard::getPlatformBinPath
749  *  Get platform binaries path
750  */
751 // ================================================================
752 QString SALOME_InstallWizard::getPlatformBinPath( const QString& plt ) const
753 {
754   return QDir::cleanDirPath( getBinPath() + "/" + QStringList::split( " ", plt ).join( "_" ) );
755 }
756
757 // ================================================================
758 /*!
759  *  SALOME_InstallWizard::getXmlMap
760  *  Creates a map of the supported operating systems and 
761  *  corresponding XML files.
762  */
763 // ================================================================
764 MapXmlFiles SALOME_InstallWizard::getXmlMap( const QString& aXmlFileName )
765 {
766   MapXmlFiles xmlMap;
767   QStringList xmlList;
768   if ( !aXmlFileName.isEmpty() )
769     xmlList.append( QFileInfo( aXmlFileName ).absFilePath() );
770   else {
771     QDir dir( rootDirPath() );
772     QStringList entries = dir.entryList( "*.xml", QDir::Files | QDir::Readable );
773     if ( entries.remove( "config.xml" ) )
774       entries.append( "config.xml" );
775     for ( uint i = 0; i < entries.count(); i++ )
776       xmlList.append( QDir( rootDirPath() ).filePath( entries[i] ) ); 
777   }
778   // XML files parsing
779   QFile file;
780   QDomDocument doc( "xml_doc" );
781   QDomElement docElem;
782   QDomNodeList nodeList;
783   QDomNode node;
784   QDomElement elem;
785   QString platforms = "";
786   QStringList platList;
787   for ( uint i = 0; i < xmlList.count(); i++ ) {
788     file.setName( xmlList[i] );
789     if ( !doc.setContent( &file ) ) {
790       file.close();
791       continue;
792     }
793     file.close();
794     
795     docElem = doc.documentElement();
796     nodeList = docElem.elementsByTagName( "config" );
797     if ( nodeList.count() == 0 )
798       continue;      
799     node = nodeList.item( 0 );
800     if ( node.isElement() ) {
801       elem = node.toElement();
802       if ( elem.attribute( "platforms" ) ) {
803         platforms = elem.attribute( "platforms" ).stripWhiteSpace();
804         QStringList platList = QStringList::split( ",", platforms );
805         for ( uint j = 0; j < platList.count(); j++ ) {
806           QString platform = platList[j].stripWhiteSpace();
807           if ( !platform.isEmpty() && xmlMap.find( platform ) == xmlMap.end() )
808             xmlMap[ platList[j] ] = xmlList[i];
809         }
810       }
811     }
812   }
813   return xmlMap;
814 }
815 // ================================================================
816 /*!
817  *  SALOME_InstallWizard::checkXmlAndPlatform
818  *  Check XML file and current platform definition
819  */
820 // ================================================================
821 void SALOME_InstallWizard::getXmlAndPlatform()
822 {
823   MapXmlFiles xmlMap;
824   if ( xmlFileName.isEmpty() ) {
825     xmlMap = getXmlMap();
826     if ( !curPlatform.isEmpty() ) {
827       // try to get XML file for current platform
828       if ( xmlMap.find( curPlatform ) != xmlMap.end() ) {
829         xmlFileName = xmlMap[ curPlatform ];
830         QFileInfo fibp( getPlatformBinPath( curPlatform ) );
831         if ( !fibp.isDir() ) {
832           warnMsg = tr( "Binaries are absent for current platform" );
833         }
834         platformsMap = xmlMap;
835       }
836       else {
837         platformsMap = xmlMap;
838         warnMsg = tr( "Your Linux platform is not supported by this SALOME package" );
839       }
840     }
841     else {
842       // get all supported platforms
843       platformsMap = xmlMap;
844       warnMsg = tr( "Installation Wizard can't identify target Linux platform" );
845     }
846   }
847   else {
848     xmlMap = getXmlMap( xmlFileName );
849     if ( !curPlatform.isEmpty() ) {
850       // check that the user's XML file supports current platform
851       if ( xmlMap.find( curPlatform ) == xmlMap.end() ) {
852         platformsMap = getXmlMap();
853         MapXmlFiles::Iterator it;
854         for ( it = xmlMap.begin(); it != xmlMap.end(); ++it )
855           platformsMap.insert( it.key(), it.data(), true );
856         warnMsg = tr( "The given configuration file doesn't support your Linux platform" );
857       }
858       else {
859         platformsMap = xmlMap;
860       }
861     }
862     else {
863       // get all supported platforms
864       platformsMap = getXmlMap();
865       MapXmlFiles::Iterator it;
866       for ( it = xmlMap.begin(); it != xmlMap.end(); ++it )
867         platformsMap.insert( it.key(), it.data(), true );
868       warnMsg = tr( "Installation Wizard can't define your Linux platform" );
869     }
870   }
871 }
872 // ================================================================
873 /*!
874  *  SALOME_InstallWizard::eventFilter
875  *  Event filter, spies for Help window closing
876  */
877 // ================================================================
878 bool SALOME_InstallWizard::eventFilter( QObject* object, QEvent* event )
879 {
880   if ( object && object == helpWindow && event->type() == QEvent::Close )
881     helpWindow = NULL;
882   return InstallWizard::eventFilter( object, event );
883 }
884 // ================================================================
885 /*!
886  *  SALOME_InstallWizard::closeEvent
887  *  Close event handler
888  */
889 // ================================================================
890 void SALOME_InstallWizard::closeEvent( QCloseEvent* ce )
891 {
892   if ( WarnDialog::isWarnDlgShown() ) {
893     ce->ignore();
894     return;
895   }
896   if ( !exitConfirmed ) {
897     if ( QMessageBox::information( this,
898                                    tr( "Exit" ),
899                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
900                                    tr( "&Yes" ),
901                                    tr( "&No" ),
902                                    QString::null,
903                                    0,
904                                    1 ) == 1 ) {
905       ce->ignore();
906     }
907     else {
908       ce->accept();
909       exitConfirmed = true;
910       reject();
911     }
912   }
913 }
914 // ================================================================
915 /*!
916  *  SALOME_InstallWizard::setupIntroPage
917  *  Creates introduction page
918  */
919 // ================================================================
920 void SALOME_InstallWizard::setupIntroPage()
921 {
922   // create page
923   introPage = new QWidget( this, "IntroPage" );
924   QGridLayout* pageLayout = new QGridLayout( introPage );
925   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
926   // create logo picture
927   logoLab = new QLabel( introPage );
928   logoLab->setPixmap( pixmap( pxBigLogo ) );
929   logoLab->setScaledContents( false );
930   logoLab->setFrameStyle( QLabel::Plain | QLabel::NoFrame );
931   logoLab->setAlignment( AlignCenter );
932   // create version box
933   QVBox* versionBox = new QVBox( introPage ); versionBox->setSpacing( 6 );
934   versionBox->setFrameStyle( QVBox::Panel | QVBox::Sunken );
935   QWidget* stretch1 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch1, 5 );
936   versionLab = new QLabel( QString("%1 %2").arg( tr( "Version" ) ).arg(myVersion), versionBox );
937   versionLab->setAlignment( AlignCenter );
938   copyrightLab = new QLabel( myCopyright, versionBox );
939   copyrightLab->setAlignment( AlignCenter );
940   licenseLab = new QLabel( myLicense, versionBox );
941   licenseLab->setAlignment( AlignCenter );
942   QWidget* stretch2 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch2, 5 );
943   // create info box
944   info = new QLabel( introPage );
945   info->setText( tr( "This program will install <b>%1</b>."
946                      "<br><br>The wizard will also help you to install all products "
947                      "which are necessary for <b>%2</b> and setup "
948                      "your environment.<br><br>Click <code>Cancel</code> button to abort "
949                      "installation and quit. Click <code>Next</code> button to continue with the "
950                      "installation program." ).arg( myCaption ).arg( myCaption ) );
951   info->setFrameStyle( QLabel::WinPanel | QLabel::Sunken );
952   info->setMargin( 6 );
953   info->setAlignment( WordBreak );
954   info->setMinimumWidth( 250 );
955   QPalette pal = info->palette();
956   pal.setColor( QColorGroup::Background, QApplication::palette().active().base() );
957   info->setPalette( pal );
958   info->setLineWidth( 2 );
959   // layouting
960   pageLayout->addWidget( logoLab, 0, 0 );
961   pageLayout->addWidget( versionBox, 1, 0 );
962   pageLayout->addMultiCellWidget( info, 0, 1, 1, 1 );
963   pageLayout->setColStretch( 1, 5 );
964   pageLayout->setRowStretch( 1, 5 );
965   // adding page
966   addPage( introPage, tr( "Introduction" ) );
967 }
968 // ================================================================
969 /*!
970  *  SALOME_InstallWizard::setupTypePage
971  *  Creates installation types page
972  */
973 // ================================================================
974 void SALOME_InstallWizard::setupTypePage()
975 {
976   // create page
977   typePage = new QWidget( this, "TypePage" );
978   QGridLayout* pageLayout = new QGridLayout( typePage );
979   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
980   // create installation type button group
981   buttonGrp = new QButtonGroup( typePage );
982   buttonGrp->setFrameShape(QButtonGroup::NoFrame);
983   QGridLayout* buttonGrpLayout = new QGridLayout( buttonGrp );
984   buttonGrpLayout->setMargin( 0 ); buttonGrpLayout->setSpacing( 6 );
985   QSpacerItem* spacer1 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
986   QSpacerItem* spacer2 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
987   QLabel* selectLab = new QLabel( tr( "Select a type of the installation:" ), buttonGrp );
988   QSpacerItem* spacer3 = new QSpacerItem( 20, 20, QSizePolicy::Fixed, QSizePolicy::Minimum );
989   // ... 'install binaries' layout
990   QGridLayout* binLayout = new QGridLayout( 2, 2, 0 );
991   binBtn = new QRadioButton( tr( "Install binaries" ), buttonGrp );
992   QFont rbFont = binBtn->font();
993   rbFont.setBold( true );
994   binBtn->setFont( rbFont );
995   QSpacerItem* spacer4 = new QSpacerItem( 16, 16, QSizePolicy::Fixed, QSizePolicy::Minimum );
996   QLabel* binLab = new QLabel( tr( "- all the binaries and sources of the chosen SALOME modules will be installed.\n"
997                                    "- all the binaries of the chosen prerequisites will be installed." ), 
998                                buttonGrp );
999   binLayout->addMultiCellWidget( binBtn,  0, 0, 0, 1 );
1000   binLayout->addItem           ( spacer4, 1,    0    );
1001   binLayout->addWidget         ( binLab,  1,    1    );
1002   // ... 'install sources' layout
1003   QGridLayout* srcLayout = new QGridLayout( 2, 2, 0 );
1004   srcBtn = new QRadioButton( tr( "Install sources" ), buttonGrp );
1005   srcBtn->setFont( rbFont );
1006   QSpacerItem* spacer5 = new QSpacerItem( 16, 16, QSizePolicy::Fixed, QSizePolicy::Minimum );
1007   QLabel* srcLab = new QLabel( tr( "- all the sources of the chosen modules and prerequisites will be installed without\ncompilation." ), 
1008                                buttonGrp );
1009   srcLayout->addMultiCellWidget( srcBtn,  0, 0, 0, 1 );
1010   srcLayout->addItem           ( spacer5, 1,    0    );
1011   srcLayout->addWidget         ( srcLab,  1,    1    );
1012   // ... 'install sources and make compilation' layout
1013   QGridLayout* srcCompileLayout = new QGridLayout( 3, 3, 0 );
1014   srcCompileBtn = new QRadioButton( tr( "Install sources and make a compilation" ), buttonGrp );
1015   srcCompileBtn->setFont( rbFont );
1016   QSpacerItem* spacer6 = new QSpacerItem( 16, 16, QSizePolicy::Fixed, QSizePolicy::Minimum );
1017   QLabel* srcCompileLab1 = new QLabel( tr( "- all the sources of the chosen modules and prerequisites will be installed and\ncompiled." ), 
1018                                        buttonGrp );
1019   QLabel* srcCompileLab2 = new QLabel( tr( "Note:" ), 
1020                                        buttonGrp );
1021   QFont noteFont = srcCompileLab2->font();
1022   noteFont.setUnderline( true );
1023   srcCompileLab2->setFont( noteFont );
1024   srcCompileLab2->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) );
1025   srcCompileLab2->setAlignment( Qt::AlignHCenter | Qt::AlignTop );
1026   QLabel* srcCompileLab3 = new QLabel( " " + 
1027                                        tr( "it is a long time operation and it can take more than 24 hours depending\n on the computer." ), 
1028                                        buttonGrp );
1029   removeSrcBtn = new QCheckBox( tr( "Remove sources and temporary files after compilation" ), typePage );
1030   setAboutInfo( removeSrcBtn, tr( "Check this option if you want to remove sources of the products\nwith all the temporary files after build finishing" ) );
1031   removeSrcBtn->setChecked( false );
1032   removeSrcBtn->setEnabled( false );
1033   rmSrcPrevState = removeSrcBtn->isChecked();
1034
1035   srcCompileLayout->addMultiCellWidget( srcCompileBtn,  0, 0, 0, 2 );
1036   srcCompileLayout->addMultiCell      ( spacer6,        1, 2, 0, 0 );
1037   srcCompileLayout->addMultiCellWidget( srcCompileLab1, 1, 1, 1, 2 );
1038   srcCompileLayout->addWidget         ( srcCompileLab2, 2,    1    );
1039   srcCompileLayout->addWidget         ( srcCompileLab3, 2,    2    );
1040   srcCompileLayout->addMultiCellWidget( removeSrcBtn,   3, 3, 1, 2 );
1041   // layout widgets in the button group
1042   buttonGrpLayout->addItem           ( spacer1,          0,    1    );
1043   buttonGrpLayout->addMultiCellWidget( selectLab,        1, 1, 0, 1 );
1044   buttonGrpLayout->addMultiCell      ( spacer3,          2, 4, 0, 0 );
1045   buttonGrpLayout->addLayout         ( binLayout,        2,    1    );
1046   buttonGrpLayout->addLayout         ( srcLayout,        3,    1    );
1047   buttonGrpLayout->addLayout         ( srcCompileLayout, 4,    1    );
1048   buttonGrpLayout->addItem           ( spacer2,          5,    1    );
1049   // layout button group at the page
1050   pageLayout->addWidget( buttonGrp, 0, 0 );
1051   // connecting signals
1052   connect( buttonGrp, SIGNAL( clicked(int) ), this, SLOT ( onButtonGroup(int) ) );
1053   // adding page
1054   addPage( typePage, tr( "Installation type" ) );
1055 }
1056 // ================================================================
1057 /*!
1058  *  SALOME_InstallWizard::setupPlatformPage
1059  *  Creates platforms page, if necessary
1060  */
1061 // ================================================================
1062 void SALOME_InstallWizard::setupPlatformPage()
1063 {
1064   // create page
1065   platformsPage = new QWidget( this, "PlatformsPage" );
1066   QGridLayout* pageLayout = new QGridLayout( platformsPage );
1067   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1068   // create warning labels
1069   QLabel* warnLab2 = new QLabel( tr( "WARNING!" ), platformsPage );
1070   warnLab2->setAlignment( Qt::AlignHCenter );
1071   QFont fnt = warnLab2->font();
1072   fnt.setBold( true );
1073   warnLab2->setFont( fnt );
1074   warnLab = new QLabel( warnMsg, platformsPage );
1075   warnLab->setAlignment( Qt::AlignHCenter | Qt::WordBreak );
1076   warnLab3 = new QLabel( tr( "If you want to proceed anyway, please select platform from the following list:" ), 
1077                                  platformsPage );
1078   warnLab3->setAlignment( Qt::AlignHCenter | Qt::WordBreak );
1079   // create button group
1080   platBtnGrp = new QButtonGroup( platformsPage );
1081   platBtnGrp->setFrameShape(QButtonGroup::LineEditPanel);
1082   platBtnGrp->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) );
1083   QVBoxLayout* platBtnGrpLayout = new QVBoxLayout( platBtnGrp );
1084   platBtnGrpLayout->setMargin( 11 ); platBtnGrpLayout->setSpacing( 6 );
1085   // create platforms radio-buttons
1086   QString plat;
1087   MapXmlFiles::Iterator it;
1088   for ( it = platformsMap.begin(); it != platformsMap.end(); ++it ) {
1089     plat = it.key();
1090     QRadioButton* rb = new QRadioButton( plat, platBtnGrp, plat );
1091     platBtnGrpLayout->addWidget( rb );
1092   }
1093   // create spacers
1094   QSpacerItem* spacer1 = new QSpacerItem( 16, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
1095   QSpacerItem* spacer2 = new QSpacerItem( 16, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
1096
1097   // layout widgets on page
1098   pageLayout->addItem           ( spacer1,    0,    0    );
1099   pageLayout->addWidget         ( warnLab2,   1,    0    );
1100   pageLayout->addWidget         ( warnLab,    2,    0    );
1101   pageLayout->addWidget         ( warnLab3,   3,    0    );
1102   pageLayout->addItem           ( spacer2,    4,    0    );
1103   pageLayout->addMultiCellWidget( platBtnGrp, 0, 4, 1, 1 );
1104
1105   // connecting signals
1106   connect( platBtnGrp, SIGNAL( clicked(int) ), this, SLOT ( onButtonGroup(int) ) );
1107
1108   // adding page
1109   addPage( platformsPage, tr( "Installation platform" ) );
1110 }
1111 // ================================================================
1112 /*!
1113  *  SALOME_InstallWizard::setupDirPage
1114  *  Creates directories page
1115  */
1116 // ================================================================
1117 void SALOME_InstallWizard::setupDirPage()
1118 {
1119   // create page
1120   dirPage = new QWidget( this, "DirPage" );
1121   QGridLayout* pageLayout = new QGridLayout( dirPage );
1122   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1123   QSpacerItem* spacer1 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
1124   QSpacerItem* spacer2 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
1125   // target directory
1126   QGridLayout* targetLayout = new QGridLayout( 2, 2, 0 );
1127   QLabel* targetLab = new QLabel( tr( "Set a target directory to install SALOME platform:" ), dirPage );
1128   targetFolder = new QLineEdit( dirPage );
1129   targetBtn = new QPushButton( tr( "Browse..." ), dirPage );
1130   setAboutInfo( targetBtn, tr( "Click this button to browse\nthe installation directory" ) );
1131   targetLayout->addMultiCellWidget( targetLab,    0, 0, 0, 1 );
1132   targetLayout->addWidget         ( targetFolder, 1,    0    );
1133   targetLayout->addWidget         ( targetBtn,    1,    1    );
1134   // temporary directory
1135   QGridLayout* tempLayout = new QGridLayout( 2, 2, 0 );
1136   QLabel* tempLab = new QLabel( tr( "Set a directory that should be used for temporary SALOME files:" ), dirPage );
1137   tempFolder = new QLineEdit( dirPage );
1138   tempBtn = new QPushButton( tr( "Browse..." ), dirPage );
1139   setAboutInfo( tempBtn, tr( "Click this button to browse\nthe temporary directory" ) );
1140   tempLayout->addMultiCellWidget( tempLab,    0, 0, 0, 1 );
1141   tempLayout->addWidget         ( tempFolder, 1,    0    );
1142   tempLayout->addWidget         ( tempBtn,    1,    1    );
1143   // AKL: 13/08/07 - disable temporary directory setting in GUI ==>
1144   tempLab->hide();
1145   tempFolder->hide();
1146   tempBtn->hide();
1147   // AKL: 13/08/07 - disable temporary directory setting in GUI <==
1148   // layout widgets
1149   pageLayout->addItem  ( spacer1,      0, 0 );
1150   pageLayout->addLayout( targetLayout, 1, 0 );
1151   pageLayout->addLayout( tempLayout,   2, 0 );
1152   pageLayout->addItem  ( spacer2,      3, 0 );
1153   // connecting signals
1154   connect( targetFolder,  SIGNAL( textChanged( const QString& ) ),
1155            this,          SLOT( directoryChanged( const QString& ) ) );
1156   connect( targetBtn,     SIGNAL( clicked() ), 
1157            this,          SLOT( browseDirectory() ) );
1158   connect( tempFolder,    SIGNAL( textChanged( const QString& ) ),
1159            this,          SLOT( directoryChanged( const QString& ) ) );
1160   connect( tempBtn,       SIGNAL( clicked() ), this, SLOT( browseDirectory() ) );
1161
1162   // adding page
1163   addPage( dirPage, tr( "Installation directory" ) );
1164 }
1165 // ================================================================
1166 /*!
1167  *  SALOME_InstallWizard::setupProductsPage
1168  *  Creates products page
1169  */
1170 // ================================================================
1171 void SALOME_InstallWizard::setupProductsPage()
1172 {
1173   // create page
1174   productsPage = new QWidget( this, "ProductsPage" );
1175   QGridLayout* pageLayout = new QGridLayout( productsPage );
1176   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1177   //
1178   // create left column widgets
1179   //
1180   QVBoxLayout* leftBoxLayout = new QVBoxLayout;
1181   leftBoxLayout->setMargin( 0 ); leftBoxLayout->setSpacing( 6 );
1182   // ... modules list
1183   modulesView = new ProductsView( productsPage, "modulesView" );
1184   setAboutInfo( modulesView, tr( "The modules available for the installation" ) );
1185   modulesView->setColumnAlignment( 1, Qt::AlignRight );
1186   leftBoxLayout->addWidget( modulesView );
1187   // ... 'Installation with GUI' checkbox
1188   installGuiBtn = new QMyCheckBox( tr( "Installation with GUI" ), productsPage );
1189   setAboutInfo( installGuiBtn, tr( "Check this option if you want\nto install SALOME with GUI" ) );
1190   leftBoxLayout->addWidget( installGuiBtn );
1191   // ... prerequisites list
1192   prereqsView = new ProductsView( productsPage, "prereqsView" );
1193   prereqsView->renameColumn( 0, "Prerequisite" );
1194   setAboutInfo( prereqsView, tr( "The prerequisites that can be installed" ) );
1195   prereqsView->setColumnAlignment( 1, Qt::AlignRight );
1196   leftBoxLayout->addWidget( prereqsView );
1197   // ... 'Show/Hide prerequisites' button
1198   moreBtn = new QPushButton( tr( "Show prerequisites..." ), productsPage );
1199   setAboutInfo( moreBtn, tr( "Click to show list of prerequisites" ) );
1200   leftBoxLayout->addWidget( moreBtn );
1201   //
1202   // create right column widgets
1203   //
1204   // ... info box
1205   productInfo = new QTextBrowser( productsPage );
1206   productInfo->setFrameShape( QFrame::LineEditPanel );
1207   productInfo->setPaletteBackgroundColor( productsPage->paletteBackgroundColor() );
1208   setAboutInfo( productInfo, tr( "Short information about the product being selected" ) );
1209   // ... disk space labels
1210   QLabel* reqLab1 = new QLabel( tr( "Disk space required:" ), productsPage );
1211   setAboutInfo( reqLab1, tr( "Total disk space required for the installation\nof the selected products" ) );
1212   requiredSize = new QLabel( productsPage );
1213   setAboutInfo( requiredSize, tr( "Total disk space required for the installation\nof the selected products" ) );
1214   requiredSize->setAlignment( Qt::AlignRight );
1215   QLabel* reqLab2 = new QLabel( tr( "Space for temporary files:" ), productsPage );
1216   setAboutInfo( reqLab2, tr( "Disk space required for the temporary files" ) );
1217   requiredTemp = new QLabel( productsPage );
1218   setAboutInfo( requiredTemp, tr( "Disk space required for the temporary files" ) );
1219   requiredTemp->setAlignment( Qt::AlignRight );
1220   QLabel* reqLab3 = new QLabel( tr( "Available disk space:" ), productsPage );
1221   setAboutInfo( reqLab3, tr( "Disk space available on the selected device" ) );
1222   availableSize = new QLabel( productsPage );
1223   setAboutInfo( availableSize, tr( "Disk space available on the selected device" ) );
1224   availableSize->setAlignment( Qt::AlignRight );
1225   // layout size widgets
1226   QGridLayout* sizeLayout = new QGridLayout; sizeLayout->setMargin( 0 ); sizeLayout->setSpacing( 6 );
1227   sizeLayout->addWidget( reqLab1,       0, 0 );
1228   sizeLayout->addWidget( requiredSize,  0, 1 );
1229   sizeLayout->addWidget( reqLab2,       1, 0 );
1230   sizeLayout->addWidget( requiredTemp,  1, 1 );
1231   sizeLayout->addWidget( reqLab3,       2, 0 );
1232   sizeLayout->addWidget( availableSize, 2, 1 );
1233   // ... 'single installation directory' check-boxes
1234   oneModDirBtn = new QMyCheckBox( tr( "Install modules to a single directory" ), productsPage );
1235   setAboutInfo( oneModDirBtn, tr( "Check this box if you want to install binaries of\nthe selected SALOME modules into a single directory" ) );
1236   oneProdDirBtn = new QMyCheckBox( tr( "Install prerequisites to a single directory" ), productsPage );
1237   setAboutInfo( oneProdDirBtn, tr( "Check this box if you want to install binaries of\nthe selected prerequisites into a single directory" ) );
1238   oneProdDirBtn->hide(); // temporarily! waiting for correct prerequisites availability
1239   QFrame* split_line = new QFrame( productsPage, "split_line" );
1240   split_line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
1241
1242   // layout common widgets
1243   pageLayout->addMultiCellLayout( leftBoxLayout, 0, 4, 0, 0 );
1244   pageLayout->addWidget         ( productInfo,   0,    1    );
1245   pageLayout->addLayout         ( sizeLayout,    1,    1    );
1246   pageLayout->addWidget         ( split_line,    2,    1    );
1247   pageLayout->addWidget         ( oneModDirBtn,  3,    1    );
1248   pageLayout->addWidget         ( oneProdDirBtn, 4,    1    );
1249
1250   // adding page
1251   addPage( productsPage, tr( "Choice of the products to be installed" ) );
1252
1253   // connecting signals
1254   connect( modulesView,   SIGNAL( selectionChanged() ),
1255            this, SLOT( onSelectionChanged() ) );
1256   connect( prereqsView,   SIGNAL( selectionChanged() ),
1257            this, SLOT( onSelectionChanged() ) );
1258   connect( modulesView,   SIGNAL( clicked ( QListViewItem * item ) ),
1259            this, SLOT( onSelectionChanged() ) );
1260   connect( prereqsView,   SIGNAL( clicked ( QListViewItem * item ) ),
1261            this, SLOT( onSelectionChanged() ) );
1262   connect( modulesView,   SIGNAL( itemToggled( QCheckListItem* ) ),
1263            this, SLOT( onItemToggled( QCheckListItem* ) ) );
1264   connect( prereqsView,   SIGNAL( itemToggled( QCheckListItem* ) ),
1265            this, SLOT( onItemToggled( QCheckListItem* ) ) );
1266   connect( installGuiBtn, SIGNAL( toggled( bool ) ), 
1267            this, SLOT( onInstallGuiBtn() ) );
1268   connect( moreBtn, SIGNAL( clicked() ), this, SLOT( onMoreBtn() ) );
1269   // start on default - non-advanced mode
1270   prereqsView->hide();
1271 }
1272 // ================================================================
1273 /*!
1274  *  SALOME_InstallWizard::setupCheckPage
1275  *  Creates prestart page
1276  */
1277 // ================================================================
1278 void SALOME_InstallWizard::setupCheckPage()
1279 {
1280   // create page
1281   prestartPage = new QWidget( this, "PrestartPage" );
1282   QVBoxLayout* pageLayout = new QVBoxLayout( prestartPage );
1283   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1284   // choice text view
1285   choices = new QTextEdit( prestartPage );
1286   choices->setReadOnly( true );
1287   choices->setTextFormat( RichText );
1288   choices->setUndoRedoEnabled ( false );
1289   setAboutInfo( choices, tr( "Information about the installation choice you have made" ) );
1290   choices->setPaletteBackgroundColor( prestartPage->paletteBackgroundColor() );
1291   choices->setMinimumHeight( 10 );
1292   // layouting
1293   pageLayout->addWidget( choices );
1294   pageLayout->setStretchFactor( choices, 5 );
1295   // adding page
1296   addPage( prestartPage, tr( "Check your choice" ) );
1297 }
1298 // ================================================================
1299 /*!
1300  *  SALOME_InstallWizard::setupProgressPage
1301  *  Creates progress page
1302  */
1303 // ================================================================
1304 void SALOME_InstallWizard::setupProgressPage()
1305 {
1306   // create page
1307   progressPage = new QWidget( this, "progressPage" );
1308   QGridLayout* pageLayout = new QGridLayout( progressPage );
1309   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1310   // top splitter
1311   splitter = new QSplitter( Vertical, progressPage );
1312   splitter->setOpaqueResize( true );
1313   // the parent for the widgets
1314   QWidget* widget = new QWidget( splitter );
1315   QGridLayout* layout = new QGridLayout( widget );
1316   layout->setMargin( 0 ); layout->setSpacing( 6 );
1317   // installation progress view box
1318   installInfo = new InstallInfo( widget );
1319   installInfo->setReadOnly( true );
1320   installInfo->setTextFormat( RichText );
1321   installInfo->setUndoRedoEnabled ( false );
1322   installInfo->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
1323   installInfo->setMinimumSize( 100, 10 );
1324   setAboutInfo( installInfo, tr( "Installation process output" ) );
1325   // parameters for the script
1326   parametersLab = new QLabel( tr( "Enter your answer here:" ), widget );
1327   passedParams = new QLineEdit ( widget );
1328   setAboutInfo( passedParams, tr( "Use this field to enter the answer\nfor the running script when it is necessary") );
1329   // VSR: 10/11/05 - disable answer mode ==>
1330   parametersLab->hide();
1331   passedParams->hide();
1332   // VSR: 10/11/05 - disable answer mode <==
1333   // layouting
1334   layout->addWidget( installInfo,   0, 0 );
1335   layout->addWidget( parametersLab, 1, 0 );
1336   layout->addWidget( passedParams,  2, 0 );
1337   layout->addRowSpacing( 3, 6 );
1338   // the parent for the widgets
1339   widget = new QWidget( splitter );
1340   layout = new QGridLayout( widget );
1341   layout->setMargin( 0 ); layout->setSpacing( 6 );
1342   // installation results view box
1343   QLabel* resultLab = new QLabel( tr( "Installation Status:" ), widget );
1344   progressView = new ProgressView( widget );
1345   progressView->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
1346   progressView->setMinimumSize( 100, 10 );
1347   statusLab = new QLabel( widget );
1348   statusLab->setFrameShape( QButtonGroup::LineEditPanel );
1349   setAboutInfo( progressView, tr( "Installation status on the selected products" ) );
1350   // layouting
1351   layout->addRowSpacing( 0, 6 );
1352   layout->addWidget( resultLab,    1, 0 );
1353   layout->addWidget( progressView, 2, 0 );
1354   layout->addWidget( statusLab,    3, 0 );
1355   // layouting
1356   pageLayout->addWidget( splitter,  0, 0 );
1357   // adding page
1358   addPage( progressPage, tr( "Installation progress" ) );
1359   // connect signals
1360   connect( passedParams, SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) ) ;
1361 }
1362 // ================================================================
1363 /*!
1364  *  SALOME_InstallWizard::setupReadmePage
1365  *  Creates readme page
1366  */
1367 // ================================================================
1368 void SALOME_InstallWizard::setupReadmePage()
1369 {
1370   // create page
1371   readmePage = new QWidget( this, "readmePage" );
1372   QVBoxLayout* pageLayout = new QVBoxLayout( readmePage );
1373   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1374   // README info text box
1375   readme = new QTextEdit( readmePage );
1376   readme->setReadOnly( true );
1377   readme->setTextFormat( PlainText );
1378   readme->setFont( QFont( "Fixed", 12 ) );
1379   readme->setUndoRedoEnabled ( false );
1380   setAboutInfo( readme, tr( "README information" ) );
1381   readme->setPaletteBackgroundColor( readmePage->paletteBackgroundColor() );
1382   readme->setMinimumHeight( 10 );
1383
1384   pageLayout->addWidget( readme );
1385   pageLayout->setStretchFactor( readme, 5 );
1386
1387   // Operation buttons
1388   QHBoxLayout* hLayout = new QHBoxLayout( -1, "finishButtons" );
1389   hLayout->setMargin( 0 ); hLayout->setSpacing( 6 );
1390   hLayout->addStretch();
1391   pageLayout->addLayout( hLayout );
1392
1393   // loading README file
1394   QString readmeFile = QDir( rootDirPath() ).filePath( "README" );
1395   QString text;
1396   if ( readFile( readmeFile, text ) )
1397     readme->setText( text );
1398   else
1399     readme->setText( tr( "README file has not been found" ) );
1400
1401   // adding page
1402   addPage( readmePage, tr( "Finish installation" ) );
1403 }
1404 // ================================================================
1405 /*!
1406  *  SALOME_InstallWizard::showChoiceInfo
1407  *  Displays choice info
1408  */
1409 // ================================================================
1410 void SALOME_InstallWizard::showChoiceInfo()
1411 {
1412   choices->clear();
1413
1414   long totSize, tempSize;
1415   checkSize( &totSize, &tempSize );
1416   int nbProd = 0;
1417   QString text;
1418
1419   text += tr( "Current Linux platform" )+ ": <b>" + (!curPlatform.isEmpty() ? curPlatform : QString( "Unknown" )) + "</b><br>";
1420   if ( !refPlatform.isEmpty() )
1421     text += tr( "Reference Linux platform" ) + ": <b>" + refPlatform + "</b><br>";
1422   text += "<br>";
1423
1424   text += tr( "Target directory:" ) + " <b>" + QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) + "</b><br>";
1425   text += tr( "Temporary directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
1426   text += "<br>";
1427
1428   text += tr( "SALOME modules to be installed" ) + ":<ul>";
1429   QCheckListItem* item = (QCheckListItem*)( modulesView->firstChild() );
1430   while( item ) {
1431     if ( productsMap.contains( item ) ) {
1432       if ( item->isOn() ) {
1433         text += "<li><b>" + item->text() + "</b><br>";
1434         nbProd++;
1435       }
1436     }
1437     item = (QCheckListItem*)( item->nextSibling() );
1438   }
1439   if ( nbProd == 0 ) {
1440     text += "<li><b>" + tr( "none" ) + "</b><br>";
1441   }
1442   text += "</ul>";
1443   nbProd = 0;
1444   text += tr( "Prerequisites to be installed" ) + ":<ul>";
1445   item = (QCheckListItem*)( prereqsView->firstChild() );
1446   while( item ) {
1447     if ( productsMap.contains( item ) ) {
1448       if ( item->isOn() ) {
1449         text += "<li><b>" + item->text() + " " + productsMap[ item ].getVersion() + "</b><br>";
1450         nbProd++;
1451       }
1452     }
1453     item = (QCheckListItem*)( item->nextSibling() );
1454   }
1455   if ( nbProd == 0 ) {
1456     text += "<li><b>" + tr( "none" ) + "</b><br>";
1457   }
1458   text += "</ul>";
1459   text += tr( "Total disk space required:" ) + " <b>" + QString::number( totSize ) + " KB</b><br>" ;
1460   text += tr( "Space for temporary files required:" ) + " <b>" + QString::number( tempSize ) + " KB</b><br>" ;
1461   choices->setText( text );
1462 }
1463 // ================================================================
1464 /*!
1465  *  SALOME_InstallWizard::acceptData
1466  *  Validates page when <Next> button is clicked
1467  */
1468 // ================================================================
1469 bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
1470 {
1471   QString tmpstr;
1472   QWidget* aPage = InstallWizard::page( pageTitle );
1473   if ( aPage == typePage ) {
1474     // installation type page
1475     warnLab3->show();
1476     this->setAppropriate( platformsPage, false );
1477     if ( installType == Binaries ) { // 'Binary' installation type
1478       // check binaries directory
1479       QFileInfo fib( QDir::cleanDirPath( getBinPath() ) );
1480       if ( !fib.isDir() ) {
1481         QMessageBox::warning( this,
1482                               tr( "Warning" ),
1483                               tr( "The directory %1 doesn't exist.\n"
1484                                   "This directory must contains another one directory with binary archives for current platform.").arg( fib.absFilePath() ),
1485                               QMessageBox::Ok,
1486                               QMessageBox::NoButton, 
1487                               QMessageBox::NoButton );
1488         return false;
1489       }
1490       if ( platformsMap.find( curPlatform ) == platformsMap.end() ) {
1491         // Unknown platform case
1492         QString aMsg = warnMsg + tr( ".\nBy default the universal binary package will be installed." );
1493         aMsg += tr( "\nIf you want to select another one, please use the following list:" );
1494         warnLab->setText( aMsg );
1495         warnLab3->hide();
1496         this->setAppropriate( platformsPage, true );
1497       }
1498       else {
1499         // Supported platform case
1500         QFileInfo fibp( getPlatformBinPath( curPlatform ) );
1501         if ( !fibp.isDir() ) {
1502           warnLab->setText( tr( "Binaries are absent for current platform." ) );
1503           this->setAppropriate( platformsPage, true );
1504         }
1505       }
1506
1507       // check sources directory
1508       QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
1509       if ( !fis.isDir() )
1510         if ( QMessageBox::warning( this,
1511                                    tr( "Warning" ),
1512                                    tr( "The directory %1 doesn't exist.\n"
1513                                        "This directory must contains sources archives.\n"
1514                                        "Continue?" ).arg( fis.absFilePath() ),
1515                                    tr( "&Yes" ),
1516                                    tr( "&No" ), 
1517                                    QString::null, 1, 1 ) == 1 )
1518           return false;
1519     }
1520     else { // 'Source' or 'Compile' installation type
1521       // check sources directory
1522       QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
1523       if ( !fis.isDir() ) {
1524         QMessageBox::warning( this,
1525                               tr( "Warning" ),
1526                               tr( "The directory %1 doesn't exist.\n"
1527                                   "This directory must contains sources archives.\n" ).arg( fis.absFilePath() ),
1528                               QMessageBox::Ok,
1529                               QMessageBox::NoButton, 
1530                               QMessageBox::NoButton );
1531         return false;
1532       }
1533       else if ( !QDir( fis.filePath(), "*.tar.gz" ).count() ) {
1534         QMessageBox::warning( this,
1535                               tr( "Warning" ),
1536                               tr( "The directory %1 doesn't contain source archives.\n" ).arg( fis.absFilePath() ),
1537                               QMessageBox::Ok,
1538                               QMessageBox::NoButton, 
1539                               QMessageBox::NoButton );
1540         return false;
1541       }
1542       if ( platformsMap.find( curPlatform ) == platformsMap.end() ) {
1543         QString aMsg = warnMsg + ".";
1544         if ( installType == Compile )
1545           aMsg = warnMsg + tr( " and compilation is not tested on this one." );
1546         warnLab->setText( aMsg );
1547         this->setAppropriate( platformsPage, true );
1548       }
1549     }
1550   }
1551
1552   else if ( aPage == platformsPage ) {
1553     // installation platform page
1554     if ( platBtnGrp->id( platBtnGrp->selected() ) == -1 ) {
1555       QMessageBox::warning( this,
1556                             tr( "Warning" ),
1557                             tr( "Select installation platform before" ),
1558                             QMessageBox::Ok,
1559                             QMessageBox::NoButton,
1560                             QMessageBox::NoButton );
1561       return false;
1562     }
1563     else if ( installType == Binaries ) {
1564       QString aPlatform = platBtnGrp->selected()->name();
1565       QFileInfo fib( getPlatformBinPath( aPlatform ) );
1566       if ( !fib.isDir() ) {
1567         QMessageBox::warning( this,
1568                               tr( "Warning" ),
1569                               tr( "The directory %1 doesn't exist.\n"
1570                                   "This directory must contains binary archives.\n" ).arg( fib.absFilePath() ),
1571                               QMessageBox::Ok,
1572                               QMessageBox::NoButton, 
1573                               QMessageBox::NoButton );
1574         return false;
1575       }
1576       else if ( QDir( fib.filePath(), "*.tar.gz" ).count() == 0 ) {
1577         QMessageBox::warning( this,
1578                               tr( "Warning" ),
1579                               tr( "The directory %1 doesn't contain binary archives.\n" ).arg( fib.absFilePath() ),
1580                               QMessageBox::Ok,
1581                               QMessageBox::NoButton, 
1582                               QMessageBox::NoButton );
1583         return false;
1584       }
1585     }
1586   }
1587
1588   else if ( aPage == dirPage ) {
1589     // installation directory page
1590     // ########## check target and temp directories (existence and available disk space)
1591     // get dirs
1592     QString targetDir = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1593     QString tempDir   = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() );
1594     // check target directory
1595     if ( targetDir.isEmpty() ) {
1596       QMessageBox::warning( this,
1597                             tr( "Warning" ),
1598                             tr( "Please, enter valid target directory path" ),
1599                             QMessageBox::Ok,
1600                             QMessageBox::NoButton,
1601                             QMessageBox::NoButton );
1602       return false;
1603     }
1604     QFileInfo fi( QDir::cleanDirPath( targetDir ) );
1605     if ( !fi.isDir() ) {
1606       bool toCreate =
1607         QMessageBox::warning( this,
1608                               tr( "Warning" ),
1609                               tr( "The directory %1 doesn't exist.\n"
1610                                   "Create directory?" ).arg( fi.absFilePath() ),
1611                               QMessageBox::Yes,
1612                               QMessageBox::No,
1613                               QMessageBox::NoButton ) == QMessageBox::Yes;
1614       if ( !toCreate)
1615         return false;
1616       if ( !makeDir( fi.absFilePath(), tmpstr ) ) {
1617         QMessageBox::critical( this,
1618                                tr( "Error" ),
1619                                tr( "Can't create the directory\n%1").arg( fi.absFilePath() ),
1620                                QMessageBox::Ok,
1621                                QMessageBox::NoButton,
1622                                QMessageBox::NoButton );
1623         return false;
1624       }
1625     }
1626     if ( !fi.isDir() ) {
1627       QMessageBox::warning( this,
1628                             tr( "Warning" ),
1629                             tr( "%1 is not a directory.\n"
1630                                 "Please, enter valid target directory path" ).arg( fi.absFilePath() ),
1631                             QMessageBox::Ok,
1632                             QMessageBox::NoButton,
1633                             QMessageBox::NoButton );
1634       return false;
1635     }
1636     if ( !fi.isWritable() ) {
1637       QMessageBox::warning( this,
1638                             tr( "Warning" ),
1639                             tr( "The directory %1 is not writable.\n"
1640                                 "Please, enter valid target directory path or change permissions" ).arg( fi.absFilePath() ),
1641                             QMessageBox::Ok,
1642                             QMessageBox::NoButton,
1643                             QMessageBox::NoButton );
1644       return false;
1645     }
1646     if ( hasSpace( fi.absFilePath() ) &&
1647          QMessageBox::warning( this,
1648                                tr( "Warning" ),
1649                                tr( "The target directory contains space symbols.\n"
1650                                    "This may cause problems with compiling or installing of products.\n\n"
1651                                    "Do you want to continue?"),
1652                                QMessageBox::Yes,
1653                                QMessageBox::No,
1654                                QMessageBox::NoButton ) == QMessageBox::No ) {
1655       return false;
1656     }
1657     // check temp directory
1658     if ( tempDir.isEmpty() ) {
1659       QMessageBox::warning( this,
1660                             tr( "Warning" ),
1661                             tr( "Please, enter valid temporary directory path" ),
1662                             QMessageBox::Ok,
1663                             QMessageBox::NoButton,
1664                             QMessageBox::NoButton );
1665       return false;
1666     }
1667     QFileInfo fit( QDir::cleanDirPath( tempDir ) );
1668     if ( !makeDir( fit.absFilePath() + TEMPDIRNAME, tmpCreated ) ) {
1669       QMessageBox::critical( this,
1670                              tr( "Error" ),
1671                              tr( "Can't use temporary directory.\nCheck permissions for the %1 directory.").arg( fit.absFilePath() ),
1672                              QMessageBox::Ok,
1673                              QMessageBox::NoButton,
1674                              QMessageBox::NoButton );
1675       return false;
1676     }
1677   }
1678
1679   else if ( aPage == productsPage ) {
1680     // products page
1681     // ########## check if any products are selected to be installed
1682     long totSize, tempSize;
1683     bool anySelected = checkSize( &totSize, &tempSize );
1684     if ( installType == Compile && removeSrcBtn->isOn() ) {
1685       totSize += tempSize;
1686     }
1687     if ( !anySelected ) {
1688       QMessageBox::warning( this,
1689                             tr( "Warning" ),
1690                             tr( "Select one or more products to install" ),
1691                             QMessageBox::Ok,
1692                             QMessageBox::NoButton,
1693                             QMessageBox::NoButton );
1694       return false;
1695     }
1696     // run script that checks available disk space for installing of products    // returns 1 in case of error
1697     QDir rd( rootDirPath() );
1698     QFileInfo fi( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) );
1699     Script script;
1700     script << QUOTE( rd.filePath( "config_files/checkSize.sh" ) );
1701     script << QUOTE( fi.absFilePath() ) << QString::number( totSize );
1702     ___MESSAGE___( "script = " << script.script().latin1() );
1703     if ( system( script.script().latin1() ) ) {
1704       QMessageBox::critical( this,
1705                              tr( "Out of space" ),
1706                              tr( "There is no available disk space for installing of selected products" ),
1707                              QMessageBox::Ok,
1708                              QMessageBox::NoButton,
1709                              QMessageBox::NoButton );
1710       return false;
1711     }
1712     // AKL: 13/08/07 - skip tmp disk space checking (all files are unpacked into installation directory) ==>
1713     /*
1714     // run script that check available disk space for temporary files
1715     // returns 1 in case of error
1716     QFileInfo fit( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) );
1717     Script tscript;
1718     tscript << QUOTE( rd.filePath( "config_files/checkSize.sh" ) );
1719     tscript << QUOTE( fit.absFilePath() ) << QString::number( tempSize );
1720     ___MESSAGE___( "script = " << tscript.script().latin1() );
1721     if ( system( tscript.script().latin1() ) ) {
1722       QMessageBox::critical( this,
1723                              tr( "Out of space" ),
1724                              tr( "There is no available disk space for the temporary files" ),
1725                              QMessageBox::Ok,
1726                              QMessageBox::NoButton,
1727                              QMessageBox::NoButton );
1728       return false;
1729       }
1730     */
1731     // AKL: 13/08/07 - skip tmp disk space checking (all files are unpacked into installation directory) <==
1732
1733     // ########## check installation scripts
1734     QCheckListItem* item;
1735     ProductsView* prodsView = modulesView;
1736     for ( int i = 0; i < 2; i++ ) {
1737       item = (QCheckListItem*)( prodsView->firstChild() );
1738       while( item ) {
1739         if ( productsMap.contains( item ) && item->isOn() ) {
1740           // check installation script definition
1741           if ( item->text(2).isEmpty() || item->text(2).isNull() ) {
1742             QMessageBox::warning( this,
1743                                   tr( "Error" ),
1744                                   tr( "The installation script for %1 is not defined.").arg(item->text(0)),
1745                                   QMessageBox::Ok,
1746                                   QMessageBox::NoButton,
1747                                   QMessageBox::NoButton );
1748             if ( !moreMode ) onMoreBtn();
1749             QListView* listView = item->listView();
1750             listView->setCurrentItem( item );
1751             listView->setSelected( item, true );
1752             listView->ensureItemVisible( item );
1753             return false;
1754           }
1755           // check installation script existence
1756           else {
1757             QDir rd( rootDirPath() );
1758             QFileInfo fi( rd.filePath( QString( "config_files/%1" ).arg( item->text(2) ) ) );
1759             if ( !fi.exists() || !fi.isExecutable() ) {
1760               QMessageBox::warning( this,
1761                                     tr( "Error" ),
1762                                     tr( "The script %1 required for %2 doesn't exist or doesn't have execute permissions.").arg(fi.filePath()).arg(item->text(0)),
1763                                     QMessageBox::Ok,
1764                                     QMessageBox::NoButton,
1765                                     QMessageBox::NoButton );
1766               if ( !moreMode ) onMoreBtn();
1767               QListView* listView = item->listView();
1768               listView->setCurrentItem( item );
1769               listView->setSelected( item, true );
1770               listView->ensureItemVisible( item );
1771               return false;
1772             }
1773           }
1774           // check installation scripts dependencies
1775           QStringList dependOn = productsMap[ item ].getDependancies();
1776           QString version = productsMap[ item ].getVersion();
1777           for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1778             QCheckListItem* depitem = findItem( dependOn[ i ] );
1779             if ( !depitem ) {
1780               QMessageBox::warning( this,
1781                                     tr( "Error" ),
1782                                     tr( "%1 is required for %2 %3 installation.\n"
1783                                         "This product is missing in the configuration file %4.").arg(dependOn[ i ]).arg(item->text(0)).arg(version).arg(xmlFileName),
1784                                     QMessageBox::Ok,
1785                                     QMessageBox::NoButton,
1786                                     QMessageBox::NoButton );
1787               return false;
1788             }
1789           }
1790         }
1791         item = (QCheckListItem*)( item->nextSibling() );
1792       }
1793       prodsView = prereqsView;
1794     }
1795 //     return true; // return in order to avoid default postValidateEvent() action
1796   }
1797   return InstallWizard::acceptData( pageTitle );
1798 }
1799 // ================================================================
1800 /*!
1801  *  SALOME_InstallWizard::checkSize
1802  *  Calculates disk space required for the installation
1803  */
1804 // ================================================================
1805 bool SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
1806 {
1807   long tots = 0, temps = 0;
1808   long maxSrcTmp = 0;
1809   int nbSelected = 0;
1810
1811   MapProducts::Iterator mapIter;
1812   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1813     QCheckListItem* item = mapIter.key();
1814     Dependancies dep = mapIter.data();
1815     if ( !item->isOn() )
1816       continue;
1817     tots += ( QStringList::split( " ", item->text(1) )[0] ).toLong();
1818     maxSrcTmp = max( maxSrcTmp, dep.getSize( Compile ) - dep.getSize( Binaries ) );
1819     temps += dep.getTempSize( installType );
1820     nbSelected++;
1821   }
1822
1823   if ( totSize )
1824     if ( installType == Compile && removeSrcBtn->isOn() )
1825       temps += maxSrcTmp;
1826     *totSize = tots;
1827   if ( tempSize )
1828     *tempSize = temps;
1829   return ( nbSelected > 0 );
1830 }
1831 // ================================================================
1832 /*!
1833  *  SALOME_InstallWizard::updateAvailableSpace
1834  *  Slot to update 'Available disk space' field
1835  */
1836 // ================================================================
1837 void SALOME_InstallWizard::updateAvailableSpace()
1838 {
1839   if ( diskSpaceProc->normalExit() )
1840     availableSize->setText( diskSpaceProc->readLineStdout() + " KB");
1841 }
1842 // ================================================================
1843 /*!
1844  *  SALOME_InstallWizard::runModifyLaFiles
1845  *  Run the modification of SALOME *.la files
1846  */
1847 // ================================================================
1848 void SALOME_InstallWizard::runModifyLaFiles()
1849 {
1850   modifyLaProc->clearArguments();
1851   // ... update status label
1852   statusLab->setText( tr( "Modification of *.la files of SALOME modules..." ) );
1853   // set process arguments
1854   modifyLaProc->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
1855   modifyLaProc->addArgument( "modifyLaFiles.sh" );
1856   modifyLaProc->addArgument( "modify_la_files" );
1857   modifyLaProc->addArgument( QDir::cleanDirPath( QFileInfo( targetFolder->text().stripWhiteSpace() ).absFilePath() ) );
1858   // ... run script
1859   if ( !modifyLaProc->start() )
1860     ___MESSAGE___( "Error: process could not start!" );
1861 }
1862 // ================================================================
1863 /*!
1864  *  SALOME_InstallWizard::checkModifyLaResult
1865  *  Slot to take result of modification SALOME *.la files
1866  */
1867 // ================================================================
1868 void SALOME_InstallWizard::checkModifyLaResult()
1869 {
1870   if ( modifyLaProc->normalExit() && modifyLaProc->exitStatus() == 1 )
1871     runCheckFLib();
1872   else {
1873     // abort of the current installation
1874     abort();
1875     statusLab->setText( tr( "Installation has been aborted" ) );
1876     QMessageBox::critical( this,
1877                            tr( "Error" ),
1878                            tr( "Modification of *.la SALOME files has not been completed."),
1879                            QMessageBox::Ok,
1880                            QMessageBox::NoButton,
1881                            QMessageBox::NoButton );
1882     // enable <Next> button
1883     setNextEnabled( true );
1884     nextButton()->setText( tr( "&Start" ) );
1885     setAboutInfo( nextButton(), tr( "Start installation process" ) );
1886     // reconnect Next button - to use it as Start button
1887     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1888     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1889     connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1890     // enable <Back> button
1891     setBackEnabled( true );
1892   }
1893 }
1894 // ================================================================
1895 /*!
1896  *  SALOME_InstallWizard::runCheckFLib
1897  *  Run the Fortran libraries checking
1898  */
1899 // ================================================================
1900 void SALOME_InstallWizard::runCheckFLib()
1901 {
1902   // Check Fortran libraries
1903   checkFLibProc->clearArguments();
1904   // ... update status label
1905   statusLab->setText( tr( "Check Fortran libraries..." ) );
1906   // ... search "not found" libraries
1907   checkFLibProc->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
1908   checkFLibProc->addArgument( "checkFortran.sh" );
1909   checkFLibProc->addArgument( "find_libraries" );
1910   checkFLibProc->addArgument( QDir::cleanDirPath( QFileInfo( targetFolder->text().stripWhiteSpace() ).absFilePath() ) );
1911   // ... run script
1912   if ( !checkFLibProc->start() )
1913     ___MESSAGE___( "Error: process could not start!" );
1914 }
1915 // ================================================================
1916 /*!
1917  *  SALOME_InstallWizard::checkFLibResult
1918  *  Slot to take result of Fortran libraries checking
1919  */
1920 // ================================================================
1921 void SALOME_InstallWizard::checkFLibResult()
1922 {
1923   if ( checkFLibProc->normalExit() && checkFLibProc->exitStatus() == 1 ) {
1924     QStringList notFoundLibsList;
1925     QString record = "";
1926     while ( checkFLibProc->canReadLineStdout() ) {
1927       record = checkFLibProc->readLineStdout();
1928       if ( !record.isEmpty() && !notFoundLibsList.contains( record ) )
1929         notFoundLibsList.append( record );
1930     }
1931     QMessageBox::warning( this,
1932                           tr( "Warning" ),
1933                           tr( "The following libraries are absent on current system:\n"
1934                           "%1").arg( notFoundLibsList.join( "\n" ) ),
1935                           QMessageBox::Ok,
1936                           QMessageBox::NoButton,
1937                           QMessageBox::NoButton );
1938   }
1939   // Update GUI and check installation errors
1940   completeInstallation();
1941 }
1942 // ================================================================
1943 /*!
1944  *  SALOME_InstallWizard::updateSizeColumn
1945  *  Sets required size for each product according to 
1946  *  installation type and 'Remove SRC & TMP' checkbox state
1947  */
1948 // ================================================================
1949 void SALOME_InstallWizard::updateSizeColumn()
1950 {
1951   long prodSize = 0;
1952   bool removeSrc = removeSrcBtn->isChecked();
1953   MapProducts::Iterator mapIter;
1954   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1955     QCheckListItem* item = mapIter.key();
1956     Dependancies dep = mapIter.data();
1957     // get required size for current product
1958     long binSize = dep.getSize( Binaries );
1959     long srcSize = dep.getSize( Sources );
1960     long bldSize = dep.getSize( Compile );
1961     InstallationType instType = getInstType();
1962     if ( instType == Binaries ) {
1963       if ( dep.getType() == "component" )
1964         prodSize = binSize + srcSize;
1965       else
1966         prodSize = ( binSize != 0 ? binSize : srcSize );
1967     }
1968     else if ( instType == Sources )
1969       prodSize = srcSize;
1970     else
1971       if ( removeSrc )
1972         prodSize = ( binSize != 0 ? binSize : srcSize );
1973       else {
1974         prodSize = ( bldSize != 0 ? bldSize : srcSize );
1975       }
1976     // fill in 'Size' field
1977     item->setText( 1, QString::number( prodSize )+" KB" );
1978   }
1979 }
1980 // ================================================================
1981 /*!
1982  *  SALOME_InstallWizard::checkProductPage
1983  *  Checks products page validity (directories and products selection) and
1984  *  enabled/disables "Next" button for the Products page
1985  */
1986 // ================================================================
1987 void SALOME_InstallWizard::checkProductPage()
1988 {
1989   if ( this->currentPage() != productsPage )
1990     return;
1991   long tots = 0, temps = 0;
1992   // check if any product is selected;
1993   bool isAnyProductSelected = checkSize( &tots, &temps );
1994
1995   // update required size information
1996   requiredSize->setText( QString::number( tots )  + " KB");
1997   requiredTemp->setText( QString::number( temps ) + " KB");
1998
1999   // update available size information
2000   QFileInfo fi( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) );
2001   if ( fi.exists() ) {
2002     diskSpaceProc->clearArguments();
2003     diskSpaceProc->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
2004     diskSpaceProc->addArgument( "diskSpace.sh" );
2005     diskSpaceProc->addArgument( fi.absFilePath() );
2006     // run script
2007     diskSpaceProc->start();
2008   }
2009
2010   // enable/disable "Next" button
2011   setNextEnabled( productsPage, isAnyProductSelected );
2012 }
2013 // ================================================================
2014 /*!
2015  *  SALOME_InstallWizard::setPrerequisites
2016  *  Sets the product and all products this one depends on to be checked ( recursively )
2017  */
2018 // ================================================================
2019 void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
2020 {
2021   if ( !productsMap.contains( item ) )
2022     return;
2023   if ( !item->isOn() )
2024     return;
2025   // get all prerequisites
2026   QStringList dependOn = productsMap[ item ].getDependancies();
2027   // install SALOME without GUI case
2028   if ( installGuiBtn->state() != QButton::On && 
2029        woGuiModules.find( item->text(0) ) != woGuiModules.end() && 
2030        woGuiModules[item->text(0)] == True ) {
2031     dependOn.remove( "GUI" );
2032   }
2033   // setting prerequisites
2034   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
2035     MapProducts::Iterator itProd;
2036     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2037       if ( itProd.data().getName() == dependOn[ i ] ) {
2038         if ( itProd.data().getType() == "component" && !itProd.key()->isOn() )
2039           itProd.key()->setOn( true );
2040         else if ( itProd.data().getType() == "prerequisite" ) {
2041           itProd.key()->setOn( true );
2042           itProd.key()->setEnabled( false );
2043         }
2044         break;
2045       }
2046     }
2047   }
2048 }
2049 // ================================================================
2050 /*!
2051  *  SALOME_InstallWizard::unsetPrerequisites
2052  *  Unsets all modules which depend of the unchecked product ( recursively )
2053  */
2054 // ================================================================
2055 void SALOME_InstallWizard::unsetPrerequisites( QCheckListItem* item )
2056 {
2057   if ( !productsMap.contains( item ) )
2058     return;
2059   if ( item->isOn() )
2060     return;
2061
2062 // uncheck dependent products
2063   QString itemName = productsMap[ item ].getName();
2064   MapProducts::Iterator itProd;
2065   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2066     if ( itProd.data().getType() == productsMap[ item ].getType() ) {
2067       QStringList dependOn = itProd.data().getDependancies();
2068       for ( int i = 0; i < (int)dependOn.count(); i++ ) {
2069         if ( dependOn[ i ] == itemName ) {
2070           if ( itProd.key()->isOn() ) {
2071             itProd.key()->setOn( false );
2072           }
2073         }
2074       }
2075     }
2076   }
2077
2078 // uncheck prerequisites
2079   int nbDependents;
2080 //   cout << "item name = " << productsMap[ item ].getName() << endl;
2081   QStringList dependOnList = productsMap[ item ].getDependancies();
2082   for ( int j = 0; j < (int)dependOnList.count(); j++ ) {
2083     nbDependents = 0;
2084     MapProducts::Iterator itProd1;
2085     for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
2086       if ( itProd1.data().getName() == dependOnList[ j ] ) {
2087         if ( itProd1.data().getType() == "prerequisite" ) {
2088           MapProducts::Iterator itProd2;
2089           for ( itProd2 = productsMap.begin(); itProd2 != productsMap.end(); ++itProd2 ) {
2090             if ( itProd2.key()->isOn() ) {
2091               QStringList prereqsList = productsMap[ itProd2.key() ].getDependancies();
2092               for ( int k = 0; k < (int)prereqsList.count(); k++ ) {
2093                 if ( prereqsList[ k ] == itProd1.data().getName() ) {
2094                   nbDependents++;
2095                   break;
2096                 }
2097               }
2098             }
2099           }
2100           if ( nbDependents == 0 ) {
2101             itProd1.key()->setEnabled( true );
2102             itProd1.key()->setOn( false );
2103           }
2104         }
2105         break;
2106       }
2107     }
2108   }
2109 }
2110 // ================================================================
2111 /*!
2112  *  SALOME_InstallWizard::launchScript
2113  *  Runs installation script
2114  */
2115 // ================================================================
2116 void SALOME_InstallWizard::launchScript()
2117 {
2118   // try to find product being processed now
2119   QString prodProc = progressView->findStatus( Processing );
2120   if ( !prodProc.isNull() ) {
2121     ___MESSAGE___( "Found <Processing>: " );
2122
2123     // if found - set status to "completed"
2124     progressView->setStatus( prodProc, Completed );
2125     // ... clear status label
2126     statusLab->clear();
2127     // ... and call this method again
2128     launchScript();
2129     return;
2130   }
2131   // else try to find next product which is not processed yet
2132   prodProc = progressView->findStatus( Waiting );
2133   if ( !prodProc.isNull() ) {
2134     ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
2135     // if found - set status to "processed" and run script
2136     progressView->setStatus( prodProc, Processing );
2137     progressView->ensureVisible( prodProc );
2138     
2139     QCheckListItem* item = 0;
2140     // fill in script parameters
2141     shellProcess->clearArguments();
2142     // ... script name
2143     shellProcess->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
2144     if ( !extraProducts.contains( prodProc ) ) {
2145       item = findItem( prodProc );
2146       shellProcess->addArgument( item->text(2) );
2147     }
2148     else
2149       shellProcess->addArgument( extraProducts[ prodProc ] );
2150
2151     // ... get folder with binaries
2152     QString OS = getPlatform();
2153     if ( refPlatform.isEmpty() && platformsMap.find( curPlatform ) == platformsMap.end() )
2154       OS = commonPlatform;
2155     QString binDir = getPlatformBinPath( OS );
2156     // ... temp folder
2157     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
2158     //if( !tempFolder->isEnabled() )
2159     //  tmpFolder = "/tmp";
2160
2161     // ... not install : try to find preinstalled
2162     if ( notInstall.contains( prodProc ) || prodProc == "gcc" ) {
2163       shellProcess->addArgument( "try_preinstalled" );
2164       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
2165       shellProcess->addArgument( QDir( rootDirPath() ).filePath( "Products" ) );
2166       statusLab->setText( tr( "Collecting environment for '" ) + prodProc + "'..." );
2167     }
2168     // ... binaries ?
2169     else if ( installType == Binaries ) {
2170       shellProcess->addArgument( "install_binary" );
2171       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
2172       shellProcess->addArgument( binDir );
2173       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
2174     }
2175     // ... sources or sources_and_compilation ?
2176     else {
2177       shellProcess->addArgument( installType == Sources ? "install_source" : 
2178                                  "install_source_and_build" );
2179       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
2180       shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
2181       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
2182     }
2183     // ... target folder
2184     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
2185     shellProcess->addArgument( QFileInfo( tgtFolder ).absFilePath() );
2186     // ... list of all products
2187     QString depproducts = getAllProducts(productsMap);
2188     depproducts.prepend( QStringList( extraProducts.keys() ).join(" ") + " " );
2189     ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
2190     shellProcess->addArgument( depproducts );
2191     // ... product name - currently installed product
2192     if ( !extraProducts.contains( prodProc ) )
2193       shellProcess->addArgument( item->text(0) );
2194     else
2195       shellProcess->addArgument( prodProc );
2196     // ... list of products being installed
2197     shellProcess->addArgument( prodSequence.join( " " ) );
2198     // ... sources directory
2199     shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
2200     // ... remove sources and tmp files or not?
2201     if ( installType == Compile && removeSrcBtn->isOn() )
2202       shellProcess->addArgument( "TRUE" );
2203     else 
2204       shellProcess->addArgument( "FALSE" );
2205     // ... binaries directory
2206     shellProcess->addArgument( binDir );
2207     // ... install SALOME with GUI or not?
2208     if ( woGuiModules.find( prodProc ) != woGuiModules.end() )
2209       ( installGuiBtn->state() != QButton::On && woGuiModules[ prodProc ] == True ) ? 
2210         shellProcess->addArgument( "FALSE" ) : 
2211         shellProcess->addArgument( "TRUE" );
2212     // ... single installation directory for SALOME modules, if this option was selected
2213     if ( oneModDirBtn->isChecked() ) {
2214       MapProducts::Iterator mapIter;
2215       for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter )
2216         if ( mapIter.data().getName() == prodProc && mapIter.data().getType() == "component" ) {
2217           shellProcess->addArgument( "TRUE" );
2218           break;
2219         }
2220     }
2221     // ... single installation directory for prerequisites, if this option was selected
2222     if ( oneProdDirBtn->isChecked() ) {
2223       if ( prodProc == "DebianLibsForSalome" )
2224         shellProcess->addArgument( oneProdDirName );
2225       else {
2226         MapProducts::Iterator mapIter;
2227         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter )
2228           if ( mapIter.data().getName() == prodProc && mapIter.data().getType() == "prerequisite" ) {
2229             shellProcess->addArgument( oneProdDirName );
2230             break;
2231           }
2232       }
2233     }
2234     
2235     // run script
2236     if ( !shellProcess->start() ) {
2237       // error handling can be here
2238       ___MESSAGE___( "error" );
2239     }
2240     return;
2241   }
2242   ___MESSAGE___( "All products have been installed successfully" );
2243   // all products are installed successfully
2244   MapProducts::Iterator mapIter;
2245   ___MESSAGE___( "starting pick-up environment" );
2246   QString depproducts = QUOTE( getAllProducts(productsMap).prepend( QStringList( extraProducts.keys() ).join(" ") + " " ) );
2247   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2248     QCheckListItem* item = mapIter.key();
2249     Dependancies dep = mapIter.data();
2250     if ( item->isOn() && dep.pickUpEnvironment() ) {
2251       statusLab->setText( tr( "Pick-up products environment for " ) + dep.getName().latin1() + "..." );
2252       ___MESSAGE___( "... for " << dep.getName().latin1() );
2253       QDir rd( rootDirPath() );
2254       Script script;
2255       script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2256       script << item->text(2) << "pickup_env";
2257       script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2258       script << QUOTE( QFileInfo( QDir::cleanDirPath( QDir( rootDirPath() ).filePath( "Products" ) ) ).absFilePath() );
2259       script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2260       script << depproducts << item->text(0) << QUOTE( prodSequence.join( " " ) );
2261       ___MESSAGE___( "... --> " << script.script().latin1() );
2262       if ( system( script.script().latin1() ) ) {
2263         ___MESSAGE___( "ERROR" );
2264       }
2265     }
2266   }
2267
2268   if ( installType == Binaries ) {
2269     if ( oneModDirBtn->isChecked() )
2270       runModifyLaFiles();
2271     else
2272       runCheckFLib();
2273   }
2274   else {
2275     // Update GUI and check installation errors
2276     completeInstallation();
2277   }
2278   
2279 }
2280 // ================================================================
2281 /*!
2282  *  SALOME_InstallWizard::completeInstallation
2283  *  Update GUI and check installation errors
2284  */
2285 // ================================================================
2286 void SALOME_InstallWizard::completeInstallation()
2287 {
2288   // update status label
2289   statusLab->setText( tr( "Installation completed" ) );
2290   // <Next> button
2291   setNextEnabled( true );
2292   nextButton()->setText( tr( "&Next >" ) );
2293   setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
2294   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2295   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2296   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2297   // <Back> button
2298   setBackEnabled( true );
2299   // script parameters
2300   passedParams->clear();
2301   passedParams->setEnabled( false );
2302   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2303   installInfo->setFinished( true );
2304   if ( isMinimized() )
2305     showNormal();
2306   raise();
2307   if ( hasErrors ) {
2308     if ( QMessageBox::warning( this,
2309                                tr( "Warning" ),
2310                                tr( "There were some errors and/or warnings during the installation.\n"
2311                                    "Do you want to save the installation log?" ),
2312                                tr( "&Save" ),
2313                                tr( "&Cancel" ),
2314                                QString::null,
2315                                0,
2316                                1 ) == 0 )
2317       saveLog();
2318   }
2319   hasErrors = false;
2320
2321 }
2322 // ================================================================
2323 /*!
2324  *  SALOME_InstallWizard::onInstallGuiBtn
2325  *  <Installation with GUI> check-box slot
2326  */
2327 // ================================================================
2328 void SALOME_InstallWizard::onInstallGuiBtn()
2329 {
2330   MapProducts::Iterator itProd;
2331   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2332     if ( itProd.data().getType() == "component" ) {
2333       if ( installGuiBtn->state() == QButton::On ) {
2334         itProd.key()->setEnabled( true );
2335         itProd.key()->setOn( true );
2336       }
2337       else {
2338         QString itemName = itProd.data().getName();
2339         if ( woGuiModules.find( itemName ) == woGuiModules.end() || 
2340              woGuiModules[ itemName ] == False ) {
2341           itProd.key()->setOn( false );
2342           itProd.key()->setEnabled( false );
2343         }
2344         else
2345           itProd.key()->setOn( true );
2346       }
2347     }
2348   }
2349 }
2350 // ================================================================
2351 /*!
2352  *  SALOME_InstallWizard::onMoreBtn
2353  *  <More...> button slot
2354  */
2355 // ================================================================
2356 void SALOME_InstallWizard::onMoreBtn()
2357 {
2358   if ( moreMode ) {
2359     prereqsView->hide();
2360     moreBtn->setText( tr( "Show prerequisites..." ) );
2361     setAboutInfo( moreBtn, tr( "Show list of prerequisites" ) );
2362   }
2363   else {
2364     prereqsView->show();
2365     moreBtn->setText( tr( "Hide prerequisites" ) );
2366     setAboutInfo( moreBtn, tr( "Hide list of prerequisites" ) );
2367   }
2368   qApp->processEvents();
2369   moreMode = !moreMode;
2370   InstallWizard::layOut();
2371   qApp->processEvents();
2372   if ( !isMaximized() ) {
2373     qApp->processEvents();
2374   }
2375   checkProductPage();
2376 }
2377 // ================================================================
2378 /*!
2379  *  SALOME_InstallWizard::onFinishButton
2380  *  Operation buttons slot
2381  */
2382 // ================================================================
2383 void SALOME_InstallWizard::onFinishButton()
2384 {
2385   const QObject* btn = sender();
2386   ButtonList::Iterator it;
2387   for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2388     if ( (*it).button() && (*it).button() == btn ) {
2389       QDir rd( rootDirPath() );
2390       Script script;
2391       script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2392       script << (*it).script() << "execute";
2393       script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2394       script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2395       script << ">& /dev/null";
2396       ___MESSAGE___( "script: " << script.script().latin1() );
2397       if ( (*it).script().isEmpty() || system( script.script().latin1() ) ) {
2398         QMessageBox::warning( this,
2399                               tr( "Error" ),
2400                               tr( "Can't perform action!"),
2401                               QMessageBox::Ok,
2402                               QMessageBox::NoButton,
2403                               QMessageBox::NoButton );
2404       }
2405       return;
2406     }
2407   }
2408 }
2409 // ================================================================
2410 /*!
2411  *  SALOME_InstallWizard::onAbout
2412  *  <About> button slot: shows <About> dialog box
2413  */
2414 // ================================================================
2415 void SALOME_InstallWizard::onAbout()
2416 {
2417   AboutDlg d( this );
2418   d.exec();
2419 }
2420
2421 // ================================================================
2422 /*!
2423  *  SALOME_InstallWizard::findItem
2424  *  Searches product listview item with given symbolic name
2425  */
2426 // ================================================================
2427 QCheckListItem* SALOME_InstallWizard::findItem( const QString& sName )
2428 {
2429   MapProducts::Iterator mapIter;
2430   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2431     if ( mapIter.data().getName() == sName )
2432       return mapIter.key();
2433   }
2434   return 0;
2435 }
2436 // ================================================================
2437 /*!
2438  *  SALOME_InstallWizard::abort
2439  *  Sets progress state to Aborted
2440  */
2441 // ================================================================
2442 void SALOME_InstallWizard::abort()
2443 {
2444   QString prod = progressView->findStatus( Processing );
2445   while ( !prod.isNull() ) {
2446     progressView->setStatus( prod, Aborted );
2447     prod = progressView->findStatus( Processing );
2448   }
2449   prod = progressView->findStatus( Waiting );
2450   while ( !prod.isNull() ) {
2451     progressView->setStatus( prod, Aborted );
2452     prod = progressView->findStatus( Waiting );
2453   }
2454 }
2455 // ================================================================
2456 /*!
2457  *  SALOME_InstallWizard::reject
2458  *  Reject slot, clears temporary directory and closes application
2459  */
2460 // ================================================================
2461 void SALOME_InstallWizard::reject()
2462 {
2463   ___MESSAGE___( "REJECTED" );
2464   if ( !exitConfirmed ) {
2465     if ( QMessageBox::information( this,
2466                                    tr( "Exit" ),
2467                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
2468                                    tr( "&Yes" ),
2469                                    tr( "&No" ),
2470                                    QString::null,
2471                                    0,
2472                                    1 ) == 1 ) {
2473       return;
2474     }
2475     exitConfirmed = true;
2476   }
2477   clean(true);
2478   InstallWizard::reject();
2479 }
2480 // ================================================================
2481 /*!
2482  *  SALOME_InstallWizard::accept
2483  *  Accept slot, clears temporary directory and closes application
2484  */
2485 // ================================================================
2486 void SALOME_InstallWizard::accept()
2487 {
2488   ___MESSAGE___( "ACCEPTED" );
2489   clean(true);
2490   InstallWizard::accept();
2491 }
2492 // ================================================================
2493 /*!
2494  *  SALOME_InstallWizard::clean
2495  *  Clears and (optionally) removes temporary directory
2496  */
2497 // ================================================================
2498 void SALOME_InstallWizard::clean(bool rmDir)
2499 {
2500   WarnDialog::showWarnDlg( 0, false );
2501   myThread->clearCommands();
2502   myWC.wakeAll();
2503   while ( myThread->running() );
2504   // first remove temporary files
2505   QDir rd( rootDirPath() );
2506   Script script;
2507   script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2508   script << "remove_tmp.sh" << QUOTE( tempFolder->text().stripWhiteSpace() + TEMPDIRNAME );
2509   script << QUOTE( getAllProducts( productsMap ) );
2510   script << ">& /dev/null";
2511   ___MESSAGE___( "script = " << script.script().latin1() );
2512   if ( system( script.script().latin1() ) ) {
2513     // error
2514   }
2515   // then try to remove created temporary directory
2516   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
2517   if ( rmDir && !tmpCreated.isNull() ) {
2518     script.clear();
2519     script << "rm -rf" << QUOTE( tmpCreated );
2520     script << ">& /dev/null";
2521     if ( system( script.script().latin1() ) ) {
2522       // error
2523     }
2524     ___MESSAGE___( "script = " << script.script().latin1() );
2525   }
2526 }
2527 // ================================================================
2528 /*!
2529  *  SALOME_InstallWizard::pageChanged
2530  *  Called when user moves from page to page
2531  */
2532 // ================================================================
2533 void SALOME_InstallWizard::pageChanged( const QString & mytitle)
2534 {
2535   nextButton()->setText( tr( "&Next >" ) );
2536   setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
2537   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2538   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2539   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2540   cancelButton()->disconnect();
2541   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
2542
2543   QWidget* aPage = InstallWizard::page( mytitle );
2544   if ( !aPage )
2545     return;
2546   updateCaption();
2547
2548   if ( aPage == typePage ) {
2549     // installation type page
2550     if ( buttonGrp->id( buttonGrp->selected() ) == -1 )
2551       // set default installation type
2552       forceSrc ? srcCompileBtn->animateClick() : binBtn->animateClick();
2553     else
2554       buttonGrp->selected()->animateClick();
2555   }
2556   else if ( aPage == platformsPage ) {
2557     // installation platforms page
2558     MapXmlFiles::Iterator it;
2559     if ( previousPage == typePage ) {
2560       for ( it = platformsMap.begin(); it != platformsMap.end(); ++it ) {
2561         QString plat = it.key();
2562         QRadioButton* rb = ( (QRadioButton*) platBtnGrp->child( plat ) );
2563         if ( installType == Binaries ) {
2564           QFileInfo fib( getPlatformBinPath( plat ) );
2565           rb->setEnabled( true/*fib.isDir()*/ );
2566           if ( platBtnGrp->id( platBtnGrp->selected() ) == -1 && plat == getBasePlatform() )
2567             rb->animateClick();
2568         }
2569 //      rb->setChecked( rb->isChecked() && rb->isEnabled() );
2570         if ( rb->isChecked() && rb->isEnabled() )
2571           rb->animateClick();
2572       }
2573       setNextEnabled( platformsPage, platBtnGrp->id( platBtnGrp->selected() ) != -1 );
2574     }
2575   }
2576   else  if ( aPage == dirPage ) {
2577     // installation and temporary directories page
2578     if ( ( ( this->indexOf( platformsPage ) != -1 && this->appropriate( platformsPage ) ) ? 
2579            previousPage == platformsPage : previousPage == typePage ) 
2580          && stateChanged ) {
2581       // clear global variables before reading XML file
2582       modulesView->clear();
2583       prereqsView->clear();
2584       productsMap.clear();
2585       // read XML file
2586       StructureParser* parser = new StructureParser( this );
2587       parser->setProductsLists( modulesView, prereqsView );
2588       if ( targetFolder->text().isEmpty() )
2589         parser->setTargetDir( targetFolder );
2590       if ( tempFolder->text().isEmpty() )
2591         parser->setTempDir( tempFolder );
2592       parser->readXmlFile( xmlFileName );
2593       // create a map of SALOME modules names, that can support installation without GUI mode
2594       if ( woGuiModules.isEmpty() ) {
2595         MapProducts::Iterator mapIter;
2596         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); mapIter++ ) {
2597           Dependancies dep = mapIter.data();
2598           if ( dep.getType() == "component" && dep.supportWoGuiMode() != NotDefined )
2599             woGuiModules[ dep.getName() ] = dep.supportWoGuiMode();
2600         }
2601       }
2602   
2603       // update required size for each product
2604       updateSizeColumn();
2605       // take into account command line parameters
2606       if ( !myTargetPath.isEmpty() )
2607         targetFolder->setText( myTargetPath );
2608       if ( !myTmpPath.isEmpty() )
2609         tempFolder->setText( myTmpPath );
2610       // set all modules to be checked and first module to be selected
2611       installGuiBtn->setState( QButton::Off );
2612       installGuiBtn->setState( QButton::On );
2613       if ( modulesView->childCount() > 0 && !modulesView->selectedItem() )
2614         modulesView->setSelected( modulesView->firstChild(), true );
2615       stateChanged = false;
2616     } 
2617     else if ( rmSrcPrevState != removeSrcBtn->isChecked() ) {
2618       // only update required size for each product
2619       updateSizeColumn();
2620       rmSrcPrevState = removeSrcBtn->isChecked();
2621     }
2622     // add extra products to install list
2623     extraProducts.clear();
2624     extraProducts.insert( "gcc", "gcc-common.sh" );
2625     if ( refPlatform == commonPlatform && installType == Binaries )
2626       extraProducts.insert( "DebianLibsForSalome", "DEBIANFORSALOME-3.1.sh" );
2627   }
2628   else if ( aPage == productsPage ) {
2629     // products page
2630     onSelectionChanged();
2631     checkProductPage();
2632   }
2633   else if ( aPage == prestartPage ) {
2634     // prestart page
2635     showChoiceInfo();
2636   }
2637   else if ( aPage == progressPage ) {
2638     if ( previousPage == prestartPage ) {
2639       // progress page
2640       statusLab->clear();
2641       progressView->clear();
2642       installInfo->clear();
2643       installInfo->setFinished( false );
2644       passedParams->clear();
2645       passedParams->setEnabled( false );
2646       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2647       nextButton()->setText( tr( "&Start" ) );
2648       setAboutInfo( nextButton(), tr( "Start installation process" ) );
2649       // reconnect Next button - to use it as Start button
2650       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2651       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2652       connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2653       setNextEnabled( true );
2654       // reconnect Cancel button to terminate process
2655       cancelButton()->disconnect();
2656       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
2657     }
2658   }
2659   else if ( aPage == readmePage ) {
2660     ButtonList::Iterator it;
2661     for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2662       if ( (*it).button() ) {
2663         QDir rd( rootDirPath() );
2664         Script script;
2665         script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2666         script << (*it).script() << "check_enabled";
2667         script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2668         script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2669         script << ">& /dev/null";
2670         ___MESSAGE___( "script: " << script.script().latin1() );
2671         (*it).button()->setEnabled( !(*it).script().isEmpty() && !system( script.script().latin1() ) );
2672       }
2673     }
2674     finishButton()->setEnabled( true );
2675   }
2676   previousPage = aPage;
2677   ___MESSAGE___( "previousPage = " << previousPage );
2678 }
2679 // ================================================================
2680 /*!
2681  *  SALOME_InstallWizard::onButtonGroup
2682  *  Called when user selected either installation type or installation platform
2683  */
2684 // ================================================================
2685 void SALOME_InstallWizard::onButtonGroup( int rbIndex )
2686 {
2687   int prevType = installType;
2688   QString prevPlat = getPlatform();
2689   QWidget* aPage = InstallWizard::currentPage();
2690   if ( aPage == typePage ) {
2691     installType = InstallationType( rbIndex );
2692     // management of the <Remove source and tmp files> check-box
2693     removeSrcBtn->setEnabled( installType == Compile );
2694     oneModDirBtn->setEnabled( installType == Binaries /*|| installType == Compile*/ );
2695     oneProdDirBtn->setEnabled( installType == Binaries || installType == Compile );
2696     refPlatform = "";
2697     xmlFileName = getXmlFile( curPlatform );
2698   }
2699   else if ( aPage == platformsPage ) {
2700     refPlatform = platBtnGrp->find( rbIndex )->name();
2701     xmlFileName = getXmlFile( refPlatform );
2702     setNextEnabled( platformsPage, true );
2703   }
2704   if ( prevType != installType || 
2705        ( indexOf( platformsPage ) != -1 ? prevPlat != getPlatform() : false ) ) {
2706     stateChanged = true;
2707     oneModDirBtn->setChecked( installType == Binaries && singleDir );
2708     oneProdDirBtn->setChecked( false );
2709   }
2710 }
2711 // ================================================================
2712 /*!
2713  *  SALOME_InstallWizard::helpClicked
2714  *  Shows help window
2715  */
2716 // ================================================================
2717 void SALOME_InstallWizard::helpClicked()
2718 {
2719   if ( helpWindow == NULL ) {
2720     helpWindow = HelpWindow::openHelp( this );
2721     if ( helpWindow ) {
2722       helpWindow->show();
2723       helpWindow->installEventFilter( this );
2724     }
2725     else {
2726       QMessageBox::warning( this,
2727                             tr( "Help file not found" ),
2728                             tr( "Sorry, help is unavailable" ) );
2729     }
2730   }
2731   else {
2732     helpWindow->raise();
2733     helpWindow->setActiveWindow();
2734   }
2735 }
2736 // ================================================================
2737 /*!
2738  *  SALOME_InstallWizard::browseDirectory
2739  *  Shows directory selection dialog
2740  */
2741 // ================================================================
2742 void SALOME_InstallWizard::browseDirectory()
2743 {
2744   const QObject* theSender = sender();
2745   QLineEdit* theFolder;
2746   if ( theSender == targetBtn )
2747     theFolder = targetFolder;
2748   else if (theSender == tempBtn)
2749     theFolder = tempFolder;
2750   else
2751     return;
2752   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
2753   if ( !typedDir.isNull() ) {
2754     theFolder->setText( typedDir );
2755     theFolder->end( false );
2756   }
2757 }
2758 // ================================================================
2759 /*!
2760  *  SALOME_InstallWizard::directoryChanged
2761  *  Called when directory path (target or temp) is changed
2762  */
2763 // ================================================================
2764 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
2765 {
2766   checkProductPage();
2767 }
2768 // ================================================================
2769 /*!
2770  *  SALOME_InstallWizard::onStart
2771  *  <Start> button's slot - runs installation
2772  */
2773 // ================================================================
2774 void SALOME_InstallWizard::onStart()
2775 {
2776   if ( nextButton()->text() == tr( "&Stop" ) ) {
2777     statusLab->setText( tr( "Aborting installation..." ) );
2778     shellProcess->kill();
2779     modifyLaProc->kill();
2780     while( shellProcess->isRunning() );
2781     statusLab->setText( tr( "Installation has been aborted by user" ) );
2782     return;
2783   }
2784
2785   hasErrors = false;
2786   progressView->clear();
2787   installInfo->clear();
2788   installInfo->setFinished( false );
2789   passedParams->clear();
2790   passedParams->setEnabled( false );
2791   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2792
2793   // update status label
2794   statusLab->setText( tr( "Preparing for installation..." ) );
2795   // clear lists of products
2796   toInstall.clear();
2797   notInstall.clear();
2798   toInstall += extraProducts.keys();
2799   // ... and fill it for new process
2800   QCheckListItem* item = (QCheckListItem*)( prereqsView->firstChild() );
2801   while( item ) {
2802     if ( productsMap.contains( item ) ) {
2803       if ( item->isOn() )
2804         toInstall.append( productsMap[item].getName() );
2805       else
2806         notInstall.append( productsMap[item].getName() );
2807     }
2808     item = (QCheckListItem*)( item->nextSibling() );
2809   }
2810   item = (QCheckListItem*)( modulesView->firstChild() );
2811   while( item ) {
2812     if ( productsMap.contains( item ) ) {
2813       if ( item->isOn() )
2814         toInstall.append( productsMap[item].getName() );
2815       else
2816         notInstall.append( productsMap[item].getName() );
2817     }
2818     item = (QCheckListItem*)( item->nextSibling() );
2819   }
2820   // if something at all is selected
2821   if ( (int)toInstall.count() > 1 ) {
2822
2823     if ( installType == Compile ) {
2824       // update status label
2825       statusLab->setText( tr( "Check Fortran compiler..." ) );
2826       // check Fortran compiler.
2827       QDir rd( rootDirPath() );
2828       Script script;
2829       script << QUOTE( rd.filePath( "config_files/checkFortran.sh" ) ) << "find_compilers";
2830       script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2831       ___MESSAGE___( "script = " << script.script().latin1() );
2832       if ( system( script.script().latin1() ) ) {
2833         QMessageBox::critical( this,
2834                                tr( "Error" ),
2835                                tr( "Fortran compiler was not found at current system!\n"
2836                                    "Installation can not be continued!"),
2837                                QMessageBox::Ok,
2838                                QMessageBox::NoButton,
2839                                QMessageBox::NoButton );
2840         // installation aborted
2841         abort();
2842         statusLab->setText( tr( "Installation has been aborted" ) );
2843         // enable <Next> button
2844         setNextEnabled( true );
2845         nextButton()->setText( tr( "&Start" ) );
2846         setAboutInfo( nextButton(), tr( "Start installation process" ) );
2847         // reconnect Next button - to use it as Start button
2848         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2849         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2850         connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2851         // enable <Back> button
2852         setBackEnabled( true );
2853         return;
2854       }
2855     }  
2856     
2857     // update status label
2858     statusLab->setText( tr( "Preparing for installation..." ) );
2859
2860     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
2861     // disable <Next> button
2862     //setNextEnabled( false );
2863     nextButton()->setText( tr( "&Stop" ) );
2864     setAboutInfo( nextButton(), tr( "Abort installation process" ) );
2865     // disable <Back> button
2866     setBackEnabled( false );
2867     // enable script parameters line edit
2868     // VSR commented: 18/09/03: passedParams->setEnabled( true );
2869     // VSR commented: 18/09/03: passedParams->setFocus();
2870     ProgressViewItem* progressItem;
2871     // set status for installed products
2872     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
2873       if ( !extraProducts.contains( toInstall[i] ) ) {
2874         item = findItem( toInstall[i] );
2875         progressView->addProduct( item->text(0), item->text(2) );
2876         continue;
2877       }
2878       progressItem = progressView->addProduct( toInstall[i], extraProducts[toInstall[i]] );
2879       progressItem->setVisible( false );
2880     }
2881     // set status for not installed products
2882     for ( int i = 0; i < (int)notInstall.count(); i++ ) {
2883       item = findItem( notInstall[i] );
2884       progressItem = progressView->addProduct( item->text(0), item->text(2) );
2885       progressItem->setVisible( false );
2886     }
2887     // get specified list of products being installed
2888     prodSequence.clear();
2889     for (int i = 0; i<(int)toInstall.count(); i++ ) {
2890       if ( extraProducts.contains( toInstall[i] ) ) {
2891         prodSequence.append( toInstall[i] );
2892         continue;
2893       }
2894       if ( installType == Binaries ) {
2895         prodSequence.append( toInstall[i] );
2896         QString prodType;
2897         MapProducts::Iterator mapIter;
2898         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2899           if ( mapIter.data().getName() == toInstall[i] && mapIter.data().getType() == "component" ) {
2900             prodSequence.append( toInstall[i] + "_src" );
2901             break;
2902           }
2903         }
2904       }
2905       else if ( installType == Sources )
2906         prodSequence.append( toInstall[i] + "_src" );
2907       else {
2908         prodSequence.append( toInstall[i] );
2909         prodSequence.append( toInstall[i] + "_src" );
2910       }
2911     }
2912
2913     // create a backup of 'env_build.csh', 'env_build.sh', 'env_products.csh', 'env_products.sh'
2914     // ( backup of 'salome.csh' and 'salome.sh' is made if pick-up environment is called )
2915     QDir rd( rootDirPath() );
2916     Script script;
2917     script << QUOTE( rd.filePath( "config_files/backupEnv.sh" ) );
2918     script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2919     ___MESSAGE___( "script = " << script.script().latin1() );
2920     if ( system( script.script().latin1() ) ) {
2921       if ( QMessageBox::warning( this,
2922                                  tr( "Warning" ),
2923                                  tr( "Backup environment files have not been created.\n"
2924                                      "Do you want to continue an installation process?" ),
2925                                  tr( "&Yes" ),
2926                                  tr( "&No" ), 
2927                                  QString::null, 0, 1 ) == 1 ) {
2928         // installation aborted
2929         abort();
2930         statusLab->setText( tr( "Installation has been aborted by user" ) );
2931         // enable <Next> button
2932         setNextEnabled( true );
2933         nextButton()->setText( tr( "&Start" ) );
2934         setAboutInfo( nextButton(), tr( "Start installation process" ) );
2935         // reconnect Next button - to use it as Start button
2936         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2937         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2938         connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2939         // enable <Back> button
2940         setBackEnabled( true );
2941         return;
2942       }
2943     }
2944
2945     // launch install script
2946     launchScript();
2947   }
2948 }
2949 // ================================================================
2950 /*!
2951  *  SALOME_InstallWizard::onReturnPressed
2952  *  Called when users tries to pass parameters for the script
2953  */
2954 // ================================================================
2955 void SALOME_InstallWizard::onReturnPressed()
2956 {
2957   QString txt = passedParams->text();
2958   installInfo->append( txt );
2959   txt += "\n";
2960   shellProcess->writeToStdin( txt );
2961   passedParams->clear();
2962   progressView->setFocus();
2963   passedParams->setEnabled( false );
2964   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2965 }
2966 /*!
2967   Callback function - as response for the script finishing
2968 */
2969 void SALOME_InstallWizard::productInstalled()
2970 {
2971   ___MESSAGE___( "process exited" );
2972   if ( shellProcess->normalExit() ) {
2973     ___MESSAGE___( "...normal exit" );
2974     // normal exit - try to proceed installation further
2975     launchScript();
2976   }
2977   else {
2978     ___MESSAGE___( "...abnormal exit" );
2979     statusLab->setText( tr( "Installation has been aborted" ) );
2980     // installation aborted
2981     abort();
2982     // clear script passed parameters lineedit
2983     passedParams->clear();
2984     passedParams->setEnabled( false );
2985     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2986     installInfo->setFinished( true );
2987     // enable <Next> button
2988     setNextEnabled( true );
2989     nextButton()->setText( tr( "&Start" ) );
2990     setAboutInfo( nextButton(), tr( "Start installation process" ) );
2991     // reconnect Next button - to use it as Start button
2992     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2993     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2994     connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2995     //nextButton()->setText( tr( "&Next >" ) );
2996     //setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
2997     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2998     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2999     //connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
3000     // enable <Back> button
3001     setBackEnabled( true );
3002   }
3003 }
3004 // ================================================================
3005 /*!
3006  *  SALOME_InstallWizard::tryTerminate
3007  *  Slot, called when <Cancel> button is clicked during installation script running
3008  */
3009 // ================================================================
3010 void SALOME_InstallWizard::tryTerminate()
3011 {
3012   if ( shellProcess->isRunning() ) {
3013     if ( QMessageBox::information( this,
3014                                    tr( "Exit" ),
3015                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
3016                                    tr( "&Yes" ),
3017                                    tr( "&No" ),
3018                                    QString::null,
3019                                    0,
3020                                    1 ) == 1 ) {
3021       return;
3022     }
3023     exitConfirmed = true;
3024     // if process still running try to terminate it first
3025     shellProcess->tryTerminate();
3026     abort();
3027     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
3028     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
3029   }
3030   else {
3031     // else just quit install wizard
3032     reject();
3033   }
3034 }
3035 // ================================================================
3036 /*!
3037  *  SALOME_InstallWizard::onCancel
3038  *  Kills installation process and quits application
3039  */
3040 // ================================================================
3041 void SALOME_InstallWizard::onCancel()
3042 {
3043   shellProcess->kill();
3044   modifyLaProc->kill();
3045   checkFLibProc->kill();
3046   reject();
3047 }
3048 // ================================================================
3049 /*!
3050  *  SALOME_InstallWizard::onSelectionChanged
3051  *  Called when selection is changed in the products list view
3052  *  to fill in the 'Information about product' text box
3053  */
3054 // ================================================================
3055 void SALOME_InstallWizard::onSelectionChanged()
3056 {
3057   const QObject* snd = sender();
3058   QListViewItem* item = modulesView->selectedItem();
3059   if ( snd == prereqsView )
3060     item = prereqsView->selectedItem();
3061   if ( !item )
3062     return;
3063   productInfo->clear();
3064   QCheckListItem* anItem = (QCheckListItem*)item;
3065   if ( !productsMap.contains( anItem ) )
3066     return;
3067   Dependancies dep = productsMap[ anItem ];
3068   QString text = "<b>" + anItem->text(0) + "</b>" + "<br>";
3069   if ( !dep.getVersion().isEmpty() )
3070     text += tr( "Version" ) + ": " + dep.getVersion() + "<br>";
3071   text += "<br>";
3072   if ( !dep.getDescription().isEmpty() ) {
3073     text += "<i>" + dep.getDescription() + "</i><br><br>";
3074   }
3075   /* AKL: 07/08/28 - hide required disk space for tmp files for each product ==>
3076      long tempSize = 0;
3077      tempSize = dep.getTempSize( installType );
3078      text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " KB<br>";
3079      AKL: 07/08/28 - hide required disk space for tmp files for each product <==
3080   */
3081   text += tr( "Disk space required" ) + ": " + item->text(1) + "<br>";
3082   text += "<br>";
3083   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
3084   text +=  tr( "Prerequisites" ) + ": " + req;
3085   productInfo->setText( text );
3086 }
3087 // ================================================================
3088 /*!
3089  *  SALOME_InstallWizard::onItemToggled
3090  *  Called when user checks/unchecks any product item
3091  *  Recursively sets all prerequisites and updates "Next" button state
3092  */
3093 // ================================================================
3094 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
3095 {
3096   if ( productsMap.contains( item ) ) {
3097     if ( item->isOn() )
3098       setPrerequisites( item );
3099     else 
3100       unsetPrerequisites( item );
3101   }
3102   onSelectionChanged();
3103   checkProductPage();
3104 }
3105 // ================================================================
3106 /*!
3107  *  SALOME_InstallWizard::wroteToStdin
3108  *  QProcess slot: -->something was written to stdin
3109  */
3110 // ================================================================
3111 void SALOME_InstallWizard::wroteToStdin( )
3112 {
3113   ___MESSAGE___( "Something was sent to stdin" );
3114 }
3115 // ================================================================
3116 /*!
3117  *  SALOME_InstallWizard::readFromStdout
3118  *  QProcess slot: -->something was written to stdout
3119  */
3120 // ================================================================
3121 void SALOME_InstallWizard::readFromStdout( )
3122 {
3123   ___MESSAGE___( "Something was sent to stdout" );
3124   QProcess* theProcess = ( QProcess* )sender();
3125   while ( theProcess->canReadLineStdout() ) {
3126     installInfo->append( QString( theProcess->readLineStdout() ) );
3127     installInfo->scrollToBottom();
3128   }
3129   QString str( theProcess->readStdout() );
3130   if ( !str.isEmpty() ) {
3131     installInfo->append( str );
3132     installInfo->scrollToBottom();
3133   }
3134 }
3135
3136 #define OUTLINE_TEXT(x) QString( "<font color=#FF0000><b>" ) + QString( x ) + QString( "</b></font>" )
3137
3138 // ================================================================
3139 /*!
3140  *  SALOME_InstallWizard::readFromStderr
3141  *  QProcess slot: -->something was written to stderr
3142  */
3143 // ================================================================
3144 void SALOME_InstallWizard::readFromStderr( )
3145 {
3146   ___MESSAGE___( "Something was sent to stderr" );
3147   QProcess* theProcess = ( QProcess* )sender();
3148   while ( theProcess->canReadLineStderr() ) {
3149     installInfo->append( OUTLINE_TEXT( QString( theProcess->readLineStderr() ) ) );
3150     installInfo->scrollToBottom();
3151     hasErrors = true;
3152   }
3153   QString str( theProcess->readStderr() );
3154   if ( !str.isEmpty() ) {
3155     installInfo->append( OUTLINE_TEXT( str ) );
3156     installInfo->scrollToBottom();
3157     hasErrors = true;
3158   }
3159   // VSR: 10/11/05 - disable answer mode ==>
3160   // passedParams->setEnabled( true );
3161   // passedParams->setFocus();
3162   // QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
3163   // VSR: 10/11/05 - disable answer mode <==
3164 }
3165 // ================================================================
3166 /*!
3167  *  SALOME_InstallWizard::setDependancies
3168  *  Sets dependancies for the product item
3169  */
3170 // ================================================================
3171 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
3172 {
3173   productsMap[item] = dep;
3174 }
3175 // ================================================================
3176 /*!
3177  *  SALOME_InstallWizard::addFinishButton
3178  *  Add button for the <Finish> page.
3179  *  Clear list of buttons if <toClear> flag is true.
3180  */
3181 // ================================================================
3182 void SALOME_InstallWizard::addFinishButton( const QString& label,
3183                                             const QString& tooltip,
3184                                             const QString& script,
3185                                             bool toClear )
3186 {
3187   ButtonList btns;
3188   if ( toClear ) {
3189     btns = buttons;
3190     buttons.clear();
3191   }
3192   buttons.append( Button( label, tooltip, script ) );
3193   // create finish buttons
3194   QButton* b = new QPushButton( tr( buttons.last().label() ), readmePage );
3195   if ( !buttons.last().tootip().isEmpty() )
3196     setAboutInfo( b, tr( buttons.last().tootip() ) );
3197   QHBoxLayout* hLayout = (QHBoxLayout*)readmePage->layout()->child("finishButtons");
3198   if ( toClear ) {
3199     // remove previous buttons
3200     ButtonList::Iterator it;
3201     for ( it = btns.begin(); it != btns.end(); ++it ) {
3202       hLayout->removeChild( (*it).button() );
3203       delete (*it).button();
3204     }
3205   }
3206   // add buttons to finish page
3207   hLayout->insertWidget( buttons.count()-1, b );
3208   buttons.last().setButton( b );
3209   connect( b, SIGNAL( clicked() ), this, SLOT( onFinishButton() ) );
3210 }
3211 // ================================================================
3212 /*!
3213  *  SALOME_InstallWizard::polish
3214  *  Polishing of the widget - to set right initial size
3215  */
3216 // ================================================================
3217 void SALOME_InstallWizard::polish()
3218 {
3219   resize( 0, 0 );
3220   InstallWizard::polish();
3221 }
3222 // ================================================================
3223 /*!
3224  *  SALOME_InstallWizard::saveLog
3225  *  Save installation log to file
3226  */
3227 // ================================================================
3228 void SALOME_InstallWizard::saveLog()
3229 {
3230   QString txt = installInfo->text();
3231   if ( txt.length() <= 0 )
3232     return;
3233   QDateTime dt = QDateTime::currentDateTime();
3234   QString fileName = dt.toString("ddMMyy-hhmm");
3235   fileName.prepend("install-"); fileName.append(".html");
3236   fileName = QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ), fileName ).absFilePath();
3237   fileName = QFileDialog::getSaveFileName( fileName,
3238                                            QString( "HTML files (*.htm *.html)" ),
3239                                            this, 0,
3240                                            tr( "Save Log file" ) );
3241   if ( !fileName.isEmpty() ) {
3242     QFile f( fileName );
3243     if ( f.open( IO_WriteOnly ) ) {
3244       QTextStream stream( &f );
3245       stream << txt;
3246       f.close();
3247     }
3248     else {
3249       QMessageBox::critical( this,
3250                              tr( "Error" ),
3251                              tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ),
3252                              QMessageBox::Ok,
3253                              QMessageBox::NoButton,
3254                              QMessageBox::NoButton );
3255     }
3256   }
3257 }
3258 // ================================================================
3259 /*!
3260  *  SALOME_InstallWizard::updateCaption
3261  *  Updates caption according to the current page number
3262  */
3263 // ================================================================
3264 void SALOME_InstallWizard::updateCaption()
3265 {
3266   QWidget* aPage = InstallWizard::currentPage();
3267   if ( !aPage )
3268     return;
3269   InstallWizard::setCaption( tr( myCaption ) + " " +
3270                              tr( getIWName() ) + " - " +
3271                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
3272 }
3273
3274 // ================================================================
3275 /*!
3276  *  SALOME_InstallWizard::processValidateEvent
3277  *  Processes validation event (<val> is validation code)
3278  */
3279 // ================================================================
3280 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
3281 {
3282   QWidget* aPage = InstallWizard::currentPage();
3283   if ( aPage != productsPage ) {
3284     InstallWizard::processValidateEvent( val, data );
3285     return;
3286   }
3287   myMutex.lock();
3288   myMutex.unlock();
3289   if ( val > 0 ) {
3290   }
3291   if ( myThread->hasCommands() )
3292     myWC.wakeAll();
3293   else {
3294     WarnDialog::showWarnDlg( 0, false );
3295     InstallWizard::processValidateEvent( val, data );
3296   }
3297 }