Salome HOME
Fix issue 0020160:[CEA:321] (installation wizard should make the difference between...
[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-2009 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.1" );
563   setCaption( tr( "SALOME %1" ).arg( myVersion ) );
564   setCopyright( tr( "<h5>Copyright &copy; 2007-2009 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 and other required 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 and other required 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 and other required libraries checking
1919  */
1920 // ================================================================
1921 void SALOME_InstallWizard::checkFLibResult()
1922 {
1923   if ( checkFLibProc->normalExit() && checkFLibProc->exitStatus() == 1 ) {
1924     QStringList notFoundLibsList, notFoundOptLibsList;
1925     QString record = "";
1926     QStringList prefOptLibs = getOptionalLibs();
1927     // create list of strings with all 'not found' libraries
1928     while ( checkFLibProc->canReadLineStdout() ) {
1929       record = checkFLibProc->readLineStdout().stripWhiteSpace();
1930       if ( !record.isEmpty() ) {
1931         record = QStringList::split( " ", record )[0];
1932         if ( !notFoundLibsList.contains( record ) && 
1933              !notFoundOptLibsList.contains( record ) ) {
1934           bool isOptional = false;
1935           QStringList::Iterator it_opt;
1936           for ( it_opt = prefOptLibs.begin(); it_opt != prefOptLibs.end(); ++it_opt )
1937             if ( record.startsWith( (*it_opt).stripWhiteSpace(), false ) ) {
1938               isOptional = true;
1939               break;
1940             }
1941           isOptional ? notFoundOptLibsList.append( record )             \
1942             : notFoundLibsList.append( record );
1943         }
1944       }
1945     }
1946     QString msg = tr( "Some libraries are absent!<br><br>" );
1947     if ( !notFoundLibsList.isEmpty() ) {
1948       msg += tr( "One or several <b>mandatory</b> libraries listed below are not found. SALOME <u>may not work</u> properly.<br>" );
1949       msg += notFoundLibsList.join( "<br>" );
1950       msg += "<br><br>";
1951     }
1952     if ( !notFoundOptLibsList.isEmpty() ) {
1953       msg += tr( "One or several <b>optional</b> libraries listed below are not found. This <u>does not affect</u> on the correct work of SALOME platform.<br>" );
1954       msg += notFoundOptLibsList.join( "<br>" );
1955     }
1956     if ( !notFoundLibsList.isEmpty() )
1957       QMessageBox::warning( this,
1958                             tr( "Warning" ),
1959                             msg,
1960                             QMessageBox::Ok,
1961                             QMessageBox::NoButton,
1962                             QMessageBox::NoButton );
1963     else if ( !notFoundOptLibsList.isEmpty() )
1964       QMessageBox::information( this,
1965                                 tr( "Information" ),
1966                                 msg,
1967                                 QMessageBox::Ok,
1968                                 QMessageBox::NoButton,
1969                                 QMessageBox::NoButton );
1970   }
1971   // Update GUI and check installation errors
1972   completeInstallation();
1973 }
1974 // ================================================================
1975 /*!
1976  *  SALOME_InstallWizard::updateSizeColumn
1977  *  Sets required size for each product according to 
1978  *  installation type and 'Remove SRC & TMP' checkbox state
1979  */
1980 // ================================================================
1981 void SALOME_InstallWizard::updateSizeColumn()
1982 {
1983   long prodSize = 0;
1984   bool removeSrc = removeSrcBtn->isChecked();
1985   MapProducts::Iterator mapIter;
1986   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1987     QCheckListItem* item = mapIter.key();
1988     Dependancies dep = mapIter.data();
1989     // get required size for current product
1990     long binSize = dep.getSize( Binaries );
1991     long srcSize = dep.getSize( Sources );
1992     long bldSize = dep.getSize( Compile );
1993     InstallationType instType = getInstType();
1994     if ( instType == Binaries ) {
1995       if ( dep.getType() == "component" )
1996         prodSize = binSize + srcSize;
1997       else
1998         prodSize = ( binSize != 0 ? binSize : srcSize );
1999     }
2000     else if ( instType == Sources )
2001       prodSize = srcSize;
2002     else
2003       if ( removeSrc )
2004         prodSize = ( binSize != 0 ? binSize : srcSize );
2005       else {
2006         prodSize = ( bldSize != 0 ? bldSize : srcSize );
2007       }
2008     // fill in 'Size' field
2009     item->setText( 1, QString::number( prodSize )+" KB" );
2010   }
2011 }
2012 // ================================================================
2013 /*!
2014  *  SALOME_InstallWizard::checkProductPage
2015  *  Checks products page validity (directories and products selection) and
2016  *  enabled/disables "Next" button for the Products page
2017  */
2018 // ================================================================
2019 void SALOME_InstallWizard::checkProductPage()
2020 {
2021   if ( this->currentPage() != productsPage )
2022     return;
2023   long tots = 0, temps = 0;
2024   // check if any product is selected;
2025   bool isAnyProductSelected = checkSize( &tots, &temps );
2026
2027   // update required size information
2028   requiredSize->setText( QString::number( tots )  + " KB");
2029   requiredTemp->setText( QString::number( temps ) + " KB");
2030
2031   // update available size information
2032   QFileInfo fi( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) );
2033   if ( fi.exists() ) {
2034     diskSpaceProc->clearArguments();
2035     diskSpaceProc->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
2036     diskSpaceProc->addArgument( "diskSpace.sh" );
2037     diskSpaceProc->addArgument( fi.absFilePath() );
2038     // run script
2039     diskSpaceProc->start();
2040   }
2041
2042   // enable/disable "Next" button
2043   setNextEnabled( productsPage, isAnyProductSelected );
2044 }
2045 // ================================================================
2046 /*!
2047  *  SALOME_InstallWizard::setPrerequisites
2048  *  Sets the product and all products this one depends on to be checked ( recursively )
2049  */
2050 // ================================================================
2051 void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
2052 {
2053   if ( !productsMap.contains( item ) )
2054     return;
2055   if ( !item->isOn() )
2056     return;
2057   // get all prerequisites
2058   QStringList dependOn = productsMap[ item ].getDependancies();
2059   // install SALOME without GUI case
2060   if ( installGuiBtn->state() != QButton::On && 
2061        woGuiModules.find( item->text(0) ) != woGuiModules.end() && 
2062        woGuiModules[item->text(0)] == True ) {
2063     dependOn.remove( "GUI" );
2064   }
2065   // setting prerequisites
2066   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
2067     MapProducts::Iterator itProd;
2068     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2069       if ( itProd.data().getName() == dependOn[ i ] ) {
2070         if ( itProd.data().getType() == "component" && !itProd.key()->isOn() )
2071           itProd.key()->setOn( true );
2072         else if ( itProd.data().getType() == "prerequisite" ) {
2073           itProd.key()->setOn( true );
2074           itProd.key()->setEnabled( false );
2075         }
2076         break;
2077       }
2078     }
2079   }
2080 }
2081 // ================================================================
2082 /*!
2083  *  SALOME_InstallWizard::unsetPrerequisites
2084  *  Unsets all modules which depend of the unchecked product ( recursively )
2085  */
2086 // ================================================================
2087 void SALOME_InstallWizard::unsetPrerequisites( QCheckListItem* item )
2088 {
2089   if ( !productsMap.contains( item ) )
2090     return;
2091   if ( item->isOn() )
2092     return;
2093
2094 // uncheck dependent products
2095   QString itemName = productsMap[ item ].getName();
2096   MapProducts::Iterator itProd;
2097   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2098     if ( itProd.data().getType() == productsMap[ item ].getType() ) {
2099       QStringList dependOn = itProd.data().getDependancies();
2100       for ( int i = 0; i < (int)dependOn.count(); i++ ) {
2101         if ( dependOn[ i ] == itemName ) {
2102           if ( itProd.key()->isOn() ) {
2103             itProd.key()->setOn( false );
2104           }
2105         }
2106       }
2107     }
2108   }
2109
2110 // uncheck prerequisites
2111   int nbDependents;
2112 //   cout << "item name = " << productsMap[ item ].getName() << endl;
2113   QStringList dependOnList = productsMap[ item ].getDependancies();
2114   for ( int j = 0; j < (int)dependOnList.count(); j++ ) {
2115     nbDependents = 0;
2116     MapProducts::Iterator itProd1;
2117     for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
2118       if ( itProd1.data().getName() == dependOnList[ j ] ) {
2119         if ( itProd1.data().getType() == "prerequisite" ) {
2120           MapProducts::Iterator itProd2;
2121           for ( itProd2 = productsMap.begin(); itProd2 != productsMap.end(); ++itProd2 ) {
2122             if ( itProd2.key()->isOn() ) {
2123               QStringList prereqsList = productsMap[ itProd2.key() ].getDependancies();
2124               for ( int k = 0; k < (int)prereqsList.count(); k++ ) {
2125                 if ( prereqsList[ k ] == itProd1.data().getName() ) {
2126                   nbDependents++;
2127                   break;
2128                 }
2129               }
2130             }
2131           }
2132           if ( nbDependents == 0 ) {
2133             itProd1.key()->setEnabled( true );
2134             itProd1.key()->setOn( false );
2135           }
2136         }
2137         break;
2138       }
2139     }
2140   }
2141 }
2142 // ================================================================
2143 /*!
2144  *  SALOME_InstallWizard::launchScript
2145  *  Runs installation script
2146  */
2147 // ================================================================
2148 void SALOME_InstallWizard::launchScript()
2149 {
2150   // try to find product being processed now
2151   QString prodProc = progressView->findStatus( Processing );
2152   if ( !prodProc.isNull() ) {
2153     ___MESSAGE___( "Found <Processing>: " );
2154
2155     // if found - set status to "completed"
2156     progressView->setStatus( prodProc, Completed );
2157     // ... clear status label
2158     statusLab->clear();
2159     // ... and call this method again
2160     launchScript();
2161     return;
2162   }
2163   // else try to find next product which is not processed yet
2164   prodProc = progressView->findStatus( Waiting );
2165   if ( !prodProc.isNull() ) {
2166     ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
2167     // if found - set status to "processed" and run script
2168     progressView->setStatus( prodProc, Processing );
2169     progressView->ensureVisible( prodProc );
2170     
2171     QCheckListItem* item = 0;
2172     // fill in script parameters
2173     shellProcess->clearArguments();
2174     // ... script name
2175     shellProcess->setWorkingDirectory( QDir( rootDirPath() ).filePath( "config_files" ) );
2176     if ( !extraProducts.contains( prodProc ) ) {
2177       item = findItem( prodProc );
2178       shellProcess->addArgument( item->text(2) );
2179     }
2180     else
2181       shellProcess->addArgument( extraProducts[ prodProc ] );
2182
2183     // ... get folder with binaries
2184     QString OS = getPlatform();
2185     if ( refPlatform.isEmpty() && platformsMap.find( curPlatform ) == platformsMap.end() )
2186       OS = commonPlatform;
2187     QString binDir = getPlatformBinPath( OS );
2188     // ... temp folder
2189     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
2190     //if( !tempFolder->isEnabled() )
2191     //  tmpFolder = "/tmp";
2192
2193     // ... not install : try to find preinstalled
2194     if ( notInstall.contains( prodProc ) || prodProc == "gcc" ) {
2195       shellProcess->addArgument( "try_preinstalled" );
2196       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
2197       shellProcess->addArgument( QDir( rootDirPath() ).filePath( "Products" ) );
2198       statusLab->setText( tr( "Collecting environment for '" ) + prodProc + "'..." );
2199     }
2200     // ... binaries ?
2201     else if ( installType == Binaries ) {
2202       shellProcess->addArgument( "install_binary" );
2203       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
2204       shellProcess->addArgument( binDir );
2205       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
2206     }
2207     // ... sources or sources_and_compilation ?
2208     else {
2209       shellProcess->addArgument( installType == Sources ? "install_source" : 
2210                                  "install_source_and_build" );
2211       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
2212       shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
2213       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
2214     }
2215     // ... target folder
2216     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
2217     shellProcess->addArgument( QFileInfo( tgtFolder ).absFilePath() );
2218     // ... list of all products
2219     QString depproducts = getAllProducts(productsMap);
2220     depproducts.prepend( QStringList( extraProducts.keys() ).join(" ") + " " );
2221     ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
2222     shellProcess->addArgument( depproducts );
2223     // ... product name - currently installed product
2224     if ( !extraProducts.contains( prodProc ) )
2225       shellProcess->addArgument( item->text(0) );
2226     else
2227       shellProcess->addArgument( prodProc );
2228     // ... list of products being installed
2229     shellProcess->addArgument( prodSequence.join( " " ) );
2230     // ... sources directory
2231     shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
2232     // ... remove sources and tmp files or not?
2233     if ( installType == Compile && removeSrcBtn->isOn() )
2234       shellProcess->addArgument( "TRUE" );
2235     else 
2236       shellProcess->addArgument( "FALSE" );
2237     // ... binaries directory
2238     shellProcess->addArgument( binDir );
2239     // ... install SALOME with GUI or not?
2240     if ( woGuiModules.find( prodProc ) != woGuiModules.end() )
2241       ( installGuiBtn->state() != QButton::On && woGuiModules[ prodProc ] == True ) ? 
2242         shellProcess->addArgument( "FALSE" ) : 
2243         shellProcess->addArgument( "TRUE" );
2244     // ... single installation directory for SALOME modules, if this option was selected
2245     if ( oneModDirBtn->isChecked() ) {
2246       MapProducts::Iterator mapIter;
2247       for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter )
2248         if ( mapIter.data().getName() == prodProc && mapIter.data().getType() == "component" ) {
2249           shellProcess->addArgument( "TRUE" );
2250           break;
2251         }
2252     }
2253     // ... single installation directory for prerequisites, if this option was selected
2254     if ( oneProdDirBtn->isChecked() ) {
2255       if ( prodProc == "DebianLibsForSalome" )
2256         shellProcess->addArgument( oneProdDirName );
2257       else {
2258         MapProducts::Iterator mapIter;
2259         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter )
2260           if ( mapIter.data().getName() == prodProc && mapIter.data().getType() == "prerequisite" ) {
2261             shellProcess->addArgument( oneProdDirName );
2262             break;
2263           }
2264       }
2265     }
2266     
2267     // run script
2268     if ( !shellProcess->start() ) {
2269       // error handling can be here
2270       ___MESSAGE___( "error" );
2271     }
2272     return;
2273   }
2274   ___MESSAGE___( "All products have been installed successfully" );
2275   // all products are installed successfully
2276   MapProducts::Iterator mapIter;
2277   ___MESSAGE___( "starting pick-up environment" );
2278   QString depproducts = QUOTE( getAllProducts(productsMap).prepend( QStringList( extraProducts.keys() ).join(" ") + " " ) );
2279   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2280     QCheckListItem* item = mapIter.key();
2281     Dependancies dep = mapIter.data();
2282     if ( item->isOn() && dep.pickUpEnvironment() ) {
2283       statusLab->setText( tr( "Pick-up products environment for " ) + dep.getName().latin1() + "..." );
2284       ___MESSAGE___( "... for " << dep.getName().latin1() );
2285       QDir rd( rootDirPath() );
2286       Script script;
2287       script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2288       script << item->text(2) << "pickup_env";
2289       script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2290       script << QUOTE( QFileInfo( QDir::cleanDirPath( QDir( rootDirPath() ).filePath( "Products" ) ) ).absFilePath() );
2291       script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2292       script << depproducts << item->text(0) << QUOTE( prodSequence.join( " " ) );
2293       ___MESSAGE___( "... --> " << script.script().latin1() );
2294       if ( system( script.script().latin1() ) ) {
2295         ___MESSAGE___( "ERROR" );
2296       }
2297     }
2298   }
2299
2300   if ( installType == Binaries ) {
2301     if ( oneModDirBtn->isChecked() )
2302       runModifyLaFiles();
2303     else
2304       runCheckFLib();
2305   }
2306   else {
2307     // Update GUI and check installation errors
2308     completeInstallation();
2309   }
2310   
2311 }
2312 // ================================================================
2313 /*!
2314  *  SALOME_InstallWizard::completeInstallation
2315  *  Update GUI and check installation errors
2316  */
2317 // ================================================================
2318 void SALOME_InstallWizard::completeInstallation()
2319 {
2320   // update status label
2321   statusLab->setText( tr( "Installation completed" ) );
2322   // <Next> button
2323   setNextEnabled( true );
2324   nextButton()->setText( tr( "&Next >" ) );
2325   setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
2326   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2327   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2328   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2329   // <Back> button
2330   setBackEnabled( true );
2331   // script parameters
2332   passedParams->clear();
2333   passedParams->setEnabled( false );
2334   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2335   installInfo->setFinished( true );
2336   if ( isMinimized() )
2337     showNormal();
2338   raise();
2339   if ( hasErrors ) {
2340     if ( QMessageBox::warning( this,
2341                                tr( "Warning" ),
2342                                tr( "There were some errors and/or warnings during the installation.\n"
2343                                    "Do you want to save the installation log?" ),
2344                                tr( "&Save" ),
2345                                tr( "&Cancel" ),
2346                                QString::null,
2347                                0,
2348                                1 ) == 0 )
2349       saveLog();
2350   }
2351   hasErrors = false;
2352
2353 }
2354 // ================================================================
2355 /*!
2356  *  SALOME_InstallWizard::onInstallGuiBtn
2357  *  <Installation with GUI> check-box slot
2358  */
2359 // ================================================================
2360 void SALOME_InstallWizard::onInstallGuiBtn()
2361 {
2362   MapProducts::Iterator itProd;
2363   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2364     if ( itProd.data().getType() == "component" ) {
2365       if ( installGuiBtn->state() == QButton::On ) {
2366         itProd.key()->setEnabled( true );
2367         itProd.key()->setOn( true );
2368       }
2369       else {
2370         QString itemName = itProd.data().getName();
2371         if ( woGuiModules.find( itemName ) == woGuiModules.end() || 
2372              woGuiModules[ itemName ] == False ) {
2373           itProd.key()->setOn( false );
2374           itProd.key()->setEnabled( false );
2375         }
2376         else
2377           itProd.key()->setOn( true );
2378       }
2379     }
2380   }
2381 }
2382 // ================================================================
2383 /*!
2384  *  SALOME_InstallWizard::onMoreBtn
2385  *  <More...> button slot
2386  */
2387 // ================================================================
2388 void SALOME_InstallWizard::onMoreBtn()
2389 {
2390   if ( moreMode ) {
2391     prereqsView->hide();
2392     moreBtn->setText( tr( "Show prerequisites..." ) );
2393     setAboutInfo( moreBtn, tr( "Show list of prerequisites" ) );
2394   }
2395   else {
2396     prereqsView->show();
2397     moreBtn->setText( tr( "Hide prerequisites" ) );
2398     setAboutInfo( moreBtn, tr( "Hide list of prerequisites" ) );
2399   }
2400   qApp->processEvents();
2401   moreMode = !moreMode;
2402   InstallWizard::layOut();
2403   qApp->processEvents();
2404   if ( !isMaximized() ) {
2405     qApp->processEvents();
2406   }
2407   checkProductPage();
2408 }
2409 // ================================================================
2410 /*!
2411  *  SALOME_InstallWizard::onFinishButton
2412  *  Operation buttons slot
2413  */
2414 // ================================================================
2415 void SALOME_InstallWizard::onFinishButton()
2416 {
2417   const QObject* btn = sender();
2418   ButtonList::Iterator it;
2419   for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2420     if ( (*it).button() && (*it).button() == btn ) {
2421       QDir rd( rootDirPath() );
2422       Script script;
2423       script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2424       script << (*it).script() << "execute";
2425       script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2426       script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2427       script << ">& /dev/null";
2428       ___MESSAGE___( "script: " << script.script().latin1() );
2429       if ( (*it).script().isEmpty() || system( script.script().latin1() ) ) {
2430         QMessageBox::warning( this,
2431                               tr( "Error" ),
2432                               tr( "Can't perform action!"),
2433                               QMessageBox::Ok,
2434                               QMessageBox::NoButton,
2435                               QMessageBox::NoButton );
2436       }
2437       return;
2438     }
2439   }
2440 }
2441 // ================================================================
2442 /*!
2443  *  SALOME_InstallWizard::onAbout
2444  *  <About> button slot: shows <About> dialog box
2445  */
2446 // ================================================================
2447 void SALOME_InstallWizard::onAbout()
2448 {
2449   AboutDlg d( this );
2450   d.exec();
2451 }
2452
2453 // ================================================================
2454 /*!
2455  *  SALOME_InstallWizard::findItem
2456  *  Searches product listview item with given symbolic name
2457  */
2458 // ================================================================
2459 QCheckListItem* SALOME_InstallWizard::findItem( const QString& sName )
2460 {
2461   MapProducts::Iterator mapIter;
2462   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2463     if ( mapIter.data().getName() == sName )
2464       return mapIter.key();
2465   }
2466   return 0;
2467 }
2468 // ================================================================
2469 /*!
2470  *  SALOME_InstallWizard::abort
2471  *  Sets progress state to Aborted
2472  */
2473 // ================================================================
2474 void SALOME_InstallWizard::abort()
2475 {
2476   QString prod = progressView->findStatus( Processing );
2477   while ( !prod.isNull() ) {
2478     progressView->setStatus( prod, Aborted );
2479     prod = progressView->findStatus( Processing );
2480   }
2481   prod = progressView->findStatus( Waiting );
2482   while ( !prod.isNull() ) {
2483     progressView->setStatus( prod, Aborted );
2484     prod = progressView->findStatus( Waiting );
2485   }
2486 }
2487 // ================================================================
2488 /*!
2489  *  SALOME_InstallWizard::reject
2490  *  Reject slot, clears temporary directory and closes application
2491  */
2492 // ================================================================
2493 void SALOME_InstallWizard::reject()
2494 {
2495   ___MESSAGE___( "REJECTED" );
2496   if ( !exitConfirmed ) {
2497     if ( QMessageBox::information( this,
2498                                    tr( "Exit" ),
2499                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
2500                                    tr( "&Yes" ),
2501                                    tr( "&No" ),
2502                                    QString::null,
2503                                    0,
2504                                    1 ) == 1 ) {
2505       return;
2506     }
2507     exitConfirmed = true;
2508   }
2509   clean(true);
2510   InstallWizard::reject();
2511 }
2512 // ================================================================
2513 /*!
2514  *  SALOME_InstallWizard::accept
2515  *  Accept slot, clears temporary directory and closes application
2516  */
2517 // ================================================================
2518 void SALOME_InstallWizard::accept()
2519 {
2520   ___MESSAGE___( "ACCEPTED" );
2521   clean(true);
2522   InstallWizard::accept();
2523 }
2524 // ================================================================
2525 /*!
2526  *  SALOME_InstallWizard::clean
2527  *  Clears and (optionally) removes temporary directory
2528  */
2529 // ================================================================
2530 void SALOME_InstallWizard::clean(bool rmDir)
2531 {
2532   WarnDialog::showWarnDlg( 0, false );
2533   myThread->clearCommands();
2534   myWC.wakeAll();
2535   while ( myThread->running() );
2536   // first remove temporary files
2537   QDir rd( rootDirPath() );
2538   Script script;
2539   script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2540   script << "remove_tmp.sh" << QUOTE( tempFolder->text().stripWhiteSpace() + TEMPDIRNAME );
2541   script << QUOTE( getAllProducts( productsMap ) );
2542   script << ">& /dev/null";
2543   ___MESSAGE___( "script = " << script.script().latin1() );
2544   if ( system( script.script().latin1() ) ) {
2545     // error
2546   }
2547   // then try to remove created temporary directory
2548   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
2549   if ( rmDir && !tmpCreated.isNull() ) {
2550     script.clear();
2551     script << "rm -rf" << QUOTE( tmpCreated );
2552     script << ">& /dev/null";
2553     if ( system( script.script().latin1() ) ) {
2554       // error
2555     }
2556     ___MESSAGE___( "script = " << script.script().latin1() );
2557   }
2558 }
2559 // ================================================================
2560 /*!
2561  *  SALOME_InstallWizard::pageChanged
2562  *  Called when user moves from page to page
2563  */
2564 // ================================================================
2565 void SALOME_InstallWizard::pageChanged( const QString & mytitle)
2566 {
2567   nextButton()->setText( tr( "&Next >" ) );
2568   setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
2569   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2570   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2571   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2572   cancelButton()->disconnect();
2573   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
2574
2575   QWidget* aPage = InstallWizard::page( mytitle );
2576   if ( !aPage )
2577     return;
2578   updateCaption();
2579
2580   if ( aPage == typePage ) {
2581     // installation type page
2582     if ( buttonGrp->id( buttonGrp->selected() ) == -1 )
2583       // set default installation type
2584       forceSrc ? srcCompileBtn->animateClick() : binBtn->animateClick();
2585     else
2586       buttonGrp->selected()->animateClick();
2587   }
2588   else if ( aPage == platformsPage ) {
2589     // installation platforms page
2590     MapXmlFiles::Iterator it;
2591     if ( previousPage == typePage ) {
2592       for ( it = platformsMap.begin(); it != platformsMap.end(); ++it ) {
2593         QString plat = it.key();
2594         QRadioButton* rb = ( (QRadioButton*) platBtnGrp->child( plat ) );
2595         if ( installType == Binaries ) {
2596           QFileInfo fib( getPlatformBinPath( plat ) );
2597           rb->setEnabled( true/*fib.isDir()*/ );
2598           if ( platBtnGrp->id( platBtnGrp->selected() ) == -1 && plat == getBasePlatform() )
2599             rb->animateClick();
2600         }
2601 //      rb->setChecked( rb->isChecked() && rb->isEnabled() );
2602         if ( rb->isChecked() && rb->isEnabled() )
2603           rb->animateClick();
2604       }
2605       setNextEnabled( platformsPage, platBtnGrp->id( platBtnGrp->selected() ) != -1 );
2606     }
2607   }
2608   else  if ( aPage == dirPage ) {
2609     // installation and temporary directories page
2610     if ( ( ( this->indexOf( platformsPage ) != -1 && this->appropriate( platformsPage ) ) ? 
2611            previousPage == platformsPage : previousPage == typePage ) 
2612          && stateChanged ) {
2613       // clear global variables before reading XML file
2614       modulesView->clear();
2615       prereqsView->clear();
2616       productsMap.clear();
2617       // read XML file
2618       StructureParser* parser = new StructureParser( this );
2619       parser->setProductsLists( modulesView, prereqsView );
2620       if ( targetFolder->text().isEmpty() )
2621         parser->setTargetDir( targetFolder );
2622       if ( tempFolder->text().isEmpty() )
2623         parser->setTempDir( tempFolder );
2624       parser->readXmlFile( xmlFileName );
2625       // create a map of SALOME modules names, that can support installation without GUI mode
2626       if ( woGuiModules.isEmpty() ) {
2627         MapProducts::Iterator mapIter;
2628         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); mapIter++ ) {
2629           Dependancies dep = mapIter.data();
2630           if ( dep.getType() == "component" && dep.supportWoGuiMode() != NotDefined )
2631             woGuiModules[ dep.getName() ] = dep.supportWoGuiMode();
2632         }
2633       }
2634   
2635       // update required size for each product
2636       updateSizeColumn();
2637       // take into account command line parameters
2638       if ( !myTargetPath.isEmpty() )
2639         targetFolder->setText( myTargetPath );
2640       if ( !myTmpPath.isEmpty() )
2641         tempFolder->setText( myTmpPath );
2642       // set all modules to be checked and first module to be selected
2643       installGuiBtn->setState( QButton::Off );
2644       installGuiBtn->setState( QButton::On );
2645       if ( modulesView->childCount() > 0 && !modulesView->selectedItem() )
2646         modulesView->setSelected( modulesView->firstChild(), true );
2647       stateChanged = false;
2648     } 
2649     else if ( rmSrcPrevState != removeSrcBtn->isChecked() ) {
2650       // only update required size for each product
2651       updateSizeColumn();
2652       rmSrcPrevState = removeSrcBtn->isChecked();
2653     }
2654     // add extra products to install list
2655     extraProducts.clear();
2656     extraProducts.insert( "gcc", "gcc-common.sh" );
2657     if ( refPlatform == commonPlatform && installType == Binaries )
2658       extraProducts.insert( "DebianLibsForSalome", "DEBIANFORSALOME-3.1.sh" );
2659   }
2660   else if ( aPage == productsPage ) {
2661     // products page
2662     onSelectionChanged();
2663     checkProductPage();
2664   }
2665   else if ( aPage == prestartPage ) {
2666     // prestart page
2667     showChoiceInfo();
2668   }
2669   else if ( aPage == progressPage ) {
2670     if ( previousPage == prestartPage ) {
2671       // progress page
2672       statusLab->clear();
2673       progressView->clear();
2674       installInfo->clear();
2675       installInfo->setFinished( false );
2676       passedParams->clear();
2677       passedParams->setEnabled( false );
2678       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2679       nextButton()->setText( tr( "&Start" ) );
2680       setAboutInfo( nextButton(), tr( "Start installation process" ) );
2681       // reconnect Next button - to use it as Start button
2682       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2683       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2684       connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2685       setNextEnabled( true );
2686       // reconnect Cancel button to terminate process
2687       cancelButton()->disconnect();
2688       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
2689     }
2690   }
2691   else if ( aPage == readmePage ) {
2692     ButtonList::Iterator it;
2693     for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2694       if ( (*it).button() ) {
2695         QDir rd( rootDirPath() );
2696         Script script;
2697         script << "cd" << QUOTE( rd.filePath( "config_files" ) ) << ";";
2698         script << (*it).script() << "check_enabled";
2699         script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2700         script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2701         script << ">& /dev/null";
2702         ___MESSAGE___( "script: " << script.script().latin1() );
2703         (*it).button()->setEnabled( !(*it).script().isEmpty() && !system( script.script().latin1() ) );
2704       }
2705     }
2706     finishButton()->setEnabled( true );
2707   }
2708   previousPage = aPage;
2709   ___MESSAGE___( "previousPage = " << previousPage );
2710 }
2711 // ================================================================
2712 /*!
2713  *  SALOME_InstallWizard::onButtonGroup
2714  *  Called when user selected either installation type or installation platform
2715  */
2716 // ================================================================
2717 void SALOME_InstallWizard::onButtonGroup( int rbIndex )
2718 {
2719   int prevType = installType;
2720   QString prevPlat = getPlatform();
2721   QWidget* aPage = InstallWizard::currentPage();
2722   if ( aPage == typePage ) {
2723     installType = InstallationType( rbIndex );
2724     // management of the <Remove source and tmp files> check-box
2725     removeSrcBtn->setEnabled( installType == Compile );
2726     oneModDirBtn->setEnabled( installType == Binaries /*|| installType == Compile*/ );
2727     oneProdDirBtn->setEnabled( installType == Binaries || installType == Compile );
2728     refPlatform = "";
2729     xmlFileName = getXmlFile( curPlatform );
2730   }
2731   else if ( aPage == platformsPage ) {
2732     refPlatform = platBtnGrp->find( rbIndex )->name();
2733     xmlFileName = getXmlFile( refPlatform );
2734     setNextEnabled( platformsPage, true );
2735   }
2736   if ( prevType != installType || 
2737        ( indexOf( platformsPage ) != -1 ? prevPlat != getPlatform() : false ) ) {
2738     stateChanged = true;
2739     oneModDirBtn->setChecked( installType == Binaries && singleDir );
2740     oneProdDirBtn->setChecked( false );
2741   }
2742 }
2743 // ================================================================
2744 /*!
2745  *  SALOME_InstallWizard::helpClicked
2746  *  Shows help window
2747  */
2748 // ================================================================
2749 void SALOME_InstallWizard::helpClicked()
2750 {
2751   if ( helpWindow == NULL ) {
2752     helpWindow = HelpWindow::openHelp( this );
2753     if ( helpWindow ) {
2754       helpWindow->show();
2755       helpWindow->installEventFilter( this );
2756     }
2757     else {
2758       QMessageBox::warning( this,
2759                             tr( "Help file not found" ),
2760                             tr( "Sorry, help is unavailable" ) );
2761     }
2762   }
2763   else {
2764     helpWindow->raise();
2765     helpWindow->setActiveWindow();
2766   }
2767 }
2768 // ================================================================
2769 /*!
2770  *  SALOME_InstallWizard::browseDirectory
2771  *  Shows directory selection dialog
2772  */
2773 // ================================================================
2774 void SALOME_InstallWizard::browseDirectory()
2775 {
2776   const QObject* theSender = sender();
2777   QLineEdit* theFolder;
2778   if ( theSender == targetBtn )
2779     theFolder = targetFolder;
2780   else if (theSender == tempBtn)
2781     theFolder = tempFolder;
2782   else
2783     return;
2784   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
2785   if ( !typedDir.isNull() ) {
2786     theFolder->setText( typedDir );
2787     theFolder->end( false );
2788   }
2789 }
2790 // ================================================================
2791 /*!
2792  *  SALOME_InstallWizard::directoryChanged
2793  *  Called when directory path (target or temp) is changed
2794  */
2795 // ================================================================
2796 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
2797 {
2798   checkProductPage();
2799 }
2800 // ================================================================
2801 /*!
2802  *  SALOME_InstallWizard::onStart
2803  *  <Start> button's slot - runs installation
2804  */
2805 // ================================================================
2806 void SALOME_InstallWizard::onStart()
2807 {
2808   if ( nextButton()->text() == tr( "&Stop" ) ) {
2809     statusLab->setText( tr( "Aborting installation..." ) );
2810     shellProcess->kill();
2811     modifyLaProc->kill();
2812     while( shellProcess->isRunning() );
2813     statusLab->setText( tr( "Installation has been aborted by user" ) );
2814     return;
2815   }
2816
2817   hasErrors = false;
2818   progressView->clear();
2819   installInfo->clear();
2820   installInfo->setFinished( false );
2821   passedParams->clear();
2822   passedParams->setEnabled( false );
2823   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2824
2825   // update status label
2826   statusLab->setText( tr( "Preparing for installation..." ) );
2827   // clear lists of products
2828   toInstall.clear();
2829   notInstall.clear();
2830   toInstall += extraProducts.keys();
2831   // ... and fill it for new process
2832   QCheckListItem* item = (QCheckListItem*)( prereqsView->firstChild() );
2833   while( item ) {
2834     if ( productsMap.contains( item ) ) {
2835       if ( item->isOn() )
2836         toInstall.append( productsMap[item].getName() );
2837       else
2838         notInstall.append( productsMap[item].getName() );
2839     }
2840     item = (QCheckListItem*)( item->nextSibling() );
2841   }
2842   item = (QCheckListItem*)( modulesView->firstChild() );
2843   while( item ) {
2844     if ( productsMap.contains( item ) ) {
2845       if ( item->isOn() )
2846         toInstall.append( productsMap[item].getName() );
2847       else
2848         notInstall.append( productsMap[item].getName() );
2849     }
2850     item = (QCheckListItem*)( item->nextSibling() );
2851   }
2852   // if something at all is selected
2853   if ( (int)toInstall.count() > 1 ) {
2854
2855     if ( installType == Compile ) {
2856       // update status label
2857       statusLab->setText( tr( "Check Fortran compiler..." ) );
2858       // check Fortran compiler.
2859       QDir rd( rootDirPath() );
2860       Script script;
2861       script << QUOTE( rd.filePath( "config_files/checkFortran.sh" ) ) << "find_compilers";
2862       script << QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2863       ___MESSAGE___( "script = " << script.script().latin1() );
2864       if ( system( script.script().latin1() ) ) {
2865         QMessageBox::critical( this,
2866                                tr( "Error" ),
2867                                tr( "Fortran compiler was not found at current system!\n"
2868                                    "Installation can not be continued!"),
2869                                QMessageBox::Ok,
2870                                QMessageBox::NoButton,
2871                                QMessageBox::NoButton );
2872         // installation aborted
2873         abort();
2874         statusLab->setText( tr( "Installation has been aborted" ) );
2875         // enable <Next> button
2876         setNextEnabled( true );
2877         nextButton()->setText( tr( "&Start" ) );
2878         setAboutInfo( nextButton(), tr( "Start installation process" ) );
2879         // reconnect Next button - to use it as Start button
2880         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2881         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2882         connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2883         // enable <Back> button
2884         setBackEnabled( true );
2885         return;
2886       }
2887     }  
2888     
2889     // update status label
2890     statusLab->setText( tr( "Preparing for installation..." ) );
2891
2892     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
2893     // disable <Next> button
2894     //setNextEnabled( false );
2895     nextButton()->setText( tr( "&Stop" ) );
2896     setAboutInfo( nextButton(), tr( "Abort installation process" ) );
2897     // disable <Back> button
2898     setBackEnabled( false );
2899     // enable script parameters line edit
2900     // VSR commented: 18/09/03: passedParams->setEnabled( true );
2901     // VSR commented: 18/09/03: passedParams->setFocus();
2902     ProgressViewItem* progressItem;
2903     // set status for installed products
2904     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
2905       if ( !extraProducts.contains( toInstall[i] ) ) {
2906         item = findItem( toInstall[i] );
2907         progressView->addProduct( item->text(0), item->text(2) );
2908         continue;
2909       }
2910       progressItem = progressView->addProduct( toInstall[i], extraProducts[toInstall[i]] );
2911       progressItem->setVisible( false );
2912     }
2913     // set status for not installed products
2914     for ( int i = 0; i < (int)notInstall.count(); i++ ) {
2915       item = findItem( notInstall[i] );
2916       progressItem = progressView->addProduct( item->text(0), item->text(2) );
2917       progressItem->setVisible( false );
2918     }
2919     // get specified list of products being installed
2920     prodSequence.clear();
2921     for (int i = 0; i<(int)toInstall.count(); i++ ) {
2922       if ( extraProducts.contains( toInstall[i] ) ) {
2923         prodSequence.append( toInstall[i] );
2924         continue;
2925       }
2926       if ( installType == Binaries ) {
2927         prodSequence.append( toInstall[i] );
2928         QString prodType;
2929         MapProducts::Iterator mapIter;
2930         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2931           if ( mapIter.data().getName() == toInstall[i] && mapIter.data().getType() == "component" ) {
2932             prodSequence.append( toInstall[i] + "_src" );
2933             break;
2934           }
2935         }
2936       }
2937       else if ( installType == Sources )
2938         prodSequence.append( toInstall[i] + "_src" );
2939       else {
2940         prodSequence.append( toInstall[i] );
2941         prodSequence.append( toInstall[i] + "_src" );
2942       }
2943     }
2944
2945     // create a backup of 'env_build.csh', 'env_build.sh', 'env_products.csh', 'env_products.sh'
2946     // ( backup of 'salome.csh' and 'salome.sh' is made if pick-up environment is called )
2947     QDir rd( rootDirPath() );
2948     Script script;
2949     script << QUOTE( rd.filePath( "config_files/backupEnv.sh" ) );
2950     script << QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2951     ___MESSAGE___( "script = " << script.script().latin1() );
2952     if ( system( script.script().latin1() ) ) {
2953       if ( QMessageBox::warning( this,
2954                                  tr( "Warning" ),
2955                                  tr( "Backup environment files have not been created.\n"
2956                                      "Do you want to continue an installation process?" ),
2957                                  tr( "&Yes" ),
2958                                  tr( "&No" ), 
2959                                  QString::null, 0, 1 ) == 1 ) {
2960         // installation aborted
2961         abort();
2962         statusLab->setText( tr( "Installation has been aborted by user" ) );
2963         // enable <Next> button
2964         setNextEnabled( true );
2965         nextButton()->setText( tr( "&Start" ) );
2966         setAboutInfo( nextButton(), tr( "Start installation process" ) );
2967         // reconnect Next button - to use it as Start button
2968         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2969         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2970         connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2971         // enable <Back> button
2972         setBackEnabled( true );
2973         return;
2974       }
2975     }
2976
2977     // launch install script
2978     launchScript();
2979   }
2980 }
2981 // ================================================================
2982 /*!
2983  *  SALOME_InstallWizard::onReturnPressed
2984  *  Called when users tries to pass parameters for the script
2985  */
2986 // ================================================================
2987 void SALOME_InstallWizard::onReturnPressed()
2988 {
2989   QString txt = passedParams->text();
2990   installInfo->append( txt );
2991   txt += "\n";
2992   shellProcess->writeToStdin( txt );
2993   passedParams->clear();
2994   progressView->setFocus();
2995   passedParams->setEnabled( false );
2996   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2997 }
2998 /*!
2999   Callback function - as response for the script finishing
3000 */
3001 void SALOME_InstallWizard::productInstalled()
3002 {
3003   ___MESSAGE___( "process exited" );
3004   if ( shellProcess->normalExit() ) {
3005     ___MESSAGE___( "...normal exit" );
3006     // normal exit - try to proceed installation further
3007     launchScript();
3008   }
3009   else {
3010     ___MESSAGE___( "...abnormal exit" );
3011     statusLab->setText( tr( "Installation has been aborted" ) );
3012     // installation aborted
3013     abort();
3014     // clear script passed parameters lineedit
3015     passedParams->clear();
3016     passedParams->setEnabled( false );
3017     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
3018     installInfo->setFinished( true );
3019     // enable <Next> button
3020     setNextEnabled( true );
3021     nextButton()->setText( tr( "&Start" ) );
3022     setAboutInfo( nextButton(), tr( "Start installation process" ) );
3023     // reconnect Next button - to use it as Start button
3024     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
3025     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
3026     connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
3027     //nextButton()->setText( tr( "&Next >" ) );
3028     //setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
3029     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
3030     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
3031     //connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
3032     // enable <Back> button
3033     setBackEnabled( true );
3034   }
3035 }
3036 // ================================================================
3037 /*!
3038  *  SALOME_InstallWizard::tryTerminate
3039  *  Slot, called when <Cancel> button is clicked during installation script running
3040  */
3041 // ================================================================
3042 void SALOME_InstallWizard::tryTerminate()
3043 {
3044   if ( shellProcess->isRunning() ) {
3045     if ( QMessageBox::information( this,
3046                                    tr( "Exit" ),
3047                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
3048                                    tr( "&Yes" ),
3049                                    tr( "&No" ),
3050                                    QString::null,
3051                                    0,
3052                                    1 ) == 1 ) {
3053       return;
3054     }
3055     exitConfirmed = true;
3056     // if process still running try to terminate it first
3057     shellProcess->tryTerminate();
3058     abort();
3059     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
3060     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
3061   }
3062   else {
3063     // else just quit install wizard
3064     reject();
3065   }
3066 }
3067 // ================================================================
3068 /*!
3069  *  SALOME_InstallWizard::onCancel
3070  *  Kills installation process and quits application
3071  */
3072 // ================================================================
3073 void SALOME_InstallWizard::onCancel()
3074 {
3075   shellProcess->kill();
3076   modifyLaProc->kill();
3077   checkFLibProc->kill();
3078   reject();
3079 }
3080 // ================================================================
3081 /*!
3082  *  SALOME_InstallWizard::onSelectionChanged
3083  *  Called when selection is changed in the products list view
3084  *  to fill in the 'Information about product' text box
3085  */
3086 // ================================================================
3087 void SALOME_InstallWizard::onSelectionChanged()
3088 {
3089   const QObject* snd = sender();
3090   QListViewItem* item = modulesView->selectedItem();
3091   if ( snd == prereqsView )
3092     item = prereqsView->selectedItem();
3093   if ( !item )
3094     return;
3095   productInfo->clear();
3096   QCheckListItem* anItem = (QCheckListItem*)item;
3097   if ( !productsMap.contains( anItem ) )
3098     return;
3099   Dependancies dep = productsMap[ anItem ];
3100   QString text = "<b>" + anItem->text(0) + "</b>" + "<br>";
3101   if ( !dep.getVersion().isEmpty() )
3102     text += tr( "Version" ) + ": " + dep.getVersion() + "<br>";
3103   text += "<br>";
3104   if ( !dep.getDescription().isEmpty() ) {
3105     text += "<i>" + dep.getDescription() + "</i><br><br>";
3106   }
3107   /* AKL: 07/08/28 - hide required disk space for tmp files for each product ==>
3108      long tempSize = 0;
3109      tempSize = dep.getTempSize( installType );
3110      text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " KB<br>";
3111      AKL: 07/08/28 - hide required disk space for tmp files for each product <==
3112   */
3113   text += tr( "Disk space required" ) + ": " + item->text(1) + "<br>";
3114   text += "<br>";
3115   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
3116   text +=  tr( "Prerequisites" ) + ": " + req;
3117   productInfo->setText( text );
3118 }
3119 // ================================================================
3120 /*!
3121  *  SALOME_InstallWizard::onItemToggled
3122  *  Called when user checks/unchecks any product item
3123  *  Recursively sets all prerequisites and updates "Next" button state
3124  */
3125 // ================================================================
3126 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
3127 {
3128   if ( productsMap.contains( item ) ) {
3129     if ( item->isOn() )
3130       setPrerequisites( item );
3131     else 
3132       unsetPrerequisites( item );
3133   }
3134   onSelectionChanged();
3135   checkProductPage();
3136 }
3137 // ================================================================
3138 /*!
3139  *  SALOME_InstallWizard::wroteToStdin
3140  *  QProcess slot: -->something was written to stdin
3141  */
3142 // ================================================================
3143 void SALOME_InstallWizard::wroteToStdin( )
3144 {
3145   ___MESSAGE___( "Something was sent to stdin" );
3146 }
3147 // ================================================================
3148 /*!
3149  *  SALOME_InstallWizard::readFromStdout
3150  *  QProcess slot: -->something was written to stdout
3151  */
3152 // ================================================================
3153 void SALOME_InstallWizard::readFromStdout( )
3154 {
3155   ___MESSAGE___( "Something was sent to stdout" );
3156   QProcess* theProcess = ( QProcess* )sender();
3157   while ( theProcess->canReadLineStdout() ) {
3158     installInfo->append( QString( theProcess->readLineStdout() ) );
3159     installInfo->scrollToBottom();
3160   }
3161   QString str( theProcess->readStdout() );
3162   if ( !str.isEmpty() ) {
3163     installInfo->append( str );
3164     installInfo->scrollToBottom();
3165   }
3166 }
3167
3168 #define OUTLINE_TEXT(x) QString( "<font color=#FF0000><b>" ) + QString( x ) + QString( "</b></font>" )
3169
3170 // ================================================================
3171 /*!
3172  *  SALOME_InstallWizard::readFromStderr
3173  *  QProcess slot: -->something was written to stderr
3174  */
3175 // ================================================================
3176 void SALOME_InstallWizard::readFromStderr( )
3177 {
3178   ___MESSAGE___( "Something was sent to stderr" );
3179   QProcess* theProcess = ( QProcess* )sender();
3180   while ( theProcess->canReadLineStderr() ) {
3181     installInfo->append( OUTLINE_TEXT( QString( theProcess->readLineStderr() ) ) );
3182     installInfo->scrollToBottom();
3183     hasErrors = true;
3184   }
3185   QString str( theProcess->readStderr() );
3186   if ( !str.isEmpty() ) {
3187     installInfo->append( OUTLINE_TEXT( str ) );
3188     installInfo->scrollToBottom();
3189     hasErrors = true;
3190   }
3191   // VSR: 10/11/05 - disable answer mode ==>
3192   // passedParams->setEnabled( true );
3193   // passedParams->setFocus();
3194   // QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
3195   // VSR: 10/11/05 - disable answer mode <==
3196 }
3197 // ================================================================
3198 /*!
3199  *  SALOME_InstallWizard::setDependancies
3200  *  Sets dependancies for the product item
3201  */
3202 // ================================================================
3203 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
3204 {
3205   productsMap[item] = dep;
3206 }
3207 // ================================================================
3208 /*!
3209  *  SALOME_InstallWizard::addFinishButton
3210  *  Add button for the <Finish> page.
3211  *  Clear list of buttons if <toClear> flag is true.
3212  */
3213 // ================================================================
3214 void SALOME_InstallWizard::addFinishButton( const QString& label,
3215                                             const QString& tooltip,
3216                                             const QString& script,
3217                                             bool toClear )
3218 {
3219   ButtonList btns;
3220   if ( toClear ) {
3221     btns = buttons;
3222     buttons.clear();
3223   }
3224   buttons.append( Button( label, tooltip, script ) );
3225   // create finish buttons
3226   QButton* b = new QPushButton( tr( buttons.last().label() ), readmePage );
3227   if ( !buttons.last().tootip().isEmpty() )
3228     setAboutInfo( b, tr( buttons.last().tootip() ) );
3229   QHBoxLayout* hLayout = (QHBoxLayout*)readmePage->layout()->child("finishButtons");
3230   if ( toClear ) {
3231     // remove previous buttons
3232     ButtonList::Iterator it;
3233     for ( it = btns.begin(); it != btns.end(); ++it ) {
3234       hLayout->removeChild( (*it).button() );
3235       delete (*it).button();
3236     }
3237   }
3238   // add buttons to finish page
3239   hLayout->insertWidget( buttons.count()-1, b );
3240   buttons.last().setButton( b );
3241   connect( b, SIGNAL( clicked() ), this, SLOT( onFinishButton() ) );
3242 }
3243 // ================================================================
3244 /*!
3245  *  SALOME_InstallWizard::polish
3246  *  Polishing of the widget - to set right initial size
3247  */
3248 // ================================================================
3249 void SALOME_InstallWizard::polish()
3250 {
3251   resize( 0, 0 );
3252   InstallWizard::polish();
3253 }
3254 // ================================================================
3255 /*!
3256  *  SALOME_InstallWizard::saveLog
3257  *  Save installation log to file
3258  */
3259 // ================================================================
3260 void SALOME_InstallWizard::saveLog()
3261 {
3262   QString txt = installInfo->text();
3263   if ( txt.length() <= 0 )
3264     return;
3265   QDateTime dt = QDateTime::currentDateTime();
3266   QString fileName = dt.toString("ddMMyy-hhmm");
3267   fileName.prepend("install-"); fileName.append(".html");
3268   fileName = QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ), fileName ).absFilePath();
3269   fileName = QFileDialog::getSaveFileName( fileName,
3270                                            QString( "HTML files (*.htm *.html)" ),
3271                                            this, 0,
3272                                            tr( "Save Log file" ) );
3273   if ( !fileName.isEmpty() ) {
3274     QFile f( fileName );
3275     if ( f.open( IO_WriteOnly ) ) {
3276       QTextStream stream( &f );
3277       stream << txt;
3278       f.close();
3279     }
3280     else {
3281       QMessageBox::critical( this,
3282                              tr( "Error" ),
3283                              tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ),
3284                              QMessageBox::Ok,
3285                              QMessageBox::NoButton,
3286                              QMessageBox::NoButton );
3287     }
3288   }
3289 }
3290 // ================================================================
3291 /*!
3292  *  SALOME_InstallWizard::updateCaption
3293  *  Updates caption according to the current page number
3294  */
3295 // ================================================================
3296 void SALOME_InstallWizard::updateCaption()
3297 {
3298   QWidget* aPage = InstallWizard::currentPage();
3299   if ( !aPage )
3300     return;
3301   InstallWizard::setCaption( tr( myCaption ) + " " +
3302                              tr( getIWName() ) + " - " +
3303                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
3304 }
3305
3306 // ================================================================
3307 /*!
3308  *  SALOME_InstallWizard::processValidateEvent
3309  *  Processes validation event (<val> is validation code)
3310  */
3311 // ================================================================
3312 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
3313 {
3314   QWidget* aPage = InstallWizard::currentPage();
3315   if ( aPage != productsPage ) {
3316     InstallWizard::processValidateEvent( val, data );
3317     return;
3318   }
3319   myMutex.lock();
3320   myMutex.unlock();
3321   if ( val > 0 ) {
3322   }
3323   if ( myThread->hasCommands() )
3324     myWC.wakeAll();
3325   else {
3326     WarnDialog::showWarnDlg( 0, false );
3327     InstallWizard::processValidateEvent( val, data );
3328   }
3329 }