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