Salome HOME
Modifications in according to improvement 15165.
[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 introduction page
537   setupIntroPage();
538   // create page to select installation type
539   setupTypePage();
540   // create page to select the reference installation platform (if necessary)
541   setupPlatformPage();
542   // create directories page
543   setupDirPage();
544   // create products page
545   setupProductsPage();
546   // create prestart page
547   setupCheckPage();
548   // create progress page
549   setupProgressPage();
550   // create readme page
551   setupReadmePage();
552
553   // common buttons
554   setAboutInfo( backButton(),   tr( "Return to the previous step\nof the installation procedure" ) );
555   setAboutInfo( nextButton(),   tr( "Move to the next step\nof the installation procedure" ) );
556   setAboutInfo( finishButton(), tr( "Finish the installation and quit the program" ) );
557   setAboutInfo( cancelButton(), tr( "Cancel the installation and quit the program" ) );
558   setAboutInfo( helpButton(),   tr( "Show the help information" ) );
559
560   // common signals connections
561   connect( this, SIGNAL( selected( const QString& ) ),
562                                            this, SLOT( pageChanged( const QString& ) ) );
563   connect( this, SIGNAL( helpClicked() ),  this, SLOT( helpClicked() ) );
564   connect( this, SIGNAL( aboutClicked() ), this, SLOT( onAbout() ) );
565
566   // catch signals from launched script
567   connect(shellProcess, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout() ) );
568   connect(shellProcess, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr() ) );
569   connect(shellProcess, SIGNAL( processExited() ),   this, SLOT( productInstalled() ) );
570   connect(shellProcess, SIGNAL( wroteToStdin() ),    this, SLOT( wroteToStdin() ) );
571
572   // create validation thread
573   myThread = new ProcessThread( this );
574
575   // show about button
576   setAboutIcon( pixmap( pxAbout ) );
577   showAboutBtn( true );
578 }
579 // ================================================================
580 /*!
581  *  SALOME_InstallWizard::~SALOME_InstallWizard
582  *  Destructor
583  */
584 // ================================================================
585 SALOME_InstallWizard::~SALOME_InstallWizard()
586 {
587   shellProcess->kill(); // kill it for sure
588   QString script = "kill -9 ";
589   int PID = (int)shellProcess->processIdentifier();
590   if ( PID > 0 ) {
591     script += QString::number( PID );
592     script += " > /dev/null";
593     ___MESSAGE___( "script: " << script.latin1() );
594     if ( system( script.latin1() ) ) {
595     }
596   }
597   delete myThread;
598 }
599 // ================================================================
600 /*!
601  *  SALOME_InstallWizard::currentPlatform
602  *  Tries to determine the current user's operating system
603  */
604 // ================================================================
605 QString SALOME_InstallWizard::currentPlatform()
606 {
607   // file parsing
608   QString curOS = "";
609   QString osFileName = "/etc/issue";
610   if ( QFile::exists( osFileName ) ) {
611     QFile file( osFileName );
612     if ( file.open( IO_ReadOnly ) ) {
613       QTextStream stream( &file );
614       QString str = stream.readLine();
615       file.close();
616       // line parsing
617       QString pltName = "", platVersion = "", platBit = "";
618       QRegExp rx( "(.*)[L|l]inux.*release\\s+([\\d.]*)" );
619 //       str = "Debian GNU/Linux 3.1 \n \l";
620 //       str = "Red Hat Enterprise Linux WS release 4 (Nahant)";
621 //       str = "Mandriva Linux release 2006.0 (Official) for x86_64";
622       int pos = rx.search( str );
623       if ( pos == -1 ) {// Debian case
624         rx = QRegExp( "(.*)GNU/Linux\\s+([\\d.]*)" );
625         pos = rx.search( str );
626       }
627       if ( pos > -1 ) {
628         pltName = rx.cap( 1 );
629         platVersion = rx.cap( 2 );
630         rx = QRegExp( "x86_64" );
631         pos = rx.search( str );
632         if ( pos > -1 )
633           platBit = "_64";
634         curOS = pltName + platVersion + platBit;
635       }
636     }
637   }
638   //   return curOS.remove( " " );
639   QString str( " " );
640   int index = 0;
641   while ( (index = curOS.find( str, index, true)) != -1 )
642     curOS.remove( index, str.length() );
643   return curOS;
644 }
645 // ================================================================
646 /*!
647  *  SALOME_InstallWizard::getXmlMap
648  *  Creates a map of the supported operating systems and 
649  *  corresponding XML files.
650  */
651 // ================================================================
652 MapXmlFiles SALOME_InstallWizard::getXmlMap( const QString& xmlFileName )
653 {
654   MapXmlFiles xmlMap;
655   QStringList xmlList;
656   if ( xmlFileName )
657     xmlList.append( xmlFileName );
658   else {
659     QDir dir( QDir::currentDirPath() );
660     xmlList = dir.entryList( "*.xml", QDir::Files | QDir::Readable );
661   }
662 //   cout << xmlList.join(",") << endl;
663   // XML files parsing
664   QFile file;
665   QDomDocument doc( "xml_doc" );
666   QDomElement docElem;
667   QDomNodeList nodeList;
668   QDomNode node;
669   QDomElement elem;
670   QString platforms = "";
671   QStringList platList;
672   for ( uint i = 0; i < xmlList.count(); i++ ) {
673     file.setName( xmlList[i] );
674     if ( !doc.setContent( &file ) ) {
675       file.close();
676       continue;
677     }
678     file.close();
679     
680     docElem = doc.documentElement();
681     nodeList = docElem.elementsByTagName( "config" );
682     if ( nodeList.count() == 0 )
683       continue;      
684     node = nodeList.item( 0 );
685     if ( node.isElement() ) {
686       elem = node.toElement();
687       if ( elem.attribute( "platforms" ) ) {
688         platforms = elem.attribute( "platforms" ).stripWhiteSpace();
689         QStringList platList = QStringList::split( ",", platforms );
690         for ( uint j = 0; j < platList.count(); j++ ) {
691           if ( !platList[j].isEmpty() && xmlMap.find( platList[j] ) == xmlMap.end() )
692             xmlMap[ platList[j] ] = xmlList[i];
693         }
694 //      if ( !curPlatform.isEmpty() && xmlMap.find( curPlatform ) != xmlMap.end() )
695 //        return xmlMap;
696       }
697     }
698   }
699   return xmlMap;
700 }
701 // ================================================================
702 /*!
703  *  SALOME_InstallWizard::checkXmlAndPlatform
704  *  Check XML file and current platform definition
705  */
706 // ================================================================
707 void SALOME_InstallWizard::getXmlAndPlatform()
708 {
709   MapXmlFiles xmlMap;
710   if ( xmlFileName.isNull() ) {
711     xmlMap = getXmlMap();
712     if ( !curPlatform.isEmpty() ) {
713       // try to get XML file for current platform
714       if ( xmlMap.find( curPlatform ) != xmlMap.end() )
715         xmlFileName = xmlMap[ curPlatform ];
716       else {
717         platformsMap = xmlMap;
718         warnMsg = tr( "Your Linux platform is not supported by this SALOME package" );
719       }
720     }
721     else {
722       // get all supported platforms
723       platformsMap = xmlMap;
724       warnMsg = tr( "Install Wizard can't define your Linux platform" );
725     }
726   }
727   else {
728     xmlMap = getXmlMap( xmlFileName );
729     if ( !curPlatform.isEmpty() ) {
730       // check that the user's XML file supports current platform
731       if ( xmlMap.find( curPlatform ) == xmlMap.end() ) {
732         platformsMap = getXmlMap();
733         MapXmlFiles::Iterator it;
734         for ( it = xmlMap.begin(); it != xmlMap.end(); ++it )
735           platformsMap.insert( it.key(), it.data(), true );
736         warnMsg = tr( "The given configuration file doesn't support your Linux platform" );
737       }
738     }
739     else {
740       // get all supported platforms
741       platformsMap = getXmlMap();
742       MapXmlFiles::Iterator it;
743       for ( it = xmlMap.begin(); it != xmlMap.end(); ++it )
744         platformsMap.insert( it.key(), it.data(), true );
745       warnMsg = tr( "Install Wizard can't define your Linux platform" );
746     }
747   }
748 }
749 // ================================================================
750 /*!
751  *  SALOME_InstallWizard::eventFilter
752  *  Event filter, spies for Help window closing
753  */
754 // ================================================================
755 bool SALOME_InstallWizard::eventFilter( QObject* object, QEvent* event )
756 {
757   if ( object && object == helpWindow && event->type() == QEvent::Close )
758     helpWindow = NULL;
759   return InstallWizard::eventFilter( object, event );
760 }
761 // ================================================================
762 /*!
763  *  SALOME_InstallWizard::closeEvent
764  *  Close event handler
765  */
766 // ================================================================
767 void SALOME_InstallWizard::closeEvent( QCloseEvent* ce )
768 {
769   if ( WarnDialog::isWarnDlgShown() ) {
770     ce->ignore();
771     return;
772   }
773   if ( !exitConfirmed ) {
774     if ( QMessageBox::information( this,
775                                    tr( "Exit" ),
776                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
777                                    tr( "&Yes" ),
778                                    tr( "&No" ),
779                                    QString::null,
780                                    0,
781                                    1 ) == 1 ) {
782       ce->ignore();
783     }
784     else {
785       ce->accept();
786       exitConfirmed = true;
787       reject();
788     }
789   }
790 }
791 // ================================================================
792 /*!
793  *  SALOME_InstallWizard::setupIntroPage
794  *  Creates introduction page
795  */
796 // ================================================================
797 void SALOME_InstallWizard::setupIntroPage()
798 {
799   // create page
800   introPage = new QWidget( this, "IntroPage" );
801   QGridLayout* pageLayout = new QGridLayout( introPage );
802   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
803   // create logo picture
804   logoLab = new QLabel( introPage );
805   logoLab->setPixmap( pixmap( pxBigLogo ) );
806   logoLab->setScaledContents( false );
807   logoLab->setFrameStyle( QLabel::Plain | QLabel::NoFrame );
808   logoLab->setAlignment( AlignCenter );
809   // create version box
810   QVBox* versionBox = new QVBox( introPage ); versionBox->setSpacing( 6 );
811   versionBox->setFrameStyle( QVBox::Panel | QVBox::Sunken );
812   QWidget* stretch1 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch1, 5 );
813   versionLab = new QLabel( QString("%1 %2").arg( tr( "Version" ) ).arg(myVersion), versionBox );
814   versionLab->setAlignment( AlignCenter );
815   copyrightLab = new QLabel( myCopyright, versionBox );
816   copyrightLab->setAlignment( AlignCenter );
817   licenseLab = new QLabel( myLicense, versionBox );
818   licenseLab->setAlignment( AlignCenter );
819   QWidget* stretch2 = new QWidget( versionBox ); versionBox->setStretchFactor( stretch2, 5 );
820   // create info box
821   info = new QLabel( introPage );
822   info->setText( tr( "This program will install <b>%1</b>."
823                      "<br><br>The wizard will also help you to install all products "
824                      "which are necessary for <b>%2</b> and setup "
825                      "your environment.<br><br>Click <code>Cancel</code> button to abort "
826                      "installation and quit. Click <code>Next</code> button to continue with the "
827                      "installation program." ).arg( myCaption ).arg( myCaption ) );
828   info->setFrameStyle( QLabel::WinPanel | QLabel::Sunken );
829   info->setMargin( 6 );
830   info->setAlignment( WordBreak );
831   info->setMinimumWidth( 250 );
832   QPalette pal = info->palette();
833   pal.setColor( QColorGroup::Background, QApplication::palette().active().base() );
834   info->setPalette( pal );
835   info->setLineWidth( 2 );
836   // layouting
837   pageLayout->addWidget( logoLab, 0, 0 );
838   pageLayout->addWidget( versionBox, 1, 0 );
839   pageLayout->addMultiCellWidget( info, 0, 1, 1, 1 );
840   pageLayout->setColStretch( 1, 5 );
841   pageLayout->setRowStretch( 1, 5 );
842   // adding page
843   addPage( introPage, tr( "Introduction" ) );
844 }
845 // ================================================================
846 /*!
847  *  SALOME_InstallWizard::setupTypePage
848  *  Creates installation types page
849  */
850 // ================================================================
851 void SALOME_InstallWizard::setupTypePage()
852 {
853   // create page
854   typePage = new QWidget( this, "TypePage" );
855   QGridLayout* pageLayout = new QGridLayout( typePage );
856   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
857   // create installation type button group
858   buttonGrp = new QButtonGroup( typePage );
859   buttonGrp->setFrameShape(QButtonGroup::NoFrame);
860   QGridLayout* buttonGrpLayout = new QGridLayout( buttonGrp );
861   buttonGrpLayout->setMargin( 0 ); buttonGrpLayout->setSpacing( 6 );
862   QSpacerItem* spacer1 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
863   QSpacerItem* spacer2 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
864   QLabel* selectLab = new QLabel( tr( "Select a type of the installation:" ), buttonGrp );
865   QSpacerItem* spacer3 = new QSpacerItem( 20, 20, QSizePolicy::Fixed, QSizePolicy::Minimum );
866   // ... 'install binaries' layout
867   QGridLayout* binLayout = new QGridLayout( 2, 2, 0 );
868   binBtn = new QRadioButton( tr( "Install binaries" ), buttonGrp );
869   QFont rbFont = binBtn->font();
870   rbFont.setBold( true );
871   binBtn->setFont( rbFont );
872   QSpacerItem* spacer4 = new QSpacerItem( 16, 16, QSizePolicy::Fixed, QSizePolicy::Minimum );
873   QLabel* binLab = new QLabel( tr( "- all the binaries and sources of the chosen SALOME modules will be installed.\n"
874                                    "- all the binaries of the chosen prerequisites will be installed." ), 
875                                buttonGrp );
876   binLayout->addMultiCellWidget( binBtn,  0, 0, 0, 1 );
877   binLayout->addItem           ( spacer4, 1,    0    );
878   binLayout->addWidget         ( binLab,  1,    1    );
879   // ... 'install sources' layout
880   QGridLayout* srcLayout = new QGridLayout( 2, 2, 0 );
881   srcBtn = new QRadioButton( tr( "Install sources" ), buttonGrp );
882   srcBtn->setFont( rbFont );
883   QSpacerItem* spacer5 = new QSpacerItem( 16, 16, QSizePolicy::Fixed, QSizePolicy::Minimum );
884   QLabel* srcLab = new QLabel( tr( "- all the sources of the chosen modules and prerequisites will be installed without\ncompilation." ), 
885                                buttonGrp );
886   srcLayout->addMultiCellWidget( srcBtn,  0, 0, 0, 1 );
887   srcLayout->addItem           ( spacer5, 1,    0    );
888   srcLayout->addWidget         ( srcLab,  1,    1    );
889   // ... 'install sources and make compilation' layout
890   QGridLayout* srcCompileLayout = new QGridLayout( 3, 3, 0 );
891   srcCompileBtn = new QRadioButton( tr( "Install sources and make a compilation" ), buttonGrp );
892   srcCompileBtn->setFont( rbFont );
893   QSpacerItem* spacer6 = new QSpacerItem( 16, 16, QSizePolicy::Fixed, QSizePolicy::Minimum );
894   QLabel* srcCompileLab1 = new QLabel( tr( "- all the sources of the chosen modules and prerequisites will be installed and\ncompiled." ), 
895                                        buttonGrp );
896   QLabel* srcCompileLab2 = new QLabel( tr( "Note:" ), 
897                                        buttonGrp );
898   QFont noteFont = srcCompileLab2->font();
899   noteFont.setUnderline( true );
900   srcCompileLab2->setFont( noteFont );
901   srcCompileLab2->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) );
902   srcCompileLab2->setAlignment( Qt::AlignHCenter | Qt::AlignTop );
903   QLabel* srcCompileLab3 = new QLabel( " " + 
904                                        tr( "it is a long time operation and it can take more than 24 hours depending\n on the computer." ), 
905                                        buttonGrp );
906   removeSrcBtn = new QMyCheckBox( tr( "Remove sources and temporary files after compilation" ), typePage );
907   setAboutInfo( removeSrcBtn, tr( "Check this option if you want to remove sources of the products\nwith all the temporary files after build finishing" ) );
908   removeSrcBtn->setState( QButton::Off );
909   removeSrcBtn->setEnabled( false );
910
911   srcCompileLayout->addMultiCellWidget( srcCompileBtn,  0, 0, 0, 2 );
912   srcCompileLayout->addMultiCell      ( spacer6,        1, 2, 0, 0 );
913   srcCompileLayout->addMultiCellWidget( srcCompileLab1, 1, 1, 1, 2 );
914   srcCompileLayout->addWidget         ( srcCompileLab2, 2,    1    );
915   srcCompileLayout->addWidget         ( srcCompileLab3, 2,    2    );
916   srcCompileLayout->addMultiCellWidget( removeSrcBtn,   3, 3, 1, 2 );
917   // layout widgets in the button group
918   buttonGrpLayout->addItem           ( spacer1,          0,    1    );
919   buttonGrpLayout->addMultiCellWidget( selectLab,        1, 1, 0, 1 );
920   buttonGrpLayout->addMultiCell      ( spacer3,          2, 4, 0, 0 );
921   buttonGrpLayout->addLayout         ( binLayout,        2,    1    );
922   buttonGrpLayout->addLayout         ( srcLayout,        3,    1    );
923   buttonGrpLayout->addLayout         ( srcCompileLayout, 4,    1    );
924   buttonGrpLayout->addItem           ( spacer2,          5,    1    );
925   // layout button group at the page
926   pageLayout->addWidget( buttonGrp, 0, 0 );
927   // connecting signals
928   connect( buttonGrp, SIGNAL( clicked(int) ), this, SLOT ( onButtonGroup(int) ) );
929   connect( removeSrcBtn,  SIGNAL( toggled( bool ) ), this, SLOT( onRemoveSrcBtn() ) );
930   // adding page
931   addPage( typePage, tr( "Installation type" ) );
932 }
933 // ================================================================
934 /*!
935  *  SALOME_InstallWizard::setupPlatformPage
936  *  Creates platforms page, if necessary
937  */
938 // ================================================================
939 void SALOME_InstallWizard::setupPlatformPage()
940 {
941   // create page or not?
942   if ( platformsMap.isEmpty() )
943     return;
944
945   // create page
946   platformsPage = new QWidget( this, "PlatformsPage" );
947   QGridLayout* pageLayout = new QGridLayout( platformsPage );
948   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
949   // create warning labels
950   QLabel* warnLab2 = new QLabel( tr( "WARNING!" ), platformsPage );
951   warnLab2->setAlignment( Qt::AlignHCenter );
952   QFont fnt = warnLab2->font();
953   fnt.setBold( true );
954   warnLab2->setFont( fnt );
955   if ( installType == Compile && platformsMap.find( curPlatform ) == platformsMap.end() )
956     warnMsg += tr( " and compilation is not tested on this one." );
957   else
958     warnMsg += ".";
959   warnLab = new QLabel( warnMsg, platformsPage );
960   warnLab->setAlignment( Qt::AlignHCenter | Qt::WordBreak );
961   QLabel* warnLab3 = new QLabel( tr( "If you want to proceed anyway, please select platform from the following list:" ), 
962                                  platformsPage );
963   warnLab3->setAlignment( Qt::AlignHCenter | Qt::WordBreak );
964   // create button group
965   platBtnGrp = new QButtonGroup( platformsPage );
966   platBtnGrp->setFrameShape(QButtonGroup::LineEditPanel);
967   platBtnGrp->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) );
968   QVBoxLayout* platBtnGrpLayout = new QVBoxLayout( platBtnGrp );
969   platBtnGrpLayout->setMargin( 11 ); platBtnGrpLayout->setSpacing( 6 );
970   // create platforms radio-buttons
971   QString plat;
972   MapXmlFiles::Iterator it;
973   for ( it = platformsMap.begin(); it != platformsMap.end(); ++it ) {
974     plat = it.key();
975     QRadioButton* rb = new QRadioButton( plat, platBtnGrp, plat );
976     platBtnGrpLayout->addWidget( rb );
977   }
978   // create spacers
979   QSpacerItem* spacer1 = new QSpacerItem( 16, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
980   QSpacerItem* spacer2 = new QSpacerItem( 16, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
981
982   // layout widgets on page
983   pageLayout->addItem           ( spacer1,    0,    0    );
984   pageLayout->addWidget         ( warnLab2,   1,    0    );
985   pageLayout->addWidget         ( warnLab,    2,    0    );
986   pageLayout->addWidget         ( warnLab3,   3,    0    );
987   pageLayout->addItem           ( spacer2,    4,    0    );
988   pageLayout->addMultiCellWidget( platBtnGrp, 0, 4, 1, 1 );
989
990   // connecting signals
991   connect( platBtnGrp, SIGNAL( clicked(int) ), this, SLOT ( onButtonGroup(int) ) );
992
993   // adding page
994   addPage( platformsPage, tr( "Installation platform" ) );
995 }
996 // ================================================================
997 /*!
998  *  SALOME_InstallWizard::setupDirPage
999  *  Creates directories page
1000  */
1001 // ================================================================
1002 void SALOME_InstallWizard::setupDirPage()
1003 {
1004   // create page
1005   dirPage = new QWidget( this, "DirPage" );
1006   QGridLayout* pageLayout = new QGridLayout( dirPage );
1007   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1008   QSpacerItem* spacer1 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
1009   QSpacerItem* spacer2 = new QSpacerItem( 16, 50, QSizePolicy::Minimum, QSizePolicy::Expanding );
1010   // target directory
1011   QGridLayout* targetLayout = new QGridLayout( 2, 2, 0 );
1012   QLabel* targetLab = new QLabel( tr( "Set a target directory to install SALOME platform:" ), dirPage );
1013   targetFolder = new QLineEdit( dirPage );
1014   targetBtn = new QPushButton( tr( "Browse..." ), dirPage );
1015   setAboutInfo( targetBtn, tr( "Click this button to browse\nthe installation directory" ) );
1016   targetLayout->addMultiCellWidget( targetLab,    0, 0, 0, 1 );
1017   targetLayout->addWidget         ( targetFolder, 1,    0    );
1018   targetLayout->addWidget         ( targetBtn,    1,    1    );
1019   // temporary directory
1020   QGridLayout* tempLayout = new QGridLayout( 2, 2, 0 );
1021   QLabel* tempLab = new QLabel( tr( "Set a directory that should be used for temporary SALOME files:" ), dirPage );
1022   tempFolder = new QLineEdit( dirPage );
1023   tempBtn = new QPushButton( tr( "Browse..." ), dirPage );
1024   setAboutInfo( tempBtn, tr( "Click this button to browse\nthe temporary directory" ) );
1025   tempLayout->addMultiCellWidget( tempLab,    0, 0, 0, 1 );
1026   tempLayout->addWidget         ( tempFolder, 1,    0    );
1027   tempLayout->addWidget         ( tempBtn,    1,    1    );
1028   // layout widgets
1029   pageLayout->addItem  ( spacer1,      0, 0 );
1030   pageLayout->addLayout( targetLayout, 1, 0 );
1031   pageLayout->addLayout( tempLayout,   2, 0 );
1032   pageLayout->addItem  ( spacer2,      3, 0 );
1033   // connecting signals
1034   connect( targetFolder,  SIGNAL( textChanged( const QString& ) ),
1035            this,          SLOT( directoryChanged( const QString& ) ) );
1036   connect( targetBtn,     SIGNAL( clicked() ), 
1037            this,          SLOT( browseDirectory() ) );
1038   connect( tempFolder,    SIGNAL( textChanged( const QString& ) ),
1039            this,          SLOT( directoryChanged( const QString& ) ) );
1040   connect( tempBtn,       SIGNAL( clicked() ), this, SLOT( browseDirectory() ) );
1041
1042   // adding page
1043   addPage( dirPage, tr( "Installation directories" ) );
1044 }
1045 // ================================================================
1046 /*!
1047  *  SALOME_InstallWizard::setupProductsPage
1048  *  Creates products page
1049  */
1050 // ================================================================
1051 void SALOME_InstallWizard::setupProductsPage()
1052 {
1053   // create page
1054   productsPage = new QWidget( this, "ProductsPage" );
1055   QGridLayout* pageLayout = new QGridLayout( productsPage );
1056   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1057   //
1058   // create left column widgets
1059   //
1060   QVBoxLayout* leftBoxLayout = new QVBoxLayout;
1061   leftBoxLayout->setMargin( 0 ); leftBoxLayout->setSpacing( 6 );
1062   // ... modules list
1063   modulesView = new ProductsView( productsPage, "modulesView" );
1064   setAboutInfo( modulesView, tr( "The modules available for the installation" ) );
1065   modulesView->setColumnAlignment( 1, Qt::AlignRight );
1066   leftBoxLayout->addWidget( modulesView );
1067   // ... 'Installation with GUI' checkbox
1068   installGuiBtn = new QMyCheckBox( tr( "Installation with GUI" ), productsPage );
1069   setAboutInfo( installGuiBtn, tr( "Check this option if you want\nto install SALOME with GUI" ) );
1070   leftBoxLayout->addWidget( installGuiBtn );
1071   // ... prerequisites list
1072   prereqsView = new ProductsView( productsPage, "prereqsView" );
1073   prereqsView->renameColumn( 0, "Prerequisite" );
1074   setAboutInfo( prereqsView, tr( "The prerequisites that can be installed" ) );
1075   prereqsView->setColumnAlignment( 1, Qt::AlignRight );
1076   leftBoxLayout->addWidget( prereqsView );
1077   // ... 'Show/Hide prerequisites' button
1078   moreBtn = new QPushButton( tr( "Show prerequisites..." ), productsPage );
1079   setAboutInfo( moreBtn, tr( "Click to show list of prerequisites" ) );
1080   leftBoxLayout->addWidget( moreBtn );
1081   //
1082   // create right column widgets
1083   //
1084   // ... info box
1085   productInfo = new QTextBrowser( productsPage );
1086   productInfo->setFrameShape( QFrame::LineEditPanel );
1087   productInfo->setPaletteBackgroundColor( productsPage->paletteBackgroundColor() );
1088   setAboutInfo( productInfo, tr( "Short information about the product being selected" ) );
1089   // ... disk space labels
1090   QLabel* reqLab1 = new QLabel( tr( "Disk space required:" ), productsPage );
1091   setAboutInfo( reqLab1, tr( "Total disk space required for the installation\nof the selected products" ) );
1092   requiredSize = new QLabel( productsPage );
1093   setAboutInfo( requiredSize, tr( "Total disk space required for the installation\nof the selected products" ) );
1094   requiredSize->setAlignment( Qt::AlignRight );
1095   QLabel* reqLab2 = new QLabel( tr( "Space for temporary files:" ), productsPage );
1096   setAboutInfo( reqLab2, tr( "Disk space required for the temporary files" ) );
1097   requiredTemp = new QLabel( productsPage );
1098   setAboutInfo( requiredTemp, tr( "Disk space required for the temporary files" ) );
1099   requiredTemp->setAlignment( Qt::AlignRight );
1100   QLabel* reqLab3 = new QLabel( tr( "Available disk space:" ), productsPage );
1101   setAboutInfo( reqLab3, tr( "Disk space available on the selected device" ) );
1102   availableSize = new QLabel( productsPage );
1103   setAboutInfo( availableSize, tr( "Disk space available on the selected device" ) );
1104   availableSize->setAlignment( Qt::AlignRight );
1105   // layout size widgets
1106   QGridLayout* sizeLayout = new QGridLayout; sizeLayout->setMargin( 0 ); sizeLayout->setSpacing( 6 );
1107   sizeLayout->addWidget( reqLab1,       0, 0 );
1108   sizeLayout->addWidget( requiredSize,  0, 1 );
1109   sizeLayout->addWidget( reqLab2,       1, 0 );
1110   sizeLayout->addWidget( requiredTemp,  1, 1 );
1111   sizeLayout->addWidget( reqLab3,       2, 0 );
1112   sizeLayout->addWidget( availableSize, 2, 1 );
1113
1114   // layout common widgets
1115   pageLayout->addMultiCellLayout( leftBoxLayout, 0, 1, 0, 0 );
1116   pageLayout->addWidget         ( productInfo,   0,    1    );
1117   pageLayout->addLayout         ( sizeLayout,    1,    1    );
1118
1119   // adding page
1120   addPage( productsPage, tr( "Choice of the products to be installed" ) );
1121
1122   // connecting signals
1123   connect( modulesView,   SIGNAL( selectionChanged() ),
1124            this, SLOT( onSelectionChanged() ) );
1125   connect( prereqsView,   SIGNAL( selectionChanged() ),
1126            this, SLOT( onSelectionChanged() ) );
1127   connect( modulesView,   SIGNAL( clicked ( QListViewItem * item ) ),
1128            this, SLOT( onSelectionChanged() ) );
1129   connect( prereqsView,   SIGNAL( clicked ( QListViewItem * item ) ),
1130            this, SLOT( onSelectionChanged() ) );
1131   connect( modulesView,   SIGNAL( itemToggled( QCheckListItem* ) ),
1132            this, SLOT( onItemToggled( QCheckListItem* ) ) );
1133   connect( prereqsView,   SIGNAL( itemToggled( QCheckListItem* ) ),
1134            this, SLOT( onItemToggled( QCheckListItem* ) ) );
1135   connect( installGuiBtn, SIGNAL( toggled( bool ) ), 
1136            this, SLOT( onInstallGuiBtn() ) );
1137   connect( moreBtn, SIGNAL( clicked() ), this, SLOT( onMoreBtn() ) );
1138   // start on default - non-advanced mode
1139   prereqsView->hide();
1140 }
1141 // ================================================================
1142 /*!
1143  *  SALOME_InstallWizard::setupCheckPage
1144  *  Creates prestart page
1145  */
1146 // ================================================================
1147 void SALOME_InstallWizard::setupCheckPage()
1148 {
1149   // create page
1150   prestartPage = new QWidget( this, "PrestartPage" );
1151   QVBoxLayout* pageLayout = new QVBoxLayout( prestartPage );
1152   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1153   // choice text view
1154   choices = new QTextEdit( prestartPage );
1155   choices->setReadOnly( true );
1156   choices->setTextFormat( RichText );
1157   choices->setUndoRedoEnabled ( false );
1158   setAboutInfo( choices, tr( "Information about the installation choice you have made" ) );
1159   choices->setPaletteBackgroundColor( prestartPage->paletteBackgroundColor() );
1160   choices->setMinimumHeight( 10 );
1161   // layouting
1162   pageLayout->addWidget( choices );
1163   pageLayout->setStretchFactor( choices, 5 );
1164   // adding page
1165   addPage( prestartPage, tr( "Check your choice" ) );
1166 }
1167 // ================================================================
1168 /*!
1169  *  SALOME_InstallWizard::setupProgressPage
1170  *  Creates progress page
1171  */
1172 // ================================================================
1173 void SALOME_InstallWizard::setupProgressPage()
1174 {
1175   // create page
1176   progressPage = new QWidget( this, "progressPage" );
1177   QGridLayout* pageLayout = new QGridLayout( progressPage );
1178   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1179   // top splitter
1180   splitter = new QSplitter( Vertical, progressPage );
1181   splitter->setOpaqueResize( true );
1182   // the parent for the widgets
1183   QWidget* widget = new QWidget( splitter );
1184   QGridLayout* layout = new QGridLayout( widget );
1185   layout->setMargin( 0 ); layout->setSpacing( 6 );
1186   // installation progress view box
1187   installInfo = new InstallInfo( widget );
1188   installInfo->setReadOnly( true );
1189   installInfo->setTextFormat( RichText );
1190   installInfo->setUndoRedoEnabled ( false );
1191   installInfo->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
1192   installInfo->setMinimumSize( 100, 10 );
1193   setAboutInfo( installInfo, tr( "Installation process output" ) );
1194   // parameters for the script
1195   parametersLab = new QLabel( tr( "Enter your answer here:" ), widget );
1196   passedParams = new QLineEdit ( widget );
1197   setAboutInfo( passedParams, tr( "Use this field to enter the answer\nfor the running script when it is necessary") );
1198   // VSR: 10/11/05 - disable answer mode ==>
1199   parametersLab->hide();
1200   passedParams->hide();
1201   // VSR: 10/11/05 - disable answer mode <==
1202   // layouting
1203   layout->addWidget( installInfo,   0, 0 );
1204   layout->addWidget( parametersLab, 1, 0 );
1205   layout->addWidget( passedParams,  2, 0 );
1206   layout->addRowSpacing( 3, 6 );
1207   // the parent for the widgets
1208   widget = new QWidget( splitter );
1209   layout = new QGridLayout( widget );
1210   layout->setMargin( 0 ); layout->setSpacing( 6 );
1211   // installation results view box
1212   QLabel* resultLab = new QLabel( tr( "Installation Status:" ), widget );
1213   progressView = new ProgressView( widget );
1214   progressView->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ) );
1215   progressView->setMinimumSize( 100, 10 );
1216   statusLab = new QLabel( widget );
1217   statusLab->setFrameShape( QButtonGroup::LineEditPanel );
1218   setAboutInfo( progressView, tr( "Installation status on the selected products" ) );
1219   // layouting
1220   layout->addRowSpacing( 0, 6 );
1221   layout->addWidget( resultLab,    1, 0 );
1222   layout->addWidget( progressView, 2, 0 );
1223   layout->addWidget( statusLab,    3, 0 );
1224   // layouting
1225   pageLayout->addWidget( splitter,  0, 0 );
1226   // adding page
1227   addPage( progressPage, tr( "Installation progress" ) );
1228   // connect signals
1229   connect( passedParams, SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) ) ;
1230 }
1231 // ================================================================
1232 /*!
1233  *  SALOME_InstallWizard::setupReadmePage
1234  *  Creates readme page
1235  */
1236 // ================================================================
1237 void SALOME_InstallWizard::setupReadmePage()
1238 {
1239   // create page
1240   readmePage = new QWidget( this, "readmePage" );
1241   QVBoxLayout* pageLayout = new QVBoxLayout( readmePage );
1242   pageLayout->setMargin( 0 ); pageLayout->setSpacing( 6 );
1243   // README info text box
1244   readme = new QTextEdit( readmePage );
1245   readme->setReadOnly( true );
1246   readme->setTextFormat( PlainText );
1247   readme->setFont( QFont( "Fixed", 12 ) );
1248   readme->setUndoRedoEnabled ( false );
1249   setAboutInfo( readme, tr( "README information" ) );
1250   readme->setPaletteBackgroundColor( readmePage->paletteBackgroundColor() );
1251   readme->setMinimumHeight( 10 );
1252
1253   pageLayout->addWidget( readme );
1254   pageLayout->setStretchFactor( readme, 5 );
1255
1256   // Operation buttons
1257   QHBoxLayout* hLayout = new QHBoxLayout( -1, "finishButtons" );
1258   hLayout->setMargin( 0 ); hLayout->setSpacing( 6 );
1259   hLayout->addStretch();
1260   pageLayout->addLayout( hLayout );
1261
1262   // loading README file
1263   QString readmeFile = QDir::currentDirPath() + "/README";
1264   QString text;
1265   if ( readFile( readmeFile, text ) )
1266     readme->setText( text );
1267   else
1268     readme->setText( tr( "README file has not been found" ) );
1269
1270   // adding page
1271   addPage( readmePage, tr( "Finish installation" ) );
1272 }
1273 // ================================================================
1274 /*!
1275  *  SALOME_InstallWizard::showChoiceInfo
1276  *  Displays choice info
1277  */
1278 // ================================================================
1279 void SALOME_InstallWizard::showChoiceInfo()
1280 {
1281   choices->clear();
1282
1283   long totSize, tempSize;
1284   checkSize( &totSize, &tempSize );
1285   int nbProd = 0;
1286   QString text;
1287
1288   text += tr( "Current Linux platform" )+ ": <b>" + (!curPlatform.isEmpty() ? curPlatform : QString( "Unknown" )) + "</b><br>";
1289   if ( !refPlatform.isEmpty() )
1290     text += tr( "Reference Linux platform" ) + ": <b>" + refPlatform + "</b><br>";
1291   text += "<br>";
1292
1293   text += tr( "Target directory:" ) + " <b>" + QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) + "</b><br>";
1294   text += tr( "Temporary directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
1295   text += "<br>";
1296
1297   text += tr( "SALOME modules to be installed" ) + ":<ul>";
1298   QCheckListItem* item = (QCheckListItem*)( modulesView->firstChild() );
1299   while( item ) {
1300     if ( productsMap.contains( item ) ) {
1301       if ( item->isOn() ) {
1302         text += "<li><b>" + item->text() + "</b><br>";
1303         nbProd++;
1304       }
1305     }
1306     item = (QCheckListItem*)( item->nextSibling() );
1307   }
1308   if ( nbProd == 0 ) {
1309     text += "<li><b>" + tr( "none" ) + "</b><br>";
1310   }
1311   text += "</ul>";
1312   nbProd = 0;
1313   text += tr( "Prerequisites to be installed" ) + ":<ul>";
1314   item = (QCheckListItem*)( prereqsView->firstChild() );
1315   while( item ) {
1316     if ( productsMap.contains( item ) ) {
1317       if ( productsMap[ item ].hasType( "salome sources" ) || 
1318            productsMap[ item ].hasType( "salome binaries" ) ) {
1319         item = (QCheckListItem*)( item->nextSibling() );
1320         continue; // skip SALOME sources and binaries
1321       }
1322       if ( item->isOn() ) {
1323         text += "<li><b>" + item->text() + " " + productsMap[ item ].getVersion() + "</b><br>";
1324         nbProd++;
1325       }
1326     }
1327     item = (QCheckListItem*)( item->nextSibling() );
1328   }
1329   if ( nbProd == 0 ) {
1330     text += "<li><b>" + tr( "none" ) + "</b><br>";
1331   }
1332   text += "</ul>";
1333   text += tr( "Total disk space required:" ) + " <b>" + QString::number( totSize ) + " KB</b><br>" ;
1334   text += tr( "Space for temporary files required:" ) + " <b>" + QString::number( tempSize ) + " KB</b><br>" ;
1335   choices->setText( text );
1336 }
1337 // ================================================================
1338 /*!
1339  *  SALOME_InstallWizard::acceptData
1340  *  Validates page when <Next> button is clicked
1341  */
1342 // ================================================================
1343 bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
1344 {
1345   QString tmpstr;
1346   QWidget* aPage = InstallWizard::page( pageTitle );
1347   if ( aPage == typePage ) {
1348     // installation type page
1349     if ( installType == Binaries ) { // 'Binary' installation type
1350       // check binaries directory
1351       QFileInfo fib( QDir::cleanDirPath( getBinPath() ) );
1352       if ( !fib.exists() ) {
1353         QMessageBox::warning( this,
1354                               tr( "Warning" ),
1355                               tr( "The directory %1 doesn't exist.\n"
1356                                   "This directory must contain sources archives.\n").arg( fib.absFilePath() ),
1357                               QMessageBox::Ok,
1358                               QMessageBox::NoButton, 
1359                               QMessageBox::NoButton );
1360         return false;
1361       }
1362       // check sources directory
1363       QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
1364       if ( !fis.exists() )
1365         if ( QMessageBox::warning( this,
1366                                    tr( "Warning" ),
1367                                    tr( "The directory %1 doesn't exist.\n"
1368                                        "This directory must contain sources archives.\n"
1369                                        "Continue?" ).arg( fis.absFilePath() ),
1370                                    tr( "&Yes" ),
1371                                    tr( "&No" ), 
1372                                    QString::null, 1, 1 ) == 1 )
1373           return false;
1374     }
1375     else { // 'Source' or 'Compile' installation type
1376       // check sources directory
1377       QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
1378       if ( !fis.exists() ) {
1379         QMessageBox::warning( this,
1380                               tr( "Warning" ),
1381                               tr( "The directory %1 doesn't exist.\n"
1382                                   "This directory must contain sources archives.\n" ).arg( fis.absFilePath() ),
1383                               QMessageBox::Ok,
1384                               QMessageBox::NoButton, 
1385                               QMessageBox::NoButton );
1386         return false;
1387       }
1388     }
1389   }
1390
1391   else if ( aPage == dirPage ) {
1392     // installation platform page
1393     // ########## check target and temp directories (existence and available disk space)
1394     // get dirs
1395     QString targetDir = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1396     QString tempDir   = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() );
1397     // check target directory
1398     if ( targetDir.isEmpty() ) {
1399       QMessageBox::warning( this,
1400                             tr( "Warning" ),
1401                             tr( "Please, enter valid target directory path" ),
1402                             QMessageBox::Ok,
1403                             QMessageBox::NoButton,
1404                             QMessageBox::NoButton );
1405       return false;
1406     }
1407     QFileInfo fi( QDir::cleanDirPath( targetDir ) );
1408     if ( !fi.exists() ) {
1409       bool toCreate =
1410         QMessageBox::warning( this,
1411                               tr( "Warning" ),
1412                               tr( "The directory %1 doesn't exist.\n"
1413                                   "Create directory?" ).arg( fi.absFilePath() ),
1414                               QMessageBox::Yes,
1415                               QMessageBox::No,
1416                               QMessageBox::NoButton ) == QMessageBox::Yes;
1417       if ( !toCreate)
1418         return false;
1419       if ( !makeDir( fi.absFilePath(), tmpstr ) ) {
1420         QMessageBox::critical( this,
1421                                tr( "Error" ),
1422                                tr( "Can't create the directory\n%1").arg( fi.absFilePath() ),
1423                                QMessageBox::Ok,
1424                                QMessageBox::NoButton,
1425                                QMessageBox::NoButton );
1426         return false;
1427       }
1428     }
1429     if ( !fi.isDir() ) {
1430       QMessageBox::warning( this,
1431                             tr( "Warning" ),
1432                             tr( "%1 is not a directory.\n"
1433                                 "Please, enter valid target directory path" ).arg( fi.absFilePath() ),
1434                             QMessageBox::Ok,
1435                             QMessageBox::NoButton,
1436                             QMessageBox::NoButton );
1437       return false;
1438     }
1439     if ( !fi.isWritable() ) {
1440       QMessageBox::warning( this,
1441                             tr( "Warning" ),
1442                             tr( "The directory %1 is not writeable.\n"
1443                                 "Please, enter valid target directory path or change permissions" ).arg( fi.absFilePath() ),
1444                             QMessageBox::Ok,
1445                             QMessageBox::NoButton,
1446                             QMessageBox::NoButton );
1447       return false;
1448     }
1449     if ( hasSpace( fi.absFilePath() ) &&
1450          QMessageBox::warning( this,
1451                                tr( "Warning" ),
1452                                tr( "The target directory contains space symbols.\n"
1453                                    "This may cause problems with compiling or installing of products.\n\n"
1454                                    "Do you want to continue?"),
1455                                QMessageBox::Yes,
1456                                QMessageBox::No,
1457                                QMessageBox::NoButton ) == QMessageBox::No ) {
1458       return false;
1459     }
1460     // check temp directory
1461     if ( tempDir.isEmpty() ) {
1462       QMessageBox::warning( this,
1463                             tr( "Warning" ),
1464                             tr( "Please, enter valid temporary directory path" ),
1465                             QMessageBox::Ok,
1466                             QMessageBox::NoButton,
1467                             QMessageBox::NoButton );
1468       return false;
1469     }
1470     QFileInfo fit( QDir::cleanDirPath( tempDir ) );
1471     if ( !makeDir( fit.absFilePath() + TEMPDIRNAME, tmpCreated ) ) {
1472       QMessageBox::critical( this,
1473                              tr( "Error" ),
1474                              tr( "Can't use temporary directory.\nCheck permissions for the %1 directory.").arg( fit.absFilePath() ),
1475                              QMessageBox::Ok,
1476                              QMessageBox::NoButton,
1477                              QMessageBox::NoButton );
1478       return false;
1479     }
1480   }
1481
1482   else if ( aPage == productsPage ) {
1483     // products page
1484     // ########## check if any products are selected to be installed
1485     long totSize, tempSize;
1486     bool anySelected = checkSize( &totSize, &tempSize );
1487     if ( !anySelected ) {
1488       QMessageBox::warning( this,
1489                             tr( "Warning" ),
1490                             tr( "Select one or more products to install" ),
1491                             QMessageBox::Ok,
1492                             QMessageBox::NoButton,
1493                             QMessageBox::NoButton );
1494       return false;
1495     }
1496     // run script that checks available disk space for installing of products    // returns 1 in case of error
1497     QFileInfo fi( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) );
1498     QString script = "./config_files/checkSize.sh '";
1499     script += fi.absFilePath();
1500     script += "' ";
1501     script += QString( "%1" ).arg( totSize );
1502     ___MESSAGE___( "script = " << script.latin1() );
1503     if ( system( script ) ) {
1504       QMessageBox::critical( this,
1505                              tr( "Out of space" ),
1506                              tr( "There is no available disk space for installing of selected products" ),
1507                              QMessageBox::Ok,
1508                              QMessageBox::NoButton,
1509                              QMessageBox::NoButton );
1510       return false;
1511     }
1512     // run script that check available disk space for temporary files
1513     // returns 1 in case of error
1514     QFileInfo fit( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) );
1515     QString tscript = "./config_files/checkSize.sh '";
1516     tscript += fit.absFilePath();
1517     tscript += "' ";
1518     tscript += QString( "%1" ).arg( tempSize );
1519     ___MESSAGE___( "script = " << tscript.latin1() );
1520     if ( system( tscript ) ) {
1521       QMessageBox::critical( this,
1522                              tr( "Out of space" ),
1523                              tr( "There is no available disk space for the temporary files" ),
1524                              QMessageBox::Ok,
1525                              QMessageBox::NoButton,
1526                              QMessageBox::NoButton );
1527       return false;
1528     }
1529     // ########## check installation scripts
1530     QCheckListItem* item;
1531     ProductsView* prodsView = modulesView;
1532     for ( int i = 0; i < 2; i++ ) {
1533       item = (QCheckListItem*)( prodsView->firstChild() );
1534       while( item ) {
1535         if ( productsMap.contains( item ) && item->isOn() ) {
1536           // check installation script definition
1537           if ( item->text(2).isEmpty() || item->text(2).isNull() ) {
1538             QMessageBox::warning( this,
1539                                   tr( "Error" ),
1540                                   tr( "The installation script for %1 is not defined.").arg(item->text(0)),
1541                                   QMessageBox::Ok,
1542                                   QMessageBox::NoButton,
1543                                   QMessageBox::NoButton );
1544             if ( !moreMode ) onMoreBtn();
1545             QListView* listView = item->listView();
1546             listView->setCurrentItem( item );
1547             listView->setSelected( item, true );
1548             listView->ensureItemVisible( item );
1549             return false;
1550           }
1551           // check installation script existence
1552           else {
1553             QFileInfo fi( QString("./config_files/") + item->text(2) );
1554             if ( !fi.exists() || !fi.isExecutable() ) {
1555               QMessageBox::warning( this,
1556                                     tr( "Error" ),
1557                                     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)),
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           }
1569           // check installation scripts dependencies
1570           QStringList dependOn = productsMap[ item ].getDependancies();
1571           QString version = productsMap[ item ].getVersion();
1572           for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1573             QCheckListItem* depitem = findItem( dependOn[ i ] );
1574             if ( !depitem ) {
1575               QMessageBox::warning( this,
1576                                     tr( "Error" ),
1577                                     tr( "%1 is required for %2 %3 installation.\n"
1578                                         "This product is missing in the configuration file %4.").arg(dependOn[ i ]).arg(item->text(0)).arg(version).arg(xmlFileName),
1579                                     QMessageBox::Ok,
1580                                     QMessageBox::NoButton,
1581                                     QMessageBox::NoButton );
1582               return false;
1583             }
1584           }
1585         }
1586         item = (QCheckListItem*)( item->nextSibling() );
1587       }
1588       prodsView = prereqsView;
1589     }
1590 //     return true; // return in order to avoid default postValidateEvent() action
1591   }
1592   return InstallWizard::acceptData( pageTitle );
1593 }
1594 // ================================================================
1595 /*!
1596  *  SALOME_InstallWizard::checkSize
1597  *  Calculates disk space required for the installation
1598  */
1599 // ================================================================
1600 bool SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
1601 {
1602   long tots = 0, temps = 0;
1603   long maxSrcTmp = 0;
1604   int nbSelected = 0;
1605
1606   MapProducts::Iterator mapIter;
1607   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1608     QCheckListItem* item = mapIter.key();
1609     Dependancies dep = mapIter.data();
1610     if ( !item->isOn() )
1611       continue;
1612     if ( installType == Compile && removeSrcBtn->state() == QButton::On )
1613       tots += dep.getSize( Binaries );
1614     else
1615       tots += dep.getSize( installType );
1616     maxSrcTmp = max( maxSrcTmp, dep.getSize( Compile ) - dep.getSize( Binaries ) );
1617     temps += dep.getTempSize( installType );
1618     nbSelected++;
1619   }
1620
1621   if ( totSize )
1622     if ( installType == Compile && removeSrcBtn->state() == QButton::On )
1623       tots += maxSrcTmp;
1624     *totSize = tots;
1625   if ( tempSize )
1626     *tempSize = temps;
1627   return ( nbSelected > 0 );
1628 }
1629 // ================================================================
1630 /*!
1631  *  SALOME_InstallWizard::updateAvailableSpace
1632  *  Slot to update 'Available disk space' field
1633  */
1634 // ================================================================
1635 void SALOME_InstallWizard::updateAvailableSpace()
1636 {
1637   if ( diskSpaceProc->normalExit() )
1638     availableSize->setText( diskSpaceProc->readLineStdout() + " KB");
1639 }
1640 // ================================================================
1641 /*!
1642  *  SALOME_InstallWizard::checkProductPage
1643  *  Checks products page validity (directories and products selection) and
1644  *  enabled/disables "Next" button for the Products page
1645  */
1646 // ================================================================
1647 void SALOME_InstallWizard::checkProductPage()
1648 {
1649   if ( this->currentPage() != productsPage )
1650     return;
1651   long tots = 0, temps = 0;
1652   // check if any product is selected;
1653   bool isAnyProductSelected = checkSize( &tots, &temps );
1654
1655   // update required size information
1656   requiredSize->setText( QString::number( tots )  + " KB");
1657   requiredTemp->setText( QString::number( temps ) + " KB");
1658
1659   // update available size information
1660   QFileInfo fi( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) );
1661   if ( fi.exists() ) {
1662     diskSpaceProc->clearArguments();
1663     QString script = "./config_files/diskSpace.sh";
1664     diskSpaceProc->addArgument( script );
1665     diskSpaceProc->addArgument( fi.absFilePath() );
1666     // run script
1667     diskSpaceProc->start();
1668   }
1669
1670   // enable/disable "Next" button
1671   setNextEnabled( productsPage, isAnyProductSelected );
1672 }
1673 // ================================================================
1674 /*!
1675  *  SALOME_InstallWizard::setPrerequisites
1676  *  Sets the product and all products this one depends on to be checked ( recursively )
1677  */
1678 // ================================================================
1679 void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
1680 {
1681   if ( !productsMap.contains( item ) )
1682     return;
1683   if ( !item->isOn() )
1684     return;
1685   // get all prerequisites
1686   QStringList dependOn = productsMap[ item ].getDependancies();
1687   // install MED without GUI case
1688   if ( installGuiBtn->state() != QButton::On && item->text(0) == "MED" ) {
1689     dependOn.remove( "GUI" );
1690   }
1691   // setting prerequisites
1692   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1693     MapProducts::Iterator itProd;
1694     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1695       if ( itProd.data().getName() == dependOn[ i ] ) {
1696         if ( itProd.data().getType() == "component" && !itProd.key()->isOn() )
1697           itProd.key()->setOn( true );
1698         else if ( itProd.data().getType() == "prerequisite" ) {
1699           itProd.key()->setOn( true );
1700           itProd.key()->setEnabled( false );
1701         }
1702       }
1703     }
1704   }
1705 }
1706 // ================================================================
1707 /*!
1708  *  SALOME_InstallWizard::unsetPrerequisites
1709  *  Unsets all modules which depend of the unchecked product ( recursively )
1710  */
1711 // ================================================================
1712 void SALOME_InstallWizard::unsetPrerequisites( QCheckListItem* item )
1713 {
1714   if ( !productsMap.contains( item ) )
1715     return;
1716   if ( item->isOn() )
1717     return;
1718
1719 // uncheck dependent products
1720   QString itemName = productsMap[ item ].getName();
1721   MapProducts::Iterator itProd;
1722   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1723     if ( itProd.data().getType() == productsMap[ item ].getType() ) {
1724       QStringList dependOn = itProd.data().getDependancies();
1725       // install MED without GUI case
1726       if ( installGuiBtn->state() != QButton::On && itemName == "GUI" ) {
1727         dependOn.remove( "MED" );
1728       }
1729       for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1730         if ( dependOn[ i ] == itemName ) {
1731           if ( itProd.key()->isOn() ) {
1732             itProd.key()->setOn( false );
1733           }
1734         }
1735       }
1736     }
1737   }
1738
1739 // uncheck prerequisites
1740   int nbDependents;
1741 //   cout << "item name = " << productsMap[ item ].getName() << endl;
1742   QStringList dependOnList = productsMap[ item ].getDependancies();
1743   for ( int j = 0; j < (int)dependOnList.count(); j++ ) {
1744     nbDependents = 0;
1745     MapProducts::Iterator itProd1;
1746     for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
1747       if ( itProd1.data().getName() == dependOnList[ j ] ) {
1748         if ( itProd1.data().getType() == "prerequisite" ) {
1749           MapProducts::Iterator itProd2;
1750           for ( itProd2 = productsMap.begin(); itProd2 != productsMap.end(); ++itProd2 ) {
1751             //      if ( itProd2.data().getType() == "component" ) {
1752             if ( itProd2.key()->isOn() ) {
1753               QStringList prereqsList = productsMap[ itProd2.key() ].getDependancies();
1754               for ( int k = 0; k < (int)prereqsList.count(); k++ ) {
1755                 if ( prereqsList[ k ] == itProd1.data().getName() ) {
1756                   nbDependents++;
1757                 }
1758               }
1759             }
1760           }
1761           if ( nbDependents == 0 ) {
1762             itProd1.key()->setEnabled( true );
1763             itProd1.key()->setOn( false );
1764           }
1765         }
1766       }
1767     }
1768   }
1769 }
1770 // ================================================================
1771 /*!
1772  *  SALOME_InstallWizard::launchScript
1773  *  Runs installation script
1774  */
1775 // ================================================================
1776 void SALOME_InstallWizard::launchScript()
1777 {
1778   // try to find product being processed now
1779   QString prodProc = progressView->findStatus( Processing );
1780   if ( !prodProc.isNull() ) {
1781     ___MESSAGE___( "Found <Processing>: " );
1782
1783     // if found - set status to "completed"
1784     progressView->setStatus( prodProc, Completed );
1785     // ... clear status label
1786     statusLab->clear();
1787     // ... and call this method again
1788     launchScript();
1789     return;
1790   }
1791   // else try to find next product which is not processed yet
1792   prodProc = progressView->findStatus( Waiting );
1793   if ( !prodProc.isNull() ) {
1794     ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
1795     // if found - set status to "processed" and run script
1796     progressView->setStatus( prodProc, Processing );
1797     progressView->ensureVisible( prodProc );
1798     
1799     QCheckListItem* item;
1800     if ( prodProc != "gcc" )
1801       item = findItem( prodProc );
1802     // fill in script parameters
1803     shellProcess->clearArguments();
1804     // ... script name
1805     shellProcess->setWorkingDirectory( QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() ) );
1806     if ( prodProc != "gcc" )
1807       shellProcess->addArgument( item->text(2) );
1808     else
1809       shellProcess->addArgument( "gcc-common.sh" );
1810
1811     // ... temp folder
1812     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1813     //if( !tempFolder->isEnabled() )
1814     //  tmpFolder = "/tmp";
1815
1816     // ... not install : try to find preinstalled
1817     if ( !progressView->isVisible( prodProc ) ) {
1818       shellProcess->addArgument( "try_preinstalled" );
1819       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1820       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1821       statusLab->setText( tr( "Collecting environment for '" ) + prodProc + "'..." );
1822     }
1823     // ... binaries ?
1824     else if ( installType == Binaries ) {
1825       shellProcess->addArgument( "install_binary" );
1826       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1827       QString binDir = QDir::cleanDirPath( getBinPath() );
1828       QString OS = getPlatform();
1829       if ( !OS.isEmpty() )
1830         binDir += "/" + OS;
1831       shellProcess->addArgument( binDir );
1832       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
1833     }
1834     // ... sources or sources_and_compilation ?
1835     else {
1836       shellProcess->addArgument( installType == Sources ? "install_source" : 
1837                                  "install_source_and_build" );
1838       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1839       shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
1840       statusLab->setText( tr( "Installing '" ) + prodProc + "'..." );
1841     }
1842     // ... target folder
1843     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1844     shellProcess->addArgument( QFileInfo( tgtFolder ).absFilePath() );
1845     // ... list of all products
1846     QString depproducts = DefineDependeces(productsMap);
1847     depproducts.prepend( "gcc " );
1848     ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
1849     shellProcess->addArgument( depproducts );
1850     // ... product name - currently installed product
1851     if ( prodProc != "gcc" )
1852       shellProcess->addArgument( item->text(0) );
1853     else
1854       shellProcess->addArgument( "gcc" );
1855     // ... list of products being installed
1856     shellProcess->addArgument( prodSequence.join( " " ) );
1857     // ... sources directory
1858     shellProcess->addArgument( QDir::cleanDirPath( getSrcPath() ) );
1859     // ... remove sources and tmp files or not?
1860     if ( installType == Compile && removeSrcBtn->state() == QButton::On )
1861       shellProcess->addArgument( "TRUE" );
1862     else 
1863       shellProcess->addArgument( "FALSE" );
1864     // ... install MED with GUI or not?
1865     if ( installGuiBtn->state() != QButton::On && prodProc == "MED" && 
1866          (installType == Binaries || installType == Compile) )
1867       shellProcess->addArgument( "FALSE" );
1868     // run script
1869     if ( !shellProcess->start() ) {
1870       // error handling can be here
1871       ___MESSAGE___( "error" );
1872     }
1873     return;
1874   }
1875   ___MESSAGE___( "All products have been installed successfully" );
1876   // all products are installed successfully
1877   MapProducts::Iterator mapIter;
1878   ___MESSAGE___( "starting pick-up environment" );
1879   QString depproducts = QUOTE( DefineDependeces(productsMap).prepend( "gcc " ) );
1880   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1881     QCheckListItem* item = mapIter.key();
1882     Dependancies dep = mapIter.data();
1883     if ( item->isOn() && dep.pickUpEnvironment() ) {
1884       statusLab->setText( tr( "Pick-up products environment for " ) + dep.getName().latin1() + "..." );
1885       ___MESSAGE___( "... for " << dep.getName().latin1() );
1886       QString script;
1887       script += "cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
1888       script += item->text(2) + " ";
1889       script += "pickup_env ";
1890       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
1891       script += QUOTE( QFileInfo( QDir::cleanDirPath( QDir::currentDirPath() + "/Products" ) ).absFilePath() ) + " ";
1892       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
1893       script += depproducts + " ";
1894       script += item->text(0) + " ";
1895       script += QUOTE( prodSequence.join( " " ) );
1896       ___MESSAGE___( "... --> " << script.latin1() );
1897       if ( system( script.latin1() ) ) {
1898         ___MESSAGE___( "ERROR" );
1899       }
1900     }
1901   }
1902   // update status label
1903   statusLab->setText( tr( "Installation completed" ) );
1904   // <Next> button
1905   setNextEnabled( true );
1906   nextButton()->setText( tr( "&Next >" ) );
1907   setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
1908   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1909   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1910   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1911   // <Back> button
1912   setBackEnabled( true );
1913   // script parameters
1914   passedParams->clear();
1915   passedParams->setEnabled( false );
1916   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1917   installInfo->setFinished( true );
1918   if ( isMinimized() )
1919     showNormal();
1920   raise();
1921   if ( hasErrors ) {
1922     if ( QMessageBox::warning( this,
1923                                tr( "Warning" ),
1924                                tr( "There were some errors and/or warnings during the installation.\n"
1925                                    "Do you want to save the installation log?" ),
1926                                tr( "&Save" ),
1927                                tr( "&Cancel" ),
1928                                QString::null,
1929                                0,
1930                                1 ) == 0 )
1931       saveLog();
1932   }
1933   hasErrors = false;
1934 }
1935 // ================================================================
1936 /*!
1937  *  SALOME_InstallWizard::onInstallGuiBtn
1938  *  <Installation with GUI> check-box slot
1939  */
1940 // ================================================================
1941 void SALOME_InstallWizard::onInstallGuiBtn()
1942 {
1943   MapProducts::Iterator itProd;
1944   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1945     if ( itProd.data().getType() == "component" ) {
1946       if ( installGuiBtn->state() == QButton::On ) {
1947         itProd.key()->setEnabled( true );
1948         itProd.key()->setOn( true );
1949       }
1950       else {
1951         QString itemName = itProd.data().getName();
1952         if ( itemName != "KERNEL" && itemName != "MED" && itemName != "SAMPLES" ) {
1953           itProd.key()->setOn( false );
1954           itProd.key()->setEnabled( false );
1955         }
1956         else
1957           itProd.key()->setOn( true );
1958       }
1959     }
1960   }
1961 }
1962 // ================================================================
1963 /*!
1964  *  SALOME_InstallWizard::onMoreBtn
1965  *  <More...> button slot
1966  */
1967 // ================================================================
1968 void SALOME_InstallWizard::onMoreBtn()
1969 {
1970   if ( moreMode ) {
1971     prereqsView->hide();
1972     moreBtn->setText( tr( "Show prerequisites..." ) );
1973     setAboutInfo( moreBtn, tr( "Show list of prerequisites" ) );
1974   }
1975   else {
1976     prereqsView->show();
1977     moreBtn->setText( tr( "Hide prerequisites" ) );
1978     setAboutInfo( moreBtn, tr( "Hide list of prerequisites" ) );
1979   }
1980   qApp->processEvents();
1981   moreMode = !moreMode;
1982   InstallWizard::layOut();
1983   qApp->processEvents();
1984   if ( !isMaximized() ) {
1985     qApp->processEvents();
1986   }
1987   checkProductPage();
1988 }
1989 // ================================================================
1990 /*!
1991  *  SALOME_InstallWizard::onFinishButton
1992  *  Operation buttons slot
1993  */
1994 // ================================================================
1995 void SALOME_InstallWizard::onFinishButton()
1996 {
1997   const QObject* btn = sender();
1998   ButtonList::Iterator it;
1999   for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2000     if ( (*it).button() && (*it).button() == btn ) {
2001       QString script;
2002       script += "( cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
2003       script +=  + (*it).script();
2004       script += " execute ";
2005       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
2006       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
2007       script += " > /dev/null )";
2008       ___MESSAGE___( "script: " << script.latin1() );
2009       if ( (*it).script().isEmpty() || system( script.latin1() ) ) {
2010         QMessageBox::warning( this,
2011                               tr( "Error" ),
2012                               tr( "Can't perform action!"),
2013                               QMessageBox::Ok,
2014                               QMessageBox::NoButton,
2015                               QMessageBox::NoButton );
2016       }
2017       return;
2018     }
2019   }
2020 }
2021 // ================================================================
2022 /*!
2023  *  SALOME_InstallWizard::onAbout
2024  *  <About> button slot: shows <About> dialog box
2025  */
2026 // ================================================================
2027 void SALOME_InstallWizard::onAbout()
2028 {
2029   AboutDlg d( this );
2030   d.exec();
2031 }
2032
2033 // ================================================================
2034 /*!
2035  *  SALOME_InstallWizard::findItem
2036  *  Searches product listview item with given symbolic name
2037  */
2038 // ================================================================
2039 QCheckListItem* SALOME_InstallWizard::findItem( const QString& sName )
2040 {
2041   MapProducts::Iterator mapIter;
2042   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2043     if ( mapIter.data().getName() == sName )
2044       return mapIter.key();
2045   }
2046   return 0;
2047 }
2048 // ================================================================
2049 /*!
2050  *  SALOME_InstallWizard::abort
2051  *  Sets progress state to Aborted
2052  */
2053 // ================================================================
2054 void SALOME_InstallWizard::abort()
2055 {
2056   QString prod = progressView->findStatus( Processing );
2057   while ( !prod.isNull() ) {
2058     progressView->setStatus( prod, Aborted );
2059     prod = progressView->findStatus( Processing );
2060   }
2061   prod = progressView->findStatus( Waiting );
2062   while ( !prod.isNull() ) {
2063     progressView->setStatus( prod, Aborted );
2064     prod = progressView->findStatus( Waiting );
2065   }
2066 }
2067 // ================================================================
2068 /*!
2069  *  SALOME_InstallWizard::reject
2070  *  Reject slot, clears temporary directory and closes application
2071  */
2072 // ================================================================
2073 void SALOME_InstallWizard::reject()
2074 {
2075   ___MESSAGE___( "REJECTED" );
2076   if ( !exitConfirmed ) {
2077     if ( QMessageBox::information( this,
2078                                    tr( "Exit" ),
2079                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
2080                                    tr( "&Yes" ),
2081                                    tr( "&No" ),
2082                                    QString::null,
2083                                    0,
2084                                    1 ) == 1 ) {
2085       return;
2086     }
2087     exitConfirmed = true;
2088   }
2089   clean(true);
2090   InstallWizard::reject();
2091 }
2092 // ================================================================
2093 /*!
2094  *  SALOME_InstallWizard::accept
2095  *  Accept slot, clears temporary directory and closes application
2096  */
2097 // ================================================================
2098 void SALOME_InstallWizard::accept()
2099 {
2100   ___MESSAGE___( "ACCEPTED" );
2101   clean(true);
2102   InstallWizard::accept();
2103 }
2104 // ================================================================
2105 /*!
2106  *  SALOME_InstallWizard::clean
2107  *  Clears and (optionally) removes temporary directory
2108  */
2109 // ================================================================
2110 void SALOME_InstallWizard::clean(bool rmDir)
2111 {
2112   WarnDialog::showWarnDlg( 0, false );
2113   myThread->clearCommands();
2114   myWC.wakeAll();
2115   while ( myThread->running() );
2116   // first remove temporary files
2117   QString script = "cd ./config_files/; remove_tmp.sh '";
2118   script += tempFolder->text().stripWhiteSpace() + TEMPDIRNAME;
2119   script += "' ";
2120   script += QUOTE(DefineDependeces(productsMap));
2121   script += " > /dev/null";
2122   ___MESSAGE___( "script = " << script.latin1() );
2123   if ( system( script.latin1() ) ) {
2124   }
2125   // then try to remove created temporary directory
2126   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
2127   if ( rmDir && !tmpCreated.isNull() ) {
2128     script = "rm -rf " + tmpCreated;
2129     script += " > /dev/null";
2130     if ( system( script.latin1() ) ) {
2131     }
2132     ___MESSAGE___( "script = " << script.latin1() );
2133   }
2134 }
2135 // ================================================================
2136 /*!
2137  *  SALOME_InstallWizard::pageChanged
2138  *  Called when user moves from page to page
2139  */
2140 // ================================================================
2141 void SALOME_InstallWizard::pageChanged( const QString & mytitle)
2142 {
2143   nextButton()->setText( tr( "&Next >" ) );
2144   setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
2145   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2146   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2147   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2148   cancelButton()->disconnect();
2149   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
2150
2151   QWidget* aPage = InstallWizard::page( mytitle );
2152   if ( !aPage )
2153     return;
2154   updateCaption();
2155
2156   if ( aPage == typePage ) {
2157     // installation type page
2158     if ( buttonGrp->id( buttonGrp->selected() ) == -1 )
2159       binBtn->animateClick(); // set default installation type
2160   }
2161   if ( aPage == platformsPage ) {
2162     // installation platforms page
2163     MapXmlFiles::Iterator it;
2164     if ( previousPage == typePage ) {
2165       for ( it = platformsMap.begin(); it != platformsMap.end(); ++it ) {
2166         QString plat = it.key();
2167         QRadioButton* rb = ( (QRadioButton*) platBtnGrp->child( plat ) );
2168         if ( installType == Binaries ) {
2169           QFileInfo fib( QDir::cleanDirPath( getBinPath() + "/" + plat ) );
2170           rb->setEnabled( fib.exists() );
2171         }
2172         else {
2173           QFileInfo fis( QDir::cleanDirPath( getSrcPath() ) );
2174           rb->setEnabled( fis.exists() );
2175         }
2176         rb->setChecked( rb->isChecked() && rb->isEnabled() );
2177       }
2178       setNextEnabled( platformsPage, platBtnGrp->id( platBtnGrp->selected() ) != -1 );
2179     }
2180   }
2181   else  if ( aPage == dirPage ) {
2182     // installation and temporary directories page
2183     if ( ( indexOf( platformsPage ) != -1 ? 
2184            previousPage == platformsPage : previousPage == typePage ) 
2185          && stateChanged ) {
2186       // clear global variables before reading XML file
2187       modulesView->clear();
2188       prereqsView->clear();
2189       productsMap.clear();
2190       // read XML file
2191       StructureParser* parser = new StructureParser( this );
2192       parser->setProductsLists( modulesView, prereqsView );
2193       if ( targetFolder->text().isEmpty() )
2194         parser->setTargetDir( targetFolder );
2195       if ( tempFolder->text().isEmpty() )
2196         parser->setTempDir( tempFolder );
2197       parser->readXmlFile( xmlFileName );
2198       // take into account command line parameters
2199       if ( !myTargetPath.isEmpty() )
2200         targetFolder->setText( myTargetPath );
2201       if ( !myTmpPath.isEmpty() )
2202         tempFolder->setText( myTmpPath );
2203       // set all modules to be checked and first module to be selected
2204       installGuiBtn->setState( QButton::Off );
2205       installGuiBtn->setState( QButton::On );
2206       if ( modulesView->childCount() > 0 && !modulesView->selectedItem() )
2207         modulesView->setSelected( modulesView->firstChild(), true );
2208       stateChanged = false;
2209     }
2210   }
2211   else if ( aPage == productsPage ) {
2212     // products page
2213     onSelectionChanged();
2214     checkProductPage();
2215   }
2216   else if ( aPage == prestartPage ) {
2217     // prestart page
2218     showChoiceInfo();
2219   }
2220   else if ( aPage == progressPage ) {
2221     if ( previousPage == prestartPage ) {
2222       // progress page
2223       statusLab->clear();
2224       progressView->clear();
2225       installInfo->clear();
2226       installInfo->setFinished( false );
2227       passedParams->clear();
2228       passedParams->setEnabled( false );
2229       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2230       nextButton()->setText( tr( "&Start" ) );
2231       setAboutInfo( nextButton(), tr( "Start installation process" ) );
2232       // reconnect Next button - to use it as Start button
2233       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2234       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2235       connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2236       setNextEnabled( true );
2237       // reconnect Cancel button to terminate process
2238       cancelButton()->disconnect();
2239       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
2240     }
2241   }
2242   else if ( aPage == readmePage ) {
2243     ButtonList::Iterator it;
2244     for ( it = buttons.begin(); it != buttons.end(); ++it ) {
2245       if ( (*it).button() ) {
2246         QString script;
2247         script += "( cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
2248         script +=  + (*it).script();
2249         script += " check_enabled ";
2250         script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
2251         script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
2252         script += " > /dev/null )";
2253         ___MESSAGE___( "script: " << script.latin1() );
2254         (*it).button()->setEnabled( !(*it).script().isEmpty() && !system( script.latin1() ) );
2255       }
2256     }
2257     finishButton()->setEnabled( true );
2258   }
2259   previousPage = aPage;
2260   ___MESSAGE___( "previousPage = " << previousPage );
2261 }
2262 // ================================================================
2263 /*!
2264  *  SALOME_InstallWizard::onButtonGroup
2265  *  Called when user selected either installation type or installation platform
2266  */
2267 // ================================================================
2268 void SALOME_InstallWizard::onButtonGroup( int rbIndex )
2269 {
2270   int prevType = installType;
2271   QString prevPlat = getPlatform();
2272   QWidget* aPage = InstallWizard::currentPage();
2273   if ( aPage == typePage ) {
2274     installType = InstallationType( rbIndex );
2275     // management of the <Remove source and tmp files> check-box
2276     removeSrcBtn->setEnabled( installType == Compile );
2277   }
2278   else if ( aPage == platformsPage ) {
2279     refPlatform = platBtnGrp->find( rbIndex )->name();
2280     xmlFileName = platformsMap[ refPlatform ];
2281     cout << xmlFileName << endl;
2282     setNextEnabled( platformsPage, true );
2283   }
2284   if ( prevType != installType || 
2285        ( indexOf( platformsPage ) != -1 ? prevPlat != getPlatform() : false ) ) {
2286     stateChanged = true;
2287   }
2288 }
2289 // ================================================================
2290 /*!
2291  *  SALOME_InstallWizard::helpClicked
2292  *  Shows help window
2293  */
2294 // ================================================================
2295 void SALOME_InstallWizard::helpClicked()
2296 {
2297   if ( helpWindow == NULL ) {
2298     helpWindow = HelpWindow::openHelp( this );
2299     if ( helpWindow ) {
2300       helpWindow->show();
2301       helpWindow->installEventFilter( this );
2302     }
2303     else {
2304       QMessageBox::warning( this,
2305                             tr( "Help file not found" ),
2306                             tr( "Sorry, help is unavailable" ) );
2307     }
2308   }
2309   else {
2310     helpWindow->raise();
2311     helpWindow->setActiveWindow();
2312   }
2313 }
2314 // ================================================================
2315 /*!
2316  *  SALOME_InstallWizard::browseDirectory
2317  *  Shows directory selection dialog
2318  */
2319 // ================================================================
2320 void SALOME_InstallWizard::browseDirectory()
2321 {
2322   const QObject* theSender = sender();
2323   QLineEdit* theFolder;
2324   if ( theSender == targetBtn )
2325     theFolder = targetFolder;
2326   else if (theSender == tempBtn)
2327     theFolder = tempFolder;
2328   else
2329     return;
2330   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
2331   if ( !typedDir.isNull() ) {
2332     theFolder->setText( typedDir );
2333     theFolder->end( false );
2334   }
2335 }
2336 // ================================================================
2337 /*!
2338  *  SALOME_InstallWizard::directoryChanged
2339  *  Called when directory path (target or temp) is changed
2340  */
2341 // ================================================================
2342 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
2343 {
2344   checkProductPage();
2345 }
2346 // ================================================================
2347 /*!
2348  *  SALOME_InstallWizard::onStart
2349  *  <Start> button's slot - runs installation
2350  */
2351 // ================================================================
2352 void SALOME_InstallWizard::onStart()
2353 {
2354   cout << "" << endl;
2355   if ( nextButton()->text() == tr( "&Stop" ) ) {
2356     statusLab->setText( tr( "Aborting installation..." ) );
2357     shellProcess->kill();
2358     while( shellProcess->isRunning() );
2359     statusLab->setText( tr( "Installation has been aborted by user" ) );
2360     return;
2361   }
2362   hasErrors = false;
2363   progressView->clear();
2364   installInfo->clear();
2365   installInfo->setFinished( false );
2366   passedParams->clear();
2367   passedParams->setEnabled( false );
2368   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2369   // update status label
2370   statusLab->setText( tr( "Preparing for installation..." ) );
2371   // clear lists of products
2372   toInstall.clear();
2373   notInstall.clear();
2374   // ... and fill it for new process
2375   toInstall.append( "gcc" );
2376   QCheckListItem* item = (QCheckListItem*)( prereqsView->firstChild() );
2377   while( item ) {
2378     if ( productsMap.contains( item ) ) {
2379       if ( item->isOn() )
2380         toInstall.append( productsMap[item].getName() );
2381       else
2382         notInstall.append( productsMap[item].getName() );
2383     }
2384     item = (QCheckListItem*)( item->nextSibling() );
2385   }
2386   item = (QCheckListItem*)( modulesView->firstChild() );
2387   while( item ) {
2388     if ( productsMap.contains( item ) ) {
2389       if ( item->isOn() )
2390         toInstall.append( productsMap[item].getName() );
2391       else
2392         notInstall.append( productsMap[item].getName() );
2393     }
2394     item = (QCheckListItem*)( item->nextSibling() );
2395   }
2396   // if something at all is selected
2397   if ( (int)toInstall.count() > 1 ) {
2398     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
2399     // disable <Next> button
2400     //setNextEnabled( false );
2401     nextButton()->setText( tr( "&Stop" ) );
2402     setAboutInfo( nextButton(), tr( "Abort installation process" ) );
2403     // disable <Back> button
2404     setBackEnabled( false );
2405     // enable script parameters line edit
2406     // VSR commented: 18/09/03: passedParams->setEnabled( true );
2407     // VSR commented: 18/09/03: passedParams->setFocus();
2408     ProgressViewItem* progressItem;
2409     // set status for installed products
2410     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
2411       if ( toInstall[i] != "gcc" ) {
2412         item = findItem( toInstall[i] );
2413         progressView->addProduct( item->text(0), item->text(2) );
2414         continue;
2415       }
2416       progressItem = progressView->addProduct( "gcc", "gcc-common.sh" );
2417       progressItem->setVisible( false );
2418     }
2419     // set status for not installed products
2420     for ( int i = 0; i < (int)notInstall.count(); i++ ) {
2421       item = findItem( notInstall[i] );
2422       progressItem = progressView->addProduct( item->text(0), item->text(2) );
2423       progressItem->setVisible( false );
2424     }
2425     // get specified list of products being installed
2426     prodSequence.clear();
2427     for (int i = 0; i<(int)toInstall.count(); i++ ) {
2428       if ( toInstall[i] == "gcc" ) {
2429         prodSequence.append( toInstall[i] );
2430         continue;
2431       }
2432       if ( installType == Binaries ) {
2433         prodSequence.append( toInstall[i] );
2434         QString prodType;
2435         MapProducts::Iterator mapIter;
2436         for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
2437           if ( mapIter.data().getName() == toInstall[i] && mapIter.data().getType() == "component" ) {
2438             prodSequence.append( toInstall[i] + "_src" );
2439             break;
2440           }
2441         }
2442       }
2443       else if ( installType == Sources )
2444         prodSequence.append( toInstall[i] + "_src" );
2445       else {
2446         prodSequence.append( toInstall[i] );
2447         prodSequence.append( toInstall[i] + "_src" );
2448       }
2449     }
2450
2451     // create a backup of 'env_build.csh', 'env_build.sh', 'env_products.csh', 'env_products.sh'
2452     // ( backup of 'salome.csh' and 'salome.sh' is made if pick-up environment is called )
2453     QString script = "./config_files/backupEnv.sh ";
2454     script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() );
2455     ___MESSAGE___( "script = " << script.latin1() );
2456     if ( system( script ) ) {
2457       if ( QMessageBox::warning( this,
2458                                  tr( "Warning" ),
2459                                  tr( "Backup environment files have not been created.\n"
2460                                      "Do you want to continue an installation process?" ),
2461                                  tr( "&Yes" ),
2462                                  tr( "&No" ), 
2463                                  QString::null, 0, 1 ) == 1 ) {
2464         // installation aborted
2465         abort();
2466         statusLab->setText( tr( "Installation has been aborted by user" ) );
2467         // enable <Next> button
2468         setNextEnabled( true );
2469         nextButton()->setText( tr( "&Start" ) );
2470         setAboutInfo( nextButton(), tr( "Start installation process" ) );
2471         // reconnect Next button - to use it as Start button
2472         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2473         disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2474         connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2475         // enable <Back> button
2476         setBackEnabled( true );
2477         return;
2478       }
2479     }
2480
2481     // launch install script
2482     launchScript();
2483   }
2484 }
2485 // ================================================================
2486 /*!
2487  *  SALOME_InstallWizard::onReturnPressed
2488  *  Called when users tries to pass parameters for the script
2489  */
2490 // ================================================================
2491 void SALOME_InstallWizard::onReturnPressed()
2492 {
2493   QString txt = passedParams->text();
2494   installInfo->append( txt );
2495   txt += "\n";
2496   shellProcess->writeToStdin( txt );
2497   passedParams->clear();
2498   progressView->setFocus();
2499   passedParams->setEnabled( false );
2500   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2501 }
2502 /*!
2503   Callback function - as response for the script finishing
2504 */
2505 void SALOME_InstallWizard::productInstalled()
2506 {
2507   ___MESSAGE___( "process exited" );
2508   if ( shellProcess->normalExit() ) {
2509     ___MESSAGE___( "...normal exit" );
2510     // normal exit - try to proceed installation further
2511     launchScript();
2512   }
2513   else {
2514     ___MESSAGE___( "...abnormal exit" );
2515     statusLab->setText( tr( "Script is not completed and installation has been aborted" ) );
2516     // installation aborted
2517     abort();
2518     // clear script passed parameters lineedit
2519     passedParams->clear();
2520     passedParams->setEnabled( false );
2521     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2522     installInfo->setFinished( true );
2523     // enable <Next> button
2524     setNextEnabled( true );
2525     nextButton()->setText( tr( "&Start" ) );
2526     setAboutInfo( nextButton(), tr( "Start installation process" ) );
2527     // reconnect Next button - to use it as Start button
2528     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2529     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2530     connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2531     //nextButton()->setText( tr( "&Next >" ) );
2532     //setAboutInfo( nextButton(), tr( "Move to the next step of the installation procedure" ) );
2533     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2534     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2535     //connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2536     // enable <Back> button
2537     setBackEnabled( true );
2538   }
2539 }
2540 // ================================================================
2541 /*!
2542  *  SALOME_InstallWizard::tryTerminate
2543  *  Slot, called when <Cancel> button is clicked during installation script running
2544  */
2545 // ================================================================
2546 void SALOME_InstallWizard::tryTerminate()
2547 {
2548   if ( shellProcess->isRunning() ) {
2549     if ( QMessageBox::information( this,
2550                                    tr( "Exit" ),
2551                                    tr( "Do you want to quit %1?" ).arg( getIWName() ),
2552                                    tr( "&Yes" ),
2553                                    tr( "&No" ),
2554                                    QString::null,
2555                                    0,
2556                                    1 ) == 1 ) {
2557       return;
2558     }
2559     exitConfirmed = true;
2560     // if process still running try to terminate it first
2561     shellProcess->tryTerminate();
2562     abort();
2563     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
2564     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
2565   }
2566   else {
2567     // else just quit install wizard
2568     reject();
2569   }
2570 }
2571 // ================================================================
2572 /*!
2573  *  SALOME_InstallWizard::onCancel
2574  *  Kills installation process and quits application
2575  */
2576 // ================================================================
2577 void SALOME_InstallWizard::onCancel()
2578 {
2579   shellProcess->kill();
2580   reject();
2581 }
2582 // ================================================================
2583 /*!
2584  *  SALOME_InstallWizard::onSelectionChanged
2585  *  Called when selection is changed in the products list view
2586  */
2587 // ================================================================
2588 void SALOME_InstallWizard::onSelectionChanged()
2589 {
2590   const QObject* snd = sender();
2591   productInfo->clear();
2592   QListViewItem* item = modulesView->selectedItem();
2593   if ( snd == prereqsView )
2594     item = prereqsView->selectedItem();
2595   if ( !item )
2596     return;
2597   QCheckListItem* anItem = (QCheckListItem*)item;
2598   if ( !productsMap.contains( anItem ) )
2599     return;
2600   Dependancies dep = productsMap[ anItem ];
2601   QString text = "<b>" + anItem->text(0) + "</b>" + "<br>";
2602   if ( !dep.getVersion().isEmpty() )
2603     text += tr( "Version" ) + ": " + dep.getVersion() + "<br>";
2604   text += "<br>";
2605   if ( !dep.getDescription().isEmpty() ) {
2606     text += "<i>" + dep.getDescription() + "</i><br><br>";
2607   }
2608   long totSize = 0, tempSize = 0;
2609   if ( installType == Compile && removeSrcBtn->state() == QButton::On )
2610     totSize = dep.getSize( Binaries );
2611   else
2612     totSize = dep.getSize( installType );
2613   tempSize = dep.getTempSize( installType );
2614   text += tr( "Disk space required" ) + ": " + QString::number( totSize ) + " KB<br>";
2615   text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " KB<br>";
2616   text += "<br>";
2617   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
2618   text +=  tr( "Prerequisites" ) + ": " + req;
2619   productInfo->setText( text );
2620 }
2621 // ================================================================
2622 /*!
2623  *  SALOME_InstallWizard::onItemToggled
2624  *  Called when user checks/unchecks any product item
2625  *  Recursively sets all prerequisites and updates "Next" button state
2626  */
2627 // ================================================================
2628 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
2629 {
2630   if ( productsMap.contains( item ) ) {
2631     if ( item->isOn() )
2632       setPrerequisites( item );
2633     else 
2634       unsetPrerequisites( item );
2635   }
2636   onSelectionChanged();
2637   checkProductPage();
2638 }
2639 // ================================================================
2640 /*!
2641  *  SALOME_InstallWizard::wroteToStdin
2642  *  QProcess slot: -->something was written to stdin
2643  */
2644 // ================================================================
2645 void SALOME_InstallWizard::wroteToStdin( )
2646 {
2647   ___MESSAGE___( "Something was sent to stdin" );
2648 }
2649 // ================================================================
2650 /*!
2651  *  SALOME_InstallWizard::readFromStdout
2652  *  QProcess slot: -->something was written to stdout
2653  */
2654 // ================================================================
2655 void SALOME_InstallWizard::readFromStdout( )
2656 {
2657   ___MESSAGE___( "Something was sent to stdout" );
2658   while ( shellProcess->canReadLineStdout() ) {
2659     installInfo->append( QString( shellProcess->readLineStdout() ) );
2660     installInfo->scrollToBottom();
2661   }
2662   QString str( shellProcess->readStdout() );
2663   if ( !str.isEmpty() ) {
2664     installInfo->append( str );
2665     installInfo->scrollToBottom();
2666   }
2667 }
2668
2669 #define OUTLINE_TEXT(x) QString( "<font color=#FF0000><b>" ) + QString( x ) + QString( "</b></font>" )
2670
2671 // ================================================================
2672 /*!
2673  *  SALOME_InstallWizard::readFromStderr
2674  *  QProcess slot: -->something was written to stderr
2675  */
2676 // ================================================================
2677 void SALOME_InstallWizard::readFromStderr( )
2678 {
2679   ___MESSAGE___( "Something was sent to stderr" );
2680   while ( shellProcess->canReadLineStderr() ) {
2681     installInfo->append( OUTLINE_TEXT( QString( shellProcess->readLineStderr() ) ) );
2682     installInfo->scrollToBottom();
2683     hasErrors = true;
2684   }
2685   QString str( shellProcess->readStderr() );
2686   if ( !str.isEmpty() ) {
2687     installInfo->append( OUTLINE_TEXT( str ) );
2688     installInfo->scrollToBottom();
2689     hasErrors = true;
2690   }
2691   // VSR: 10/11/05 - disable answer mode ==>
2692   // passedParams->setEnabled( true );
2693   // passedParams->setFocus();
2694   // QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
2695   // VSR: 10/11/05 - disable answer mode <==
2696 }
2697 // ================================================================
2698 /*!
2699  *  SALOME_InstallWizard::setDependancies
2700  *  Sets dependancies for the product item
2701  */
2702 // ================================================================
2703 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
2704 {
2705   productsMap[item] = dep;
2706 }
2707 // ================================================================
2708 /*!
2709  *  SALOME_InstallWizard::addFinishButton
2710  *  Add button for the <Finish> page.
2711  *  Clear list of buttons if <toClear> flag is true.
2712  */
2713 // ================================================================
2714 void SALOME_InstallWizard::addFinishButton( const QString& label,
2715                                             const QString& tooltip,
2716                                             const QString& script,
2717                                             bool toClear )
2718 {
2719   ButtonList btns;
2720   if ( toClear ) {
2721     btns = buttons;
2722     buttons.clear();
2723   }
2724   buttons.append( Button( label, tooltip, script ) );
2725   // create finish buttons
2726   QButton* b = new QPushButton( tr( buttons.last().label() ), readmePage );
2727   if ( !buttons.last().tootip().isEmpty() )
2728     setAboutInfo( b, tr( buttons.last().tootip() ) );
2729   QHBoxLayout* hLayout = (QHBoxLayout*)readmePage->layout()->child("finishButtons");
2730   if ( toClear ) {
2731     // remove previous buttons
2732     ButtonList::Iterator it;
2733     for ( it = btns.begin(); it != btns.end(); ++it ) {
2734       hLayout->removeChild( (*it).button() );
2735       delete (*it).button();
2736     }
2737   }
2738   // add buttons to finish page
2739   hLayout->insertWidget( buttons.count()-1, b );
2740   buttons.last().setButton( b );
2741   connect( b, SIGNAL( clicked() ), this, SLOT( onFinishButton() ) );
2742 }
2743 // ================================================================
2744 /*!
2745  *  SALOME_InstallWizard::polish
2746  *  Polishing of the widget - to set right initial size
2747  */
2748 // ================================================================
2749 void SALOME_InstallWizard::polish()
2750 {
2751   resize( 0, 0 );
2752   InstallWizard::polish();
2753 }
2754 // ================================================================
2755 /*!
2756  *  SALOME_InstallWizard::saveLog
2757  *  Save installation log to file
2758  */
2759 // ================================================================
2760 void SALOME_InstallWizard::saveLog()
2761 {
2762   QString txt = installInfo->text();
2763   if ( txt.length() <= 0 )
2764     return;
2765   QDateTime dt = QDateTime::currentDateTime();
2766   QString fileName = dt.toString("ddMMyy-hhmm");
2767   fileName.prepend("install-"); fileName.append(".html");
2768   fileName = QFileDialog::getSaveFileName( fileName,
2769                                            QString( "HTML files (*.htm *.html)" ),
2770                                            this, 0,
2771                                            tr( "Save Log file" ) );
2772   if ( !fileName.isEmpty() ) {
2773     QFile f( fileName );
2774     if ( f.open( IO_WriteOnly ) ) {
2775       QTextStream stream( &f );
2776       stream << txt;
2777       f.close();
2778     }
2779     else {
2780       QMessageBox::critical( this,
2781                              tr( "Error" ),
2782                              tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ),
2783                              QMessageBox::Ok,
2784                              QMessageBox::NoButton,
2785                              QMessageBox::NoButton );
2786     }
2787   }
2788 }
2789 // ================================================================
2790 /*!
2791  *  SALOME_InstallWizard::updateCaption
2792  *  Updates caption according to the current page number
2793  */
2794 // ================================================================
2795 void SALOME_InstallWizard::updateCaption()
2796 {
2797   QWidget* aPage = InstallWizard::currentPage();
2798   if ( !aPage )
2799     return;
2800   InstallWizard::setCaption( tr( myCaption ) + " " +
2801                              tr( getIWName() ) + " - " +
2802                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
2803 }
2804
2805 // ================================================================
2806 /*!
2807  *  SALOME_InstallWizard::processValidateEvent
2808  *  Processes validation event (<val> is validation code)
2809  */
2810 // ================================================================
2811 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
2812 {
2813   QWidget* aPage = InstallWizard::currentPage();
2814   if ( aPage != productsPage ) {
2815     InstallWizard::processValidateEvent( val, data );
2816     return;
2817   }
2818   myMutex.lock();
2819   myMutex.unlock();
2820   if ( val > 0 ) {
2821   }
2822   if ( myThread->hasCommands() )
2823     myWC.wakeAll();
2824   else {
2825     WarnDialog::showWarnDlg( 0, false );
2826     InstallWizard::processValidateEvent( val, data );
2827   }
2828 }