Salome HOME
e4e97d018b506872ef6d3b69c3e7ffe1913ab352
[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.6" );
515   setCaption( tr( "SALOME %1" ).arg( myVersion ) );
516   setCopyright( tr( "Copyright (C) 2007 CEA" ) );
517   setLicense( tr( "All right 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 QMyCheckBox( 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->setState( QButton::Off );
913   removeSrcBtn->setEnabled( false );
914
915   srcCompileLayout->addMultiCellWidget( srcCompileBtn,  0, 0, 0, 2 );
916   srcCompileLayout->addMultiCell      ( spacer6,        1, 2, 0, 0 );
917   srcCompileLayout->addMultiCellWidget( srcCompileLab1, 1, 1, 1, 2 );
918   srcCompileLayout->addWidget         ( srcCompileLab2, 2,    1    );
919   srcCompileLayout->addWidget         ( srcCompileLab3, 2,    2    );
920   srcCompileLayout->addMultiCellWidget( removeSrcBtn,   3, 3, 1, 2 );
921   // layout widgets in the button group
922   buttonGrpLayout->addItem           ( spacer1,          0,    1    );
923   buttonGrpLayout->addMultiCellWidget( selectLab,        1, 1, 0, 1 );
924   buttonGrpLayout->addMultiCell      ( spacer3,          2, 4, 0, 0 );
925   buttonGrpLayout->addLayout         ( binLayout,        2,    1    );
926   buttonGrpLayout->addLayout         ( srcLayout,        3,    1    );
927   buttonGrpLayout->addLayout         ( srcCompileLayout, 4,    1    );
928   buttonGrpLayout->addItem           ( spacer2,          5,    1    );
929   // layout button group at the page
930   pageLayout->addWidget( buttonGrp, 0, 0 );
931   // connecting signals
932   connect( buttonGrp, SIGNAL( clicked(int) ), this, SLOT ( onButtonGroup(int) ) );
933   connect( removeSrcBtn,  SIGNAL( toggled( bool ) ), this, SLOT( onRemoveSrcBtn() ) );
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 ( productsMap[ item ].hasType( "salome sources" ) || 
1327            productsMap[ item ].hasType( "salome binaries" ) ) {
1328         item = (QCheckListItem*)( item->nextSibling() );
1329         continue; // skip SALOME sources and binaries
1330       }
1331       if ( item->isOn() ) {
1332         text += "<li><b>" + item->text() + " " + productsMap[ item ].getVersion() + "</b><br>";
1333         nbProd++;
1334       }
1335     }
1336     item = (QCheckListItem*)( item->nextSibling() );
1337   }
1338   if ( nbProd == 0 ) {
1339     text += "<li><b>" + tr( "none" ) + "</b><br>";
1340   }
1341   text += "</ul>";
1342   text += tr( "Total disk space required:" ) + " <b>" + QString::number( totSize ) + " KB</b><br>" ;
1343   text += tr( "Space for temporary files required:" ) + " <b>" + QString::number( tempSize ) + " KB</b><br>" ;
1344   choices->setText( text );
1345 }
1346 // ================================================================
1347 /*!
1348  *  SALOME_InstallWizard::acceptData
1349  *  Validates page when <Next> button is clicked
1350  */
1351 // ================================================================
1352 bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
1353 {
1354   QString tmpstr;
1355   QWidget* aPage = InstallWizard::page( pageTitle );
1356   if ( aPage == typePage ) {
1357     // installation type page
1358     if ( installType == Binaries ) { // 'Binary' installation type
1359       // check binaries directory
1360       QFileInfo fib( QDir::cleanDirPath( getBinPath() ) );
1361       if ( !fib.exists() ) {
1362         QMessageBox::warning( this,
1363                               tr( "Warning" ),
1364                               tr( "The directory %1 doesn't exist.\n"
1365                                   "This directory must contain sources archives.\n").arg( fib.absFilePath() ),
1366                               QMessageBox::Ok,
1367                               QMessageBox::NoButton, 
1368                               QMessageBox::NoButton );
1369         return false;
1370       }
1371       // check sources directory
1372       QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
1373       if ( !fis.exists() )
1374         if ( QMessageBox::warning( this,
1375                                    tr( "Warning" ),
1376                                    tr( "The directory %1 doesn't exist.\n"
1377                                        "This directory must contain sources archives.\n"
1378                                        "Continue?" ).arg( fis.absFilePath() ),
1379                                    tr( "&Yes" ),
1380                                    tr( "&No" ), 
1381                                    QString::null, 1, 1 ) == 1 )
1382           return false;
1383     }
1384     else { // 'Source' or 'Compile' installation type
1385       // check sources directory
1386       QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
1387       if ( !fis.exists() ) {
1388         QMessageBox::warning( this,
1389                               tr( "Warning" ),
1390                               tr( "The directory %1 doesn't exist.\n"
1391                                   "This directory must contain sources archives.\n" ).arg( fis.absFilePath() ),
1392                               QMessageBox::Ok,
1393                               QMessageBox::NoButton, 
1394                               QMessageBox::NoButton );
1395         return false;
1396       }
1397     }
1398   }
1399
1400   else if ( aPage == dirPage ) {
1401     // installation platform page
1402     // ########## check target and temp directories (existence and available disk space)
1403     // get dirs
1404     QString targetDir = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1405     QString tempDir   = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() );
1406     // check target directory
1407     if ( targetDir.isEmpty() ) {
1408       QMessageBox::warning( this,
1409                             tr( "Warning" ),
1410                             tr( "Please, enter valid target directory path" ),
1411                             QMessageBox::Ok,
1412                             QMessageBox::NoButton,
1413                             QMessageBox::NoButton );
1414       return false;
1415     }
1416     QFileInfo fi( QDir::cleanDirPath( targetDir ) );
1417     if ( !fi.exists() ) {
1418       bool toCreate =
1419         QMessageBox::warning( this,
1420                               tr( "Warning" ),
1421                               tr( "The directory %1 doesn't exist.\n"
1422                                   "Create directory?" ).arg( fi.absFilePath() ),
1423                               QMessageBox::Yes,
1424                               QMessageBox::No,
1425                               QMessageBox::NoButton ) == QMessageBox::Yes;
1426       if ( !toCreate)
1427         return false;
1428       if ( !makeDir( fi.absFilePath(), tmpstr ) ) {
1429         QMessageBox::critical( this,
1430                                tr( "Error" ),
1431                                tr( "Can't create the directory\n%1").arg( fi.absFilePath() ),
1432                                QMessageBox::Ok,
1433                                QMessageBox::NoButton,
1434                                QMessageBox::NoButton );
1435         return false;
1436       }
1437     }
1438     if ( !fi.isDir() ) {
1439       QMessageBox::warning( this,
1440                             tr( "Warning" ),
1441                             tr( "%1 is not a directory.\n"
1442                                 "Please, enter valid target directory path" ).arg( fi.absFilePath() ),
1443                             QMessageBox::Ok,
1444                             QMessageBox::NoButton,
1445                             QMessageBox::NoButton );
1446       return false;
1447     }
1448     if ( !fi.isWritable() ) {
1449       QMessageBox::warning( this,
1450                             tr( "Warning" ),
1451                             tr( "The directory %1 is not writeable.\n"
1452                                 "Please, enter valid target directory path or change permissions" ).arg( fi.absFilePath() ),
1453                             QMessageBox::Ok,
1454                             QMessageBox::NoButton,
1455                             QMessageBox::NoButton );
1456       return false;
1457     }
1458     if ( hasSpace( fi.absFilePath() ) &&
1459          QMessageBox::warning( this,
1460                                tr( "Warning" ),
1461                                tr( "The target directory contains space symbols.\n"
1462                                    "This may cause problems with compiling or installing of products.\n\n"
1463                                    "Do you want to continue?"),
1464                                QMessageBox::Yes,
1465                                QMessageBox::No,
1466                                QMessageBox::NoButton ) == QMessageBox::No ) {
1467       return false;
1468     }
1469     // check temp directory
1470     if ( tempDir.isEmpty() ) {
1471       QMessageBox::warning( this,
1472                             tr( "Warning" ),
1473                             tr( "Please, enter valid temporary directory path" ),
1474                             QMessageBox::Ok,
1475                             QMessageBox::NoButton,
1476                             QMessageBox::NoButton );
1477       return false;
1478     }
1479     QFileInfo fit( QDir::cleanDirPath( tempDir ) );
1480     if ( !makeDir( fit.absFilePath() + TEMPDIRNAME, tmpCreated ) ) {
1481       QMessageBox::critical( this,
1482                              tr( "Error" ),
1483                              tr( "Can't use temporary directory.\nCheck permissions for the %1 directory.").arg( fit.absFilePath() ),
1484                              QMessageBox::Ok,
1485                              QMessageBox::NoButton,
1486                              QMessageBox::NoButton );
1487       return false;
1488     }
1489   }
1490
1491   else if ( aPage == productsPage ) {
1492     // products page
1493     // ########## check if any products are selected to be installed
1494     long totSize, tempSize;
1495     bool anySelected = checkSize( &totSize, &tempSize );
1496     if ( installType == Compile && removeSrcBtn->state() == QButton::On ) {
1497       totSize += tempSize;
1498     }
1499     if ( !anySelected ) {
1500       QMessageBox::warning( this,
1501                             tr( "Warning" ),
1502                             tr( "Select one or more products to install" ),
1503                             QMessageBox::Ok,
1504                             QMessageBox::NoButton,
1505                             QMessageBox::NoButton );
1506       return false;
1507     }
1508     // run script that checks available disk space for installing of products    // returns 1 in case of error
1509     QFileInfo fi( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) );
1510     QString script = "./config_files/checkSize.sh '";
1511     script += fi.absFilePath();
1512     script += "' ";
1513     script += QString( "%1" ).arg( totSize );
1514     ___MESSAGE___( "script = " << script.latin1() );
1515     if ( system( script ) ) {
1516       QMessageBox::critical( this,
1517                              tr( "Out of space" ),
1518                              tr( "There is no available disk space for installing of selected products" ),
1519                              QMessageBox::Ok,
1520                              QMessageBox::NoButton,
1521                              QMessageBox::NoButton );
1522       return false;
1523     }
1524     // AKL: 13/08/07 - skip tmp disk space checking (all files are unpacked into installation directory) ==>
1525     /*
1526     // run script that check available disk space for temporary files
1527     // returns 1 in case of error
1528     QFileInfo fit( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) );
1529     QString tscript = "./config_files/checkSize.sh '";
1530     tscript += fit.absFilePath();
1531     tscript += "' ";
1532     tscript += QString( "%1" ).arg( tempSize );
1533     ___MESSAGE___( "script = " << tscript.latin1() );
1534     if ( system( tscript ) ) {
1535       QMessageBox::critical( this,
1536                              tr( "Out of space" ),
1537                              tr( "There is no available disk space for the temporary files" ),
1538                              QMessageBox::Ok,
1539                              QMessageBox::NoButton,
1540                              QMessageBox::NoButton );
1541       return false;
1542       }
1543     */
1544     // AKL: 13/08/07 - skip tmp disk space checking (all files are unpacked into installation directory) <==
1545
1546     // ########## check installation scripts
1547     QCheckListItem* item;
1548     ProductsView* prodsView = modulesView;
1549     for ( int i = 0; i < 2; i++ ) {
1550       item = (QCheckListItem*)( prodsView->firstChild() );
1551       while( item ) {
1552         if ( productsMap.contains( item ) && item->isOn() ) {
1553           // check installation script definition
1554           if ( item->text(2).isEmpty() || item->text(2).isNull() ) {
1555             QMessageBox::warning( this,
1556                                   tr( "Error" ),
1557                                   tr( "The installation script for %1 is not defined.").arg(item->text(0)),
1558                                   QMessageBox::Ok,
1559                                   QMessageBox::NoButton,
1560                                   QMessageBox::NoButton );
1561             if ( !moreMode ) onMoreBtn();
1562             QListView* listView = item->listView();
1563             listView->setCurrentItem( item );
1564             listView->setSelected( item, true );
1565             listView->ensureItemVisible( item );
1566             return false;
1567           }
1568           // check installation script existence
1569           else {
1570             QFileInfo fi( QString("./config_files/") + item->text(2) );
1571             if ( !fi.exists() || !fi.isExecutable() ) {
1572               QMessageBox::warning( this,
1573                                     tr( "Error" ),
1574                                     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)),
1575                                     QMessageBox::Ok,
1576                                     QMessageBox::NoButton,
1577                                     QMessageBox::NoButton );
1578               if ( !moreMode ) onMoreBtn();
1579               QListView* listView = item->listView();
1580               listView->setCurrentItem( item );
1581               listView->setSelected( item, true );
1582               listView->ensureItemVisible( item );
1583               return false;
1584             }
1585           }
1586           // check installation scripts dependencies
1587           QStringList dependOn = productsMap[ item ].getDependancies();
1588           QString version = productsMap[ item ].getVersion();
1589           for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1590             QCheckListItem* depitem = findItem( dependOn[ i ] );
1591             if ( !depitem ) {
1592               QMessageBox::warning( this,
1593                                     tr( "Error" ),
1594                                     tr( "%1 is required for %2 %3 installation.\n"
1595                                         "This product is missing in the configuration file %4.").arg(dependOn[ i ]).arg(item->text(0)).arg(version).arg(xmlFileName),
1596                                     QMessageBox::Ok,
1597                                     QMessageBox::NoButton,
1598                                     QMessageBox::NoButton );
1599               return false;
1600             }
1601           }
1602         }
1603         item = (QCheckListItem*)( item->nextSibling() );
1604       }
1605       prodsView = prereqsView;
1606     }
1607 //     return true; // return in order to avoid default postValidateEvent() action
1608   }
1609   return InstallWizard::acceptData( pageTitle );
1610 }
1611 // ================================================================
1612 /*!
1613  *  SALOME_InstallWizard::checkSize
1614  *  Calculates disk space required for the installation
1615  */
1616 // ================================================================
1617 bool SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
1618 {
1619   long tots = 0, temps = 0;
1620   long maxSrcTmp = 0;
1621   int nbSelected = 0;
1622
1623   MapProducts::Iterator mapIter;
1624   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1625     QCheckListItem* item = mapIter.key();
1626     Dependancies dep = mapIter.data();
1627     if ( !item->isOn() )
1628       continue;
1629     if ( installType == Compile && removeSrcBtn->state() == QButton::On )
1630       tots += dep.getSize( Binaries );
1631     else
1632       tots += dep.getSize( installType );
1633     maxSrcTmp = max( maxSrcTmp, dep.getSize( Compile ) - dep.getSize( Binaries ) );
1634     temps += dep.getTempSize( installType );
1635     nbSelected++;
1636   }
1637
1638   if ( totSize )
1639     if ( installType == Compile && removeSrcBtn->state() == QButton::On )
1640       temps += maxSrcTmp;
1641     *totSize = tots;
1642   if ( tempSize )
1643     *tempSize = temps;
1644   return ( nbSelected > 0 );
1645 }
1646 // ================================================================
1647 /*!
1648  *  SALOME_InstallWizard::updateAvailableSpace
1649  *  Slot to update 'Available disk space' field
1650  */
1651 // ================================================================
1652 void SALOME_InstallWizard::updateAvailableSpace()
1653 {
1654   if ( diskSpaceProc->normalExit() )
1655     availableSize->setText( diskSpaceProc->readLineStdout() + " KB");
1656 }
1657 // ================================================================
1658 /*!
1659  *  SALOME_InstallWizard::checkFLibResult
1660  *  Slot to take result of Fortran libraries checking
1661  */
1662 // ================================================================
1663 void SALOME_InstallWizard::checkFLibResult()
1664 {
1665   if ( checkFLibProc->normalExit() && checkFLibProc->exitStatus() == 1 ) {
1666     QStringList notFoundLibsList;
1667     QString record = "";
1668     while ( checkFLibProc->canReadLineStdout() ) {
1669       record = checkFLibProc->readLineStdout();
1670       if ( !record.isEmpty() && !notFoundLibsList.contains( record ) )
1671         notFoundLibsList.append( record );
1672     }
1673     QMessageBox::warning( this,
1674                           tr( "Warning" ),
1675                           tr( "The following libraries are absent on current system:\n"
1676                           "%1").arg( notFoundLibsList.join( "\n" ) ),
1677                           QMessageBox::Ok,
1678                           QMessageBox::NoButton,
1679                           QMessageBox::NoButton );
1680   }
1681   // Update GUI and check installation errors
1682   completeInstallation();
1683 }
1684 // ================================================================
1685 /*!
1686  *  SALOME_InstallWizard::checkProductPage
1687  *  Checks products page validity (directories and products selection) and
1688  *  enabled/disables "Next" button for the Products page
1689  */
1690 // ================================================================
1691 void SALOME_InstallWizard::checkProductPage()
1692 {
1693   if ( this->currentPage() != productsPage )
1694     return;
1695   long tots = 0, temps = 0;
1696   // check if any product is selected;
1697   bool isAnyProductSelected = checkSize( &tots, &temps );
1698
1699   // update required size information
1700   requiredSize->setText( QString::number( tots )  + " KB");
1701   requiredTemp->setText( QString::number( temps ) + " KB");
1702
1703   // update available size information
1704   QFileInfo fi( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) );
1705   if ( fi.exists() ) {
1706     diskSpaceProc->clearArguments();
1707     QString script = "./config_files/diskSpace.sh";
1708     diskSpaceProc->addArgument( script );
1709     diskSpaceProc->addArgument( fi.absFilePath() );
1710     // run script
1711     diskSpaceProc->start();
1712   }
1713
1714   // enable/disable "Next" button
1715   setNextEnabled( productsPage, isAnyProductSelected );
1716 }
1717 // ================================================================
1718 /*!
1719  *  SALOME_InstallWizard::setPrerequisites
1720  *  Sets the product and all products this one depends on to be checked ( recursively )
1721  */
1722 // ================================================================
1723 void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
1724 {
1725   if ( !productsMap.contains( item ) )
1726     return;
1727   if ( !item->isOn() )
1728     return;
1729   // get all prerequisites
1730   QStringList dependOn = productsMap[ item ].getDependancies();
1731   // install MED without GUI case
1732   if ( installGuiBtn->state() != QButton::On && item->text(0) == "MED" ) {
1733     dependOn.remove( "GUI" );
1734   }
1735   // setting prerequisites
1736   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1737     MapProducts::Iterator itProd;
1738     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1739       if ( itProd.data().getName() == dependOn[ i ] ) {
1740         if ( itProd.data().getType() == "component" && !itProd.key()->isOn() )
1741           itProd.key()->setOn( true );
1742         else if ( itProd.data().getType() == "prerequisite" ) {
1743           itProd.key()->setOn( true );
1744           itProd.key()->setEnabled( false );
1745         }
1746       }
1747     }
1748   }
1749 }
1750 // ================================================================
1751 /*!
1752  *  SALOME_InstallWizard::unsetPrerequisites
1753  *  Unsets all modules which depend of the unchecked product ( recursively )
1754  */
1755 // ================================================================
1756 void SALOME_InstallWizard::unsetPrerequisites( QCheckListItem* item )
1757 {
1758   if ( !productsMap.contains( item ) )
1759     return;
1760   if ( item->isOn() )
1761     return;
1762
1763 // uncheck dependent products
1764   QString itemName = productsMap[ item ].getName();
1765   MapProducts::Iterator itProd;
1766   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1767     if ( itProd.data().getType() == productsMap[ item ].getType() ) {
1768       QStringList dependOn = itProd.data().getDependancies();
1769       // install MED without GUI case
1770       if ( installGuiBtn->state() != QButton::On && itemName == "GUI" ) {
1771         dependOn.remove( "MED" );
1772       }
1773       for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1774         if ( dependOn[ i ] == itemName ) {
1775           if ( itProd.key()->isOn() ) {
1776             itProd.key()->setOn( false );
1777           }
1778         }
1779       }
1780     }
1781   }
1782
1783 // uncheck prerequisites
1784   int nbDependents;
1785 //   cout << "item name = " << productsMap[ item ].getName() << endl;
1786   QStringList dependOnList = productsMap[ item ].getDependancies();
1787   for ( int j = 0; j < (int)dependOnList.count(); j++ ) {
1788     nbDependents = 0;
1789     MapProducts::Iterator itProd1;
1790     for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
1791       if ( itProd1.data().getName() == dependOnList[ j ] ) {
1792         if ( itProd1.data().getType() == "prerequisite" ) {
1793           MapProducts::Iterator itProd2;
1794           for ( itProd2 = productsMap.begin(); itProd2 != productsMap.end(); ++itProd2 ) {
1795             //      if ( itProd2.data().getType() == "component" ) {
1796             if ( itProd2.key()->isOn() ) {
1797               QStringList prereqsList = productsMap[ itProd2.key() ].getDependancies();
1798               for ( int k = 0; k < (int)prereqsList.count(); k++ ) {
1799                 if ( prereqsList[ k ] == itProd1.data().getName() ) {
1800                   nbDependents++;
1801                 }
1802               }
1803             }
1804           }
1805           if ( nbDependents == 0 ) {
1806             itProd1.key()->setEnabled( true );
1807             itProd1.key()->setOn( false );
1808           }
1809         }
1810       }
1811     }
1812   }
1813 }
1814 // ================================================================
1815 /*!
1816  *  SALOME_InstallWizard::launchScript
1817  *  Runs installation script
1818  */
1819 // ================================================================
1820 void SALOME_InstallWizard::launchScript()
1821 {
1822   // try to find product being processed now
1823   QString prodProc = progressView->findStatus( Processing );
1824   if ( !prodProc.isNull() ) {
1825     ___MESSAGE___( "Found <Processing>: " );
1826
1827     // if found - set status to "completed"
1828     progressView->setStatus( prodProc, Completed );
1829     // ... clear status label
1830     statusLab->clear();
1831     // ... and call this method again
1832     launchScript();
1833     return;
1834   }
1835   // else try to find next product which is not processed yet
1836   prodProc = progressView->findStatus( Waiting );
1837   if ( !prodProc.isNull() ) {
1838     ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
1839     // if found - set status to "processed" and run script
1840     progressView->setStatus( prodProc, Processing );
1841     progressView->ensureVisible( prodProc );
1842     
1843     QCheckListItem* item;
1844     if ( prodProc != "gcc" )
1845       item = findItem( prodProc );
1846     // fill in script parameters
1847     shellProcess->clearArguments();
1848     // ... script name
1849     shellProcess->setWorkingDirectory( QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() ) );
1850     if ( prodProc != "gcc" )
1851       shellProcess->addArgument( item->text(2) );
1852     else
1853       shellProcess->addArgument( "gcc-common.sh" );
1854
1855     // ... temp folder
1856     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1857     //if( !tempFolder->isEnabled() )
1858     //  tmpFolder = "/tmp";
1859
1860     // ... not install : try to find preinstalled
1861     if ( !progressView->isVisible( prodProc ) ) {
1862       shellProcess->addArgument( "try_preinstalled" );
1863       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1864       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1865       statusLab->setText( tr( "Collecting environment for '" ) + prodProc + "'..." );
1866     }
1867     // ... binaries ?
1868     else if ( installType == Binaries ) {
1869       shellProcess->addArgument( "install_binary" );
1870       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1871       QString binDir = QDir::cleanDirPath( getBinPath() );
1872       QString OS = getPlatform();
1873       if ( !OS.isEmpty() )
1874         binDir += "/" + OS;
1875       shellProcess->addArgument( binDir );
1876       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
1877     }
1878     // ... sources or sources_and_compilation ?
1879     else {
1880       shellProcess->addArgument( installType == Sources ? "install_source" : 
1881                                  "install_source_and_build" );
1882       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1883       shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
1884       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
1885     }
1886     // ... target folder
1887     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1888     shellProcess->addArgument( QFileInfo( tgtFolder ).absFilePath() );
1889     // ... list of all products
1890     QString depproducts = DefineDependeces(productsMap);
1891     depproducts.prepend( "gcc " );
1892     ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
1893     shellProcess->addArgument( depproducts );
1894     // ... product name - currently installed product
1895     if ( prodProc != "gcc" )
1896       shellProcess->addArgument( item->text(0) );
1897     else
1898       shellProcess->addArgument( "gcc" );
1899     // ... list of products being installed
1900     shellProcess->addArgument( prodSequence.join( " " ) );
1901     // ... sources directory
1902     shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
1903     // ... remove sources and tmp files or not?
1904     if ( installType == Compile && removeSrcBtn->state() == QButton::On )
1905       shellProcess->addArgument( "TRUE" );
1906     else 
1907       shellProcess->addArgument( "FALSE" );
1908     // ... install MED with GUI or not?
1909     if ( installGuiBtn->state() != QButton::On && prodProc == "MED" && 
1910          (installType == Binaries || installType == Compile) )
1911       shellProcess->addArgument( "FALSE" );
1912     // run script
1913     if ( !shellProcess->start() ) {
1914       // error handling can be here
1915       ___MESSAGE___( "error" );
1916     }
1917     return;
1918   }
1919   ___MESSAGE___( "All products have been installed successfully" );
1920   // all products are installed successfully
1921   MapProducts::Iterator mapIter;
1922   ___MESSAGE___( "starting pick-up environment" );
1923   QString depproducts = QUOTE( DefineDependeces(productsMap).prepend( "gcc " ) );
1924   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1925     QCheckListItem* item = mapIter.key();
1926     Dependancies dep = mapIter.data();
1927     if ( item->isOn() && dep.pickUpEnvironment() ) {
1928       statusLab->setText( tr( "Pick-up products environment for " ) + dep.getName().latin1() + "..." );
1929       ___MESSAGE___( "... for " << dep.getName().latin1() );
1930       QString script;
1931       script += "cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
1932       script += item->text(2) + " ";
1933       script += "pickup_env ";
1934       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
1935       script += QUOTE( QFileInfo( QDir::cleanDirPath( QDir::currentDirPath() + "/Products" ) ).absFilePath() ) + " ";
1936       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
1937       script += depproducts + " ";
1938       script += item->text(0) + " ";
1939       script += QUOTE( prodSequence.join( " " ) );
1940       ___MESSAGE___( "... --> " << script.latin1() );
1941       if ( system( script.latin1() ) ) {
1942         ___MESSAGE___( "ERROR" );
1943       }
1944     }
1945   }
1946   
1947   if ( installType == Binaries ) {
1948     // Check Fortran libraries
1949     // ... update status label
1950     statusLab->setText( tr( "Check Fortran libraries..." ) );
1951     // ... search "not found" libraries
1952     checkFLibProc->setWorkingDirectory( QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() ) );
1953     checkFLibProc->addArgument( "checkFortran.sh" );
1954     checkFLibProc->addArgument( "find_libraries" );
1955     checkFLibProc->addArgument( QDir::cleanDirPath( QFileInfo( targetFolder->text().stripWhiteSpace() ).absFilePath() ) );
1956     // ... run script
1957     if ( !checkFLibProc->start() ) {
1958       ___MESSAGE___( "Error: process could not start!" );
1959     }
1960   }
1961   else
1962     // Update GUI and check installation errors
1963     completeInstallation();
1964   
1965 }
1966 // ================================================================
1967 /*!
1968  *  SALOME_InstallWizard::completeInstallation
1969  *  Update GUI and check installation errors
1970  */
1971 // ================================================================
1972 void SALOME_InstallWizard::completeInstallation()
1973 {
1974   // update status label
1975   statusLab->setText( tr( "Installation completed" ) );
1976   // <Next> button
1977   setNextEnabled( true );
1978   nextButton()->setText( tr( "&Next >" ) );
1979   setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
1980   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1981   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1982   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1983   // <Back> button
1984   setBackEnabled( true );
1985   // script parameters
1986   passedParams->clear();
1987   passedParams->setEnabled( false );
1988   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1989   installInfo->setFinished( true );
1990   if ( isMinimized() )
1991     showNormal();
1992   raise();
1993   if ( hasErrors ) {
1994     if ( QMessageBox::warning( this,
1995                                tr( "Warning" ),
1996                                tr( "There were some errors and/or warnings during the installation.\n"
1997                                    "Do you want to save the installation log?" ),
1998                                tr( "&Save" ),
1999                                tr( "&Cancel" ),
2000                                QString::null,
2001                                0,
2002                                1 ) == 0 )
2003       saveLog();
2004   }
2005   hasErrors = false;
2006
2007 }
2008 // ================================================================
2009 /*!
2010  *  SALOME_InstallWizard::onInstallGuiBtn
2011  *  <Installation with GUI> check-box slot
2012  */
2013 // ================================================================
2014 void SALOME_InstallWizard::onInstallGuiBtn()
2015 {
2016   MapProducts::Iterator itProd;
2017   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2018     if ( itProd.data().getType() == "component" ) {
2019       if ( installGuiBtn->state() == QButton::On ) {
2020         itProd.key()->setEnabled( true );
2021         itProd.key()->setOn( true );
2022       }
2023       else {
2024         QString itemName = itProd.data().getName();
2025         if ( itemName != "KERNEL" && itemName != "MED" && itemName != "SAMPLES" ) {
2026           itProd.key()->setOn( false );
2027           itProd.key()->setEnabled( false );
2028         }
2029         else
2030           itProd.key()->setOn( true );
2031       }
2032     }
2033   }
2034 }
2035 // ================================================================
2036 /*!
2037  *  SALOME_InstallWizard::onMoreBtn
2038  *  <More...> button slot
2039  */
2040 // ================================================================
2041 void SALOME_InstallWizard::onMoreBtn()
2042 {
2043   if ( moreMode ) {
2044     prereqsView->hide();
2045     moreBtn->setText( tr( "Show prerequisites..." ) );
2046     setAboutInfo( moreBtn, tr( "Show list of prerequisites" ) );
2047   }
2048   else {
2049     prereqsView->show();
2050     moreBtn->setText( tr( "Hide prerequisites" ) );
2051     setAboutInfo( moreBtn, tr( "Hide list of prerequisites" ) );
2052   }
2053   qApp->processEvents();
2054   moreMode = !moreMode;
2055   InstallWizard::layOut();
2056   qApp->processEvents();
2057   if ( !isMaximized() ) {
2058     qApp->processEvents();
2059   }
2060   checkProductPage();
2061 }
2062 // ================================================================
2063 /*!
2064  *  SALOME_InstallWizard::onFinishButton
2065  *  Operation buttons slot
2066  */
2067 // ================================================================
2068 void SALOME_InstallWizard::onFinishButton()
2069 {
2070   const QObject* btn = sender();
2071   ButtonList::Iterator it;
2072   for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2073     if ( (*it).button() && (*it).button() == btn ) {
2074       QString script;
2075       script += "( cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
2076       script +=  + (*it).script();
2077       script += " execute ";
2078       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
2079       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
2080       script += " > /dev/null )";
2081       ___MESSAGE___( "script: " << script.latin1() );
2082       if ( (*it).script().isEmpty() || system( script.latin1() ) ) {
2083         QMessageBox::warning( this,
2084                               tr( "Error" ),
2085                               tr( "Can't perform action!"),
2086                               QMessageBox::Ok,
2087                               QMessageBox::NoButton,
2088                               QMessageBox::NoButton );
2089       }
2090       return;
2091     }
2092   }
2093 }
2094 // ================================================================
2095 /*!
2096  *  SALOME_InstallWizard::onAbout
2097  *  <About> button slot: shows <About> dialog box
2098  */
2099 // ================================================================
2100 void SALOME_InstallWizard::onAbout()
2101 {
2102   AboutDlg d( this );
2103   d.exec();
2104 }
2105
2106 // ================================================================
2107 /*!
2108  *  SALOME_InstallWizard::findItem
2109  *  Searches product listview item with given symbolic name
2110  */
2111 // ================================================================
2112 QCheckListItem* SALOME_InstallWizard::findItem( const QString& sName )
2113 {
2114   MapProducts::Iterator mapIter;
2115   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2116     if ( mapIter.data().getName() == sName )
2117       return mapIter.key();
2118   }
2119   return 0;
2120 }
2121 // ================================================================
2122 /*!
2123  *  SALOME_InstallWizard::abort
2124  *  Sets progress state to Aborted
2125  */
2126 // ================================================================
2127 void SALOME_InstallWizard::abort()
2128 {
2129   QString prod = progressView->findStatus( Processing );
2130   while ( !prod.isNull() ) {
2131     progressView->setStatus( prod, Aborted );
2132     prod = progressView->findStatus( Processing );
2133   }
2134   prod = progressView->findStatus( Waiting );
2135   while ( !prod.isNull() ) {
2136     progressView->setStatus( prod, Aborted );
2137     prod = progressView->findStatus( Waiting );
2138   }
2139 }
2140 // ================================================================
2141 /*!
2142  *  SALOME_InstallWizard::reject
2143  *  Reject slot, clears temporary directory and closes application
2144  */
2145 // ================================================================
2146 void SALOME_InstallWizard::reject()
2147 {
2148   ___MESSAGE___( "REJECTED" );
2149   if ( !exitConfirmed ) {
2150     if ( QMessageBox::information( this,
2151                                    tr( "Exit" ),
2152                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
2153                                    tr( "&Yes" ),
2154                                    tr( "&No" ),
2155                                    QString::null,
2156                                    0,
2157                                    1 ) == 1 ) {
2158       return;
2159     }
2160     exitConfirmed = true;
2161   }
2162   clean(true);
2163   InstallWizard::reject();
2164 }
2165 // ================================================================
2166 /*!
2167  *  SALOME_InstallWizard::accept
2168  *  Accept slot, clears temporary directory and closes application
2169  */
2170 // ================================================================
2171 void SALOME_InstallWizard::accept()
2172 {
2173   ___MESSAGE___( "ACCEPTED" );
2174   clean(true);
2175   InstallWizard::accept();
2176 }
2177 // ================================================================
2178 /*!
2179  *  SALOME_InstallWizard::clean
2180  *  Clears and (optionally) removes temporary directory
2181  */
2182 // ================================================================
2183 void SALOME_InstallWizard::clean(bool rmDir)
2184 {
2185   WarnDialog::showWarnDlg( 0, false );
2186   myThread->clearCommands();
2187   myWC.wakeAll();
2188   while ( myThread->running() );
2189   // first remove temporary files
2190   QString script = "cd ./config_files/; remove_tmp.sh '";
2191   script += tempFolder->text().stripWhiteSpace() + TEMPDIRNAME;
2192   script += "' ";
2193   script += QUOTE(DefineDependeces(productsMap));
2194   script += " > /dev/null";
2195   ___MESSAGE___( "script = " << script.latin1() );
2196   if ( system( script.latin1() ) ) {
2197   }
2198   // then try to remove created temporary directory
2199   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
2200   if ( rmDir && !tmpCreated.isNull() ) {
2201     script = "rm -rf " + tmpCreated;
2202     script += " > /dev/null";
2203     if ( system( script.latin1() ) ) {
2204     }
2205     ___MESSAGE___( "script = " << script.latin1() );
2206   }
2207 }
2208 // ================================================================
2209 /*!
2210  *  SALOME_InstallWizard::pageChanged
2211  *  Called when user moves from page to page
2212  */
2213 // ================================================================
2214 void SALOME_InstallWizard::pageChanged( const QString & mytitle)
2215 {
2216   nextButton()->setText( tr( "&Next >" ) );
2217   setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
2218   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2219   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2220   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2221   cancelButton()->disconnect();
2222   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
2223
2224   QWidget* aPage = InstallWizard::page( mytitle );
2225   if ( !aPage )
2226     return;
2227   updateCaption();
2228
2229   if ( aPage == typePage ) {
2230     // installation type page
2231     if ( buttonGrp->id( buttonGrp->selected() ) == -1 )
2232       binBtn->animateClick(); // set default installation type
2233   }
2234   if ( aPage == platformsPage ) {
2235     // installation platforms page
2236     MapXmlFiles::Iterator it;
2237     if ( previousPage == typePage ) {
2238       for ( it = platformsMap.begin(); it != platformsMap.end(); ++it ) {
2239         QString plat = it.key();
2240         QRadioButton* rb = ( (QRadioButton*) platBtnGrp->child( plat ) );
2241         if ( installType == Binaries ) {
2242           QFileInfo fib( QDir::cleanDirPath( getBinPath() + "/" + plat ) );
2243           rb->setEnabled( fib.exists() );
2244         }
2245         else {
2246           QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
2247           rb->setEnabled( fis.exists() );
2248         }
2249         rb->setChecked( rb->isChecked() && rb->isEnabled() );
2250       }
2251       setNextEnabled( platformsPage, platBtnGrp->id( platBtnGrp->selected() ) != -1 );
2252     }
2253   }
2254   else  if ( aPage == dirPage ) {
2255     // installation and temporary directories page
2256     if ( ( indexOf( platformsPage ) != -1 ? 
2257            previousPage == platformsPage : previousPage == typePage ) 
2258          && stateChanged ) {
2259       // clear global variables before reading XML file
2260       modulesView->clear();
2261       prereqsView->clear();
2262       productsMap.clear();
2263       // read XML file
2264       StructureParser* parser = new StructureParser( this );
2265       parser->setProductsLists( modulesView, prereqsView );
2266       if ( targetFolder->text().isEmpty() )
2267         parser->setTargetDir( targetFolder );
2268       if ( tempFolder->text().isEmpty() )
2269         parser->setTempDir( tempFolder );
2270       parser->readXmlFile( xmlFileName );
2271       // take into account command line parameters
2272       if ( !myTargetPath.isEmpty() )
2273         targetFolder->setText( myTargetPath );
2274       if ( !myTmpPath.isEmpty() )
2275         tempFolder->setText( myTmpPath );
2276       // set all modules to be checked and first module to be selected
2277       installGuiBtn->setState( QButton::Off );
2278       installGuiBtn->setState( QButton::On );
2279       if ( modulesView->childCount() > 0 && !modulesView->selectedItem() )
2280         modulesView->setSelected( modulesView->firstChild(), true );
2281       stateChanged = false;
2282     }
2283   }
2284   else if ( aPage == productsPage ) {
2285     // products page
2286     onSelectionChanged();
2287     checkProductPage();
2288   }
2289   else if ( aPage == prestartPage ) {
2290     // prestart page
2291     showChoiceInfo();
2292   }
2293   else if ( aPage == progressPage ) {
2294     if ( previousPage == prestartPage ) {
2295       // progress page
2296       statusLab->clear();
2297       progressView->clear();
2298       installInfo->clear();
2299       installInfo->setFinished( false );
2300       passedParams->clear();
2301       passedParams->setEnabled( false );
2302       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2303       nextButton()->setText( tr( "&Start" ) );
2304       setAboutInfo( nextButton(), tr( "Start installation process" ) );
2305       // reconnect Next button - to use it as Start button
2306       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2307       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2308       connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2309       setNextEnabled( true );
2310       // reconnect Cancel button to terminate process
2311       cancelButton()->disconnect();
2312       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
2313     }
2314   }
2315   else if ( aPage == readmePage ) {
2316     ButtonList::Iterator it;
2317     for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2318       if ( (*it).button() ) {
2319         QString script;
2320         script += "( cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
2321         script +=  + (*it).script();
2322         script += " check_enabled ";
2323         script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
2324         script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
2325         script += " > /dev/null )";
2326         ___MESSAGE___( "script: " << script.latin1() );
2327         (*it).button()->setEnabled( !(*it).script().isEmpty() && !system( script.latin1() ) );
2328       }
2329     }
2330     finishButton()->setEnabled( true );
2331   }
2332   previousPage = aPage;
2333   ___MESSAGE___( "previousPage = " << previousPage );
2334 }
2335 // ================================================================
2336 /*!
2337  *  SALOME_InstallWizard::onButtonGroup
2338  *  Called when user selected either installation type or installation platform
2339  */
2340 // ================================================================
2341 void SALOME_InstallWizard::onButtonGroup( int rbIndex )
2342 {
2343   int prevType = installType;
2344   QString prevPlat = getPlatform();
2345   QWidget* aPage = InstallWizard::currentPage();
2346   if ( aPage == typePage ) {
2347     installType = InstallationType( rbIndex );
2348     // management of the <Remove source and tmp files> check-box
2349     removeSrcBtn->setEnabled( installType == Compile );
2350   }
2351   else if ( aPage == platformsPage ) {
2352     refPlatform = platBtnGrp->find( rbIndex )->name();
2353     xmlFileName = platformsMap[ refPlatform ];
2354     cout << xmlFileName << endl;
2355     setNextEnabled( platformsPage, true );
2356   }
2357   if ( prevType != installType || 
2358        ( indexOf( platformsPage ) != -1 ? prevPlat != getPlatform() : false ) ) {
2359     stateChanged = true;
2360   }
2361 }
2362 // ================================================================
2363 /*!
2364  *  SALOME_InstallWizard::helpClicked
2365  *  Shows help window
2366  */
2367 // ================================================================
2368 void SALOME_InstallWizard::helpClicked()
2369 {
2370   if ( helpWindow == NULL ) {
2371     helpWindow = HelpWindow::openHelp( this );
2372     if ( helpWindow ) {
2373       helpWindow->show();
2374       helpWindow->installEventFilter( this );
2375     }
2376     else {
2377       QMessageBox::warning( this,
2378                             tr( "Help file not found" ),
2379                             tr( "Sorry, help is unavailable" ) );
2380     }
2381   }
2382   else {
2383     helpWindow->raise();
2384     helpWindow->setActiveWindow();
2385   }
2386 }
2387 // ================================================================
2388 /*!
2389  *  SALOME_InstallWizard::browseDirectory
2390  *  Shows directory selection dialog
2391  */
2392 // ================================================================
2393 void SALOME_InstallWizard::browseDirectory()
2394 {
2395   const QObject* theSender = sender();
2396   QLineEdit* theFolder;
2397   if ( theSender == targetBtn )
2398     theFolder = targetFolder;
2399   else if (theSender == tempBtn)
2400     theFolder = tempFolder;
2401   else
2402     return;
2403   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
2404   if ( !typedDir.isNull() ) {
2405     theFolder->setText( typedDir );
2406     theFolder->end( false );
2407   }
2408 }
2409 // ================================================================
2410 /*!
2411  *  SALOME_InstallWizard::directoryChanged
2412  *  Called when directory path (target or temp) is changed
2413  */
2414 // ================================================================
2415 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
2416 {
2417   checkProductPage();
2418 }
2419 // ================================================================
2420 /*!
2421  *  SALOME_InstallWizard::onStart
2422  *  <Start> button's slot - runs installation
2423  */
2424 // ================================================================
2425 void SALOME_InstallWizard::onStart()
2426 {
2427   cout << "" << endl;
2428   if ( nextButton()->text() == tr( "&Stop" ) ) {
2429     statusLab->setText( tr( "Aborting installation..." ) );
2430     shellProcess->kill();
2431     while( shellProcess->isRunning() );
2432     statusLab->setText( tr( "Installation has been aborted by user" ) );
2433     return;
2434   }
2435
2436   hasErrors = false;
2437   progressView->clear();
2438   installInfo->clear();
2439   installInfo->setFinished( false );
2440   passedParams->clear();
2441   passedParams->setEnabled( false );
2442   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2443
2444   // update status label
2445   statusLab->setText( tr( "Preparing for installation..." ) );
2446   // clear lists of products
2447   toInstall.clear();
2448   notInstall.clear();
2449   // ... and fill it for new process
2450   toInstall.append( "gcc" );
2451   QCheckListItem* item = (QCheckListItem*)( prereqsView->firstChild() );
2452   while( item ) {
2453     if ( productsMap.contains( item ) ) {
2454       if ( item->isOn() )
2455         toInstall.append( productsMap[item].getName() );
2456       else
2457         notInstall.append( productsMap[item].getName() );
2458     }
2459     item = (QCheckListItem*)( item->nextSibling() );
2460   }
2461   item = (QCheckListItem*)( modulesView->firstChild() );
2462   while( item ) {
2463     if ( productsMap.contains( item ) ) {
2464       if ( item->isOn() )
2465         toInstall.append( productsMap[item].getName() );
2466       else
2467         notInstall.append( productsMap[item].getName() );
2468     }
2469     item = (QCheckListItem*)( item->nextSibling() );
2470   }
2471   // if something at all is selected
2472   if ( (int)toInstall.count() > 1 ) {
2473
2474     if ( installType == Compile ) {
2475       // update status label
2476       statusLab->setText( tr( "Check Fortran compiler..." ) );
2477       // check Fortran compiler.
2478       QString script = "./config_files/checkFortran.sh find_compilers";
2479       script += " " + QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() );
2480       ___MESSAGE___( "script = " << script.latin1() );
2481       if ( system( script ) ) {
2482         QMessageBox::critical( this,
2483                                tr( "Error" ),
2484                                tr( "Fortran compiler was not found at current system!\n"
2485                                    "Installation can not be continued!"),
2486                                QMessageBox::Ok,
2487                                QMessageBox::NoButton,
2488                                QMessageBox::NoButton );
2489         // installation aborted
2490         abort();
2491         statusLab->setText( tr( "Installation has been aborted" ) );
2492         // enable <Next> button
2493         setNextEnabled( true );
2494         nextButton()->setText( tr( "&Start" ) );
2495         setAboutInfo( nextButton(), tr( "Start installation process" ) );
2496         // reconnect Next button - to use it as Start button
2497         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2498         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2499         connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2500         // enable <Back> button
2501         setBackEnabled( true );
2502         return;
2503       }
2504     }  
2505     
2506     // update status label
2507     statusLab->setText( tr( "Preparing for installation..." ) );
2508
2509     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
2510     // disable <Next> button
2511     //setNextEnabled( false );
2512     nextButton()->setText( tr( "&Stop" ) );
2513     setAboutInfo( nextButton(), tr( "Abort installation process" ) );
2514     // disable <Back> button
2515     setBackEnabled( false );
2516     // enable script parameters line edit
2517     // VSR commented: 18/09/03: passedParams->setEnabled( true );
2518     // VSR commented: 18/09/03: passedParams->setFocus();
2519     ProgressViewItem* progressItem;
2520     // set status for installed products
2521     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
2522       if ( toInstall[i] != "gcc" ) {
2523         item = findItem( toInstall[i] );
2524         progressView->addProduct( item->text(0), item->text(2) );
2525         continue;
2526       }
2527       progressItem = progressView->addProduct( "gcc", "gcc-common.sh" );
2528       progressItem->setVisible( false );
2529     }
2530     // set status for not installed products
2531     for ( int i = 0; i < (int)notInstall.count(); i++ ) {
2532       item = findItem( notInstall[i] );
2533       progressItem = progressView->addProduct( item->text(0), item->text(2) );
2534       progressItem->setVisible( false );
2535     }
2536     // get specified list of products being installed
2537     prodSequence.clear();
2538     for (int i = 0; i<(int)toInstall.count(); i++ ) {
2539       if ( toInstall[i] == "gcc" ) {
2540         prodSequence.append( toInstall[i] );
2541         continue;
2542       }
2543       if ( installType == Binaries ) {
2544         prodSequence.append( toInstall[i] );
2545         QString prodType;
2546         MapProducts::Iterator mapIter;
2547         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2548           if ( mapIter.data().getName() == toInstall[i] && mapIter.data().getType() == "component" ) {
2549             prodSequence.append( toInstall[i] + "_src" );
2550             break;
2551           }
2552         }
2553       }
2554       else if ( installType == Sources )
2555         prodSequence.append( toInstall[i] + "_src" );
2556       else {
2557         prodSequence.append( toInstall[i] );
2558         prodSequence.append( toInstall[i] + "_src" );
2559       }
2560     }
2561
2562     // create a backup of 'env_build.csh', 'env_build.sh', 'env_products.csh', 'env_products.sh'
2563     // ( backup of 'salome.csh' and 'salome.sh' is made if pick-up environment is called )
2564     QString script = "./config_files/backupEnv.sh ";
2565     script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2566     ___MESSAGE___( "script = " << script.latin1() );
2567     if ( system( script ) ) {
2568       if ( QMessageBox::warning( this,
2569                                  tr( "Warning" ),
2570                                  tr( "Backup environment files have not been created.\n"
2571                                      "Do you want to continue an installation process?" ),
2572                                  tr( "&Yes" ),
2573                                  tr( "&No" ), 
2574                                  QString::null, 0, 1 ) == 1 ) {
2575         // installation aborted
2576         abort();
2577         statusLab->setText( tr( "Installation has been aborted by user" ) );
2578         // enable <Next> button
2579         setNextEnabled( true );
2580         nextButton()->setText( tr( "&Start" ) );
2581         setAboutInfo( nextButton(), tr( "Start installation process" ) );
2582         // reconnect Next button - to use it as Start button
2583         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2584         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2585         connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2586         // enable <Back> button
2587         setBackEnabled( true );
2588         return;
2589       }
2590     }
2591
2592     // launch install script
2593     launchScript();
2594   }
2595 }
2596 // ================================================================
2597 /*!
2598  *  SALOME_InstallWizard::onReturnPressed
2599  *  Called when users tries to pass parameters for the script
2600  */
2601 // ================================================================
2602 void SALOME_InstallWizard::onReturnPressed()
2603 {
2604   QString txt = passedParams->text();
2605   installInfo->append( txt );
2606   txt += "\n";
2607   shellProcess->writeToStdin( txt );
2608   passedParams->clear();
2609   progressView->setFocus();
2610   passedParams->setEnabled( false );
2611   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2612 }
2613 /*!
2614   Callback function - as response for the script finishing
2615 */
2616 void SALOME_InstallWizard::productInstalled()
2617 {
2618   ___MESSAGE___( "process exited" );
2619   if ( shellProcess->normalExit() ) {
2620     ___MESSAGE___( "...normal exit" );
2621     // normal exit - try to proceed installation further
2622     launchScript();
2623   }
2624   else {
2625     ___MESSAGE___( "...abnormal exit" );
2626     statusLab->setText( tr( "Installation has been aborted" ) );
2627     // installation aborted
2628     abort();
2629     // clear script passed parameters lineedit
2630     passedParams->clear();
2631     passedParams->setEnabled( false );
2632     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2633     installInfo->setFinished( true );
2634     // enable <Next> button
2635     setNextEnabled( true );
2636     nextButton()->setText( tr( "&Start" ) );
2637     setAboutInfo( nextButton(), tr( "Start installation process" ) );
2638     // reconnect Next button - to use it as Start button
2639     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2640     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2641     connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2642     //nextButton()->setText( tr( "&Next >" ) );
2643     //setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
2644     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2645     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2646     //connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2647     // enable <Back> button
2648     setBackEnabled( true );
2649   }
2650 }
2651 // ================================================================
2652 /*!
2653  *  SALOME_InstallWizard::tryTerminate
2654  *  Slot, called when <Cancel> button is clicked during installation script running
2655  */
2656 // ================================================================
2657 void SALOME_InstallWizard::tryTerminate()
2658 {
2659   if ( shellProcess->isRunning() ) {
2660     if ( QMessageBox::information( this,
2661                                    tr( "Exit" ),
2662                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
2663                                    tr( "&Yes" ),
2664                                    tr( "&No" ),
2665                                    QString::null,
2666                                    0,
2667                                    1 ) == 1 ) {
2668       return;
2669     }
2670     exitConfirmed = true;
2671     // if process still running try to terminate it first
2672     shellProcess->tryTerminate();
2673     abort();
2674     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
2675     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
2676   }
2677   else {
2678     // else just quit install wizard
2679     reject();
2680   }
2681 }
2682 // ================================================================
2683 /*!
2684  *  SALOME_InstallWizard::onCancel
2685  *  Kills installation process and quits application
2686  */
2687 // ================================================================
2688 void SALOME_InstallWizard::onCancel()
2689 {
2690   shellProcess->kill();
2691   reject();
2692 }
2693 // ================================================================
2694 /*!
2695  *  SALOME_InstallWizard::onSelectionChanged
2696  *  Called when selection is changed in the products list view
2697  */
2698 // ================================================================
2699 void SALOME_InstallWizard::onSelectionChanged()
2700 {
2701   const QObject* snd = sender();
2702   QListViewItem* item = modulesView->selectedItem();
2703   if ( snd == prereqsView )
2704     item = prereqsView->selectedItem();
2705   else if ( snd != modulesView )
2706     return;
2707   productInfo->clear();
2708   if ( !item )
2709     return;
2710   QCheckListItem* anItem = (QCheckListItem*)item;
2711   if ( !productsMap.contains( anItem ) )
2712     return;
2713   Dependancies dep = productsMap[ anItem ];
2714   QString text = "<b>" + anItem->text(0) + "</b>" + "<br>";
2715   if ( !dep.getVersion().isEmpty() )
2716     text += tr( "Version" ) + ": " + dep.getVersion() + "<br>";
2717   text += "<br>";
2718   if ( !dep.getDescription().isEmpty() ) {
2719     text += "<i>" + dep.getDescription() + "</i><br><br>";
2720   }
2721   long totSize = 0, tempSize = 0;
2722   if ( installType == Compile && removeSrcBtn->state() == QButton::On )
2723     totSize = dep.getSize( Binaries );
2724   else
2725     totSize = dep.getSize( installType );
2726   tempSize = dep.getTempSize( installType );
2727   text += tr( "Disk space required" ) + ": " + QString::number( totSize ) + " KB<br>";
2728   text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " KB<br>";
2729   text += "<br>";
2730   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
2731   text +=  tr( "Prerequisites" ) + ": " + req;
2732   productInfo->setText( text );
2733 }
2734 // ================================================================
2735 /*!
2736  *  SALOME_InstallWizard::onItemToggled
2737  *  Called when user checks/unchecks any product item
2738  *  Recursively sets all prerequisites and updates "Next" button state
2739  */
2740 // ================================================================
2741 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
2742 {
2743   if ( productsMap.contains( item ) ) {
2744     if ( item->isOn() )
2745       setPrerequisites( item );
2746     else 
2747       unsetPrerequisites( item );
2748   }
2749   onSelectionChanged();
2750   checkProductPage();
2751 }
2752 // ================================================================
2753 /*!
2754  *  SALOME_InstallWizard::wroteToStdin
2755  *  QProcess slot: -->something was written to stdin
2756  */
2757 // ================================================================
2758 void SALOME_InstallWizard::wroteToStdin( )
2759 {
2760   ___MESSAGE___( "Something was sent to stdin" );
2761 }
2762 // ================================================================
2763 /*!
2764  *  SALOME_InstallWizard::readFromStdout
2765  *  QProcess slot: -->something was written to stdout
2766  */
2767 // ================================================================
2768 void SALOME_InstallWizard::readFromStdout( )
2769 {
2770   ___MESSAGE___( "Something was sent to stdout" );
2771   while ( shellProcess->canReadLineStdout() ) {
2772     installInfo->append( QString( shellProcess->readLineStdout() ) );
2773     installInfo->scrollToBottom();
2774   }
2775   QString str( shellProcess->readStdout() );
2776   if ( !str.isEmpty() ) {
2777     installInfo->append( str );
2778     installInfo->scrollToBottom();
2779   }
2780 }
2781
2782 #define OUTLINE_TEXT(x) QString( "<font color=#FF0000><b>" ) + QString( x ) + QString( "</b></font>" )
2783
2784 // ================================================================
2785 /*!
2786  *  SALOME_InstallWizard::readFromStderr
2787  *  QProcess slot: -->something was written to stderr
2788  */
2789 // ================================================================
2790 void SALOME_InstallWizard::readFromStderr( )
2791 {
2792   ___MESSAGE___( "Something was sent to stderr" );
2793   while ( shellProcess->canReadLineStderr() ) {
2794     installInfo->append( OUTLINE_TEXT( QString( shellProcess->readLineStderr() ) ) );
2795     installInfo->scrollToBottom();
2796     hasErrors = true;
2797   }
2798   QString str( shellProcess->readStderr() );
2799   if ( !str.isEmpty() ) {
2800     installInfo->append( OUTLINE_TEXT( str ) );
2801     installInfo->scrollToBottom();
2802     hasErrors = true;
2803   }
2804   // VSR: 10/11/05 - disable answer mode ==>
2805   // passedParams->setEnabled( true );
2806   // passedParams->setFocus();
2807   // QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
2808   // VSR: 10/11/05 - disable answer mode <==
2809 }
2810 // ================================================================
2811 /*!
2812  *  SALOME_InstallWizard::setDependancies
2813  *  Sets dependancies for the product item
2814  */
2815 // ================================================================
2816 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
2817 {
2818   productsMap[item] = dep;
2819 }
2820 // ================================================================
2821 /*!
2822  *  SALOME_InstallWizard::addFinishButton
2823  *  Add button for the <Finish> page.
2824  *  Clear list of buttons if <toClear> flag is true.
2825  */
2826 // ================================================================
2827 void SALOME_InstallWizard::addFinishButton( const QString& label,
2828                                             const QString& tooltip,
2829                                             const QString& script,
2830                                             bool toClear )
2831 {
2832   ButtonList btns;
2833   if ( toClear ) {
2834     btns = buttons;
2835     buttons.clear();
2836   }
2837   buttons.append( Button( label, tooltip, script ) );
2838   // create finish buttons
2839   QButton* b = new QPushButton( tr( buttons.last().label() ), readmePage );
2840   if ( !buttons.last().tootip().isEmpty() )
2841     setAboutInfo( b, tr( buttons.last().tootip() ) );
2842   QHBoxLayout* hLayout = (QHBoxLayout*)readmePage->layout()->child("finishButtons");
2843   if ( toClear ) {
2844     // remove previous buttons
2845     ButtonList::Iterator it;
2846     for ( it = btns.begin(); it != btns.end(); ++it ) {
2847       hLayout->removeChild( (*it).button() );
2848       delete (*it).button();
2849     }
2850   }
2851   // add buttons to finish page
2852   hLayout->insertWidget( buttons.count()-1, b );
2853   buttons.last().setButton( b );
2854   connect( b, SIGNAL( clicked() ), this, SLOT( onFinishButton() ) );
2855 }
2856 // ================================================================
2857 /*!
2858  *  SALOME_InstallWizard::polish
2859  *  Polishing of the widget - to set right initial size
2860  */
2861 // ================================================================
2862 void SALOME_InstallWizard::polish()
2863 {
2864   resize( 0, 0 );
2865   InstallWizard::polish();
2866 }
2867 // ================================================================
2868 /*!
2869  *  SALOME_InstallWizard::saveLog
2870  *  Save installation log to file
2871  */
2872 // ================================================================
2873 void SALOME_InstallWizard::saveLog()
2874 {
2875   QString txt = installInfo->text();
2876   if ( txt.length() <= 0 )
2877     return;
2878   QDateTime dt = QDateTime::currentDateTime();
2879   QString fileName = dt.toString("ddMMyy-hhmm");
2880   fileName.prepend("install-"); fileName.append(".html");
2881   fileName = QFileDialog::getSaveFileName( fileName,
2882                                            QString( "HTML files (*.htm *.html)" ),
2883                                            this, 0,
2884                                            tr( "Save Log file" ) );
2885   if ( !fileName.isEmpty() ) {
2886     QFile f( fileName );
2887     if ( f.open( IO_WriteOnly ) ) {
2888       QTextStream stream( &f );
2889       stream << txt;
2890       f.close();
2891     }
2892     else {
2893       QMessageBox::critical( this,
2894                              tr( "Error" ),
2895                              tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ),
2896                              QMessageBox::Ok,
2897                              QMessageBox::NoButton,
2898                              QMessageBox::NoButton );
2899     }
2900   }
2901 }
2902 // ================================================================
2903 /*!
2904  *  SALOME_InstallWizard::updateCaption
2905  *  Updates caption according to the current page number
2906  */
2907 // ================================================================
2908 void SALOME_InstallWizard::updateCaption()
2909 {
2910   QWidget* aPage = InstallWizard::currentPage();
2911   if ( !aPage )
2912     return;
2913   InstallWizard::setCaption( tr( myCaption ) + " " +
2914                              tr( getIWName() ) + " - " +
2915                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
2916 }
2917
2918 // ================================================================
2919 /*!
2920  *  SALOME_InstallWizard::processValidateEvent
2921  *  Processes validation event (<val> is validation code)
2922  */
2923 // ================================================================
2924 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
2925 {
2926   QWidget* aPage = InstallWizard::currentPage();
2927   if ( aPage != productsPage ) {
2928     InstallWizard::processValidateEvent( val, data );
2929     return;
2930   }
2931   myMutex.lock();
2932   myMutex.unlock();
2933   if ( val > 0 ) {
2934   }
2935   if ( myThread->hasCommands() )
2936     myWC.wakeAll();
2937   else {
2938     WarnDialog::showWarnDlg( 0, false );
2939     InstallWizard::processValidateEvent( val, data );
2940   }
2941 }