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