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