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