Salome HOME
acedde53dea629edc5e7c6a45d96c4280b13d75b
[tools/install.git] / src / SALOME_InstallWizard.cxx
1 //  File      : SALOME_InstallWizard.cxx 
2 //  Created   : Thu Dec 18 12:01:00 2002
3 //  Author    : Vadim SANDLER, Open CASCADE SAS (vadim.sandler@opencascade.com)
4 //  Project   : SALOME
5 //  Module    : Installation Wizard
6 //  Copyright : 2002-2006 CEA
7
8 #include "globals.h"
9
10 #include "SALOME_InstallWizard.hxx"
11 #include "SALOME_ProductsView.hxx"
12 #include "SALOME_ProgressView.hxx"
13 #include "SALOME_XmlHandler.hxx"
14 #include "SALOME_HelpWindow.hxx"
15
16 #include "icons.h"
17
18 #include <qlineedit.h>
19 #include <qpushbutton.h>
20 #include <qlistview.h>
21 #include <qlabel.h>
22 #include <qtextedit.h>
23 #include <qtextbrowser.h>
24 #include <qprocess.h>
25 #include <qcheckbox.h>
26 #include <qsplitter.h>
27 #include <qlayout.h>
28 #include <qfiledialog.h> 
29 #include <qapplication.h>
30 #include <qfileinfo.h> 
31 #include <qmessagebox.h> 
32 #include <qtimer.h> 
33 #include <qvbox.h>
34 #include <qwhatsthis.h> 
35 #include <qtooltip.h>
36 #include <qfile.h>
37 #include <qthread.h>
38 #include <qwaitcondition.h>
39 #include <qmutex.h>
40 #include <qstringlist.h>
41 #include <qpopupmenu.h>
42
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
938   pageLayout->addWidget( readme );
939   pageLayout->setStretchFactor( readme, 5 );
940
941   // Operation buttons
942   if ( buttons.count() > 0 ) {
943     QHBoxLayout* hLayout = new QHBoxLayout;
944     hLayout->setMargin( 0 ); hLayout->setSpacing( 6 );
945     ButtonList::Iterator it;
946     for ( it = buttons.begin(); it != buttons.end(); ++it ) {
947       QButton* b = new QPushButton( tr( (*it).label() ), readmePage );
948       if ( !(*it).tootip().isEmpty() ) {
949         QWhatsThis::add( b, tr( (*it).tootip() ) );
950         QToolTip::add  ( b, tr( (*it).tootip() ) );
951       }
952       hLayout->addWidget( b ); 
953       (*it).setButton( b );
954       connect( b, SIGNAL( clicked() ), this, SLOT( onFinishButton() ) );
955     }
956     hLayout->addStretch();
957     pageLayout->addLayout( hLayout );
958   }
959
960   // loading README file
961   QString readmeFile = QDir::currentDirPath() + "/README";
962   QString text;
963   if ( readFile( readmeFile, text ) )
964     readme->setText( text );
965   else
966     readme->setText( tr( "README file has not been found" ) );
967
968   // adding page
969   addPage( readmePage, tr( "Finish installation" ) );
970 }
971 // ================================================================
972 /*!
973  *  SALOME_InstallWizard::showChoiceInfo
974  *  Displays choice info
975  */
976 // ================================================================
977 void SALOME_InstallWizard::showChoiceInfo()
978 {
979   choices->clear();
980
981   long totSize, tempSize;
982   checkSize( &totSize, &tempSize );
983   int nbProd = 0;
984   QString text;
985
986   if ( !xmlFileName.isEmpty() ) {
987     text += tr( "Configuration file" )+ ": <b>" + xmlFileName + "</b><br>";
988     text += "<br>";
989   }
990   if ( !myOS.isEmpty() ) {
991     text += tr( "Reference Linux platform" ) + ": <b>" + myOS + "</b><br>";
992     text += "<br>";
993   }
994   text += tr( "Native products to be used" ) + ":<ul>";
995   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
996   while( item ) {
997     if ( productsMap.contains( item ) ) {
998       if ( item->childCount() > 0 ) {
999         if ( productsView->isNative( item ) ) {
1000           text += "<li><b>" + item->text() + "</b><br>";
1001           nbProd++;
1002         }
1003       }
1004     }
1005     item = (QCheckListItem*)( item->nextSibling() );
1006   }
1007   if ( nbProd == 0 ) {
1008     text += "<li><b>" + tr( "none" ) + "</b><br>";
1009   }
1010   text += "</ul>";
1011   nbProd = 0;
1012   text += tr( "Products to be installed" ) + ":<ul>";
1013   item = (QCheckListItem*)( productsView->firstChild() );
1014   while( item ) {
1015     if ( productsMap.contains( item ) ) {
1016       if ( item->childCount() > 0 ) {
1017         if ( productsView->isBinaries( item ) ) {
1018           text += "<li><b>" + item->text() + " " + item->text(1) + "</b> " + tr( "as binaries" ) + "<br>";
1019           nbProd++;
1020         }
1021         else if ( productsView->isSources( item ) ) {
1022           text+= "<li><b>" + item->text() + " " + item->text(1) + "</b> " + tr( "as sources" ) + "<br>";
1023           nbProd++;
1024         }
1025       }
1026       else if ( item->isOn() ) {
1027         text+= "<li><b>" + item->text() + "</b><br>";
1028         nbProd++;
1029       }
1030     }
1031     item = (QCheckListItem*)( item->nextSibling() );
1032   }
1033   if ( nbProd == 0 ) {
1034     text += "<li><b>" + tr( "none" ) + "</b><br>";
1035   }
1036   text += "</ul>";
1037   text += tr( "Total disk space required:" ) + " <b>" + QString::number( totSize ) + " Kb</b><br>" ;
1038   text += tr( "Space for temporary files required:" ) + " <b>" + QString::number( tempSize ) + " Kb</b><br>" ;
1039   text += "<br>";
1040   text += tr( "Target directory:" ) + " <b>" + QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) + "</b><br>";
1041   // VSR: Temporary folder is used always now and it is not necessary to disable it -->
1042   // if ( tempSize > 0 )
1043   // VSR: <----------------------------------------------------------------------------
1044   text += tr( "Temporary directory:" ) + " <b>" + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "</b><br>";
1045   text += "<br>";
1046   choices->setText( text );
1047 }
1048 // ================================================================
1049 /*!
1050  *  SALOME_InstallWizard::acceptData
1051  *  Validates page when <Next> button is clicked
1052  */
1053 // ================================================================
1054 bool SALOME_InstallWizard::acceptData( const QString& pageTitle )
1055 {
1056   QString tmpstr;
1057   QWidget* aPage = InstallWizard::page( pageTitle );
1058   if ( aPage == productsPage ) {
1059     // ########## check if any products are selected to be installed
1060     long totSize, tempSize;
1061     bool anySelected = checkSize( &totSize, &tempSize );
1062     if ( !anySelected ) {
1063       QMessageBox::warning( this, 
1064                             tr( "Warning" ), 
1065                             tr( "Select one or more products to install" ), 
1066                             QMessageBox::Ok, 
1067                             QMessageBox::NoButton,
1068                             QMessageBox::NoButton );
1069       return false;
1070     }
1071     // ########## check target and temp directories (existence and available disk space)
1072     // get dirs
1073     QString targetDir = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1074     QString tempDir   = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() );
1075     // directories should differ
1076 //    if (!targetDir.isEmpty() && tempDir == targetDir) {
1077 //      QMessageBox::warning( this, 
1078 //                          tr( "Warning" ), 
1079 //                          tr( "Target and temporary directories must be different"), 
1080 //                          QMessageBox::Ok, 
1081 //                          QMessageBox::NoButton, 
1082 //                          QMessageBox::NoButton );
1083 //      return false;
1084 //    }
1085     // check target directory
1086     if ( targetDir.isEmpty() ) {
1087       QMessageBox::warning( this, 
1088                             tr( "Warning" ), 
1089                             tr( "Please, enter valid target directory path" ), 
1090                             QMessageBox::Ok, 
1091                             QMessageBox::NoButton,
1092                             QMessageBox::NoButton );
1093       return false;
1094     }
1095     QFileInfo fi( QDir::cleanDirPath( targetDir ) );
1096     if ( !fi.exists() ) {
1097       bool toCreate = 
1098         QMessageBox::warning( this, 
1099                               tr( "Warning" ), 
1100                               tr( "The directory %1 doesn't exist.\n"
1101                                   "Create directory?" ).arg( fi.absFilePath() ), 
1102                               QMessageBox::Yes, 
1103                               QMessageBox::No,
1104                               QMessageBox::NoButton ) == QMessageBox::Yes;
1105       if ( !toCreate) 
1106         return false;
1107       if ( !makeDir( fi.absFilePath(), tmpstr ) ) {
1108         QMessageBox::critical( this, 
1109                                tr( "Error" ), 
1110                                tr( "Can't create the directory\n%1").arg( fi.absFilePath() ), 
1111                                QMessageBox::Ok, 
1112                                QMessageBox::NoButton, 
1113                                QMessageBox::NoButton );
1114         return false;
1115       }
1116     }
1117     if ( !fi.isDir() ) {
1118       QMessageBox::warning( this, 
1119                             tr( "Warning" ), 
1120                             tr( "%1 is not a directory.\n"
1121                                 "Please, enter valid target directory path" ).arg( fi.absFilePath() ), 
1122                             QMessageBox::Ok, 
1123                             QMessageBox::NoButton,
1124                             QMessageBox::NoButton );
1125       return false;
1126     }
1127     if ( !fi.isWritable() ) {
1128       QMessageBox::warning( this, 
1129                             tr( "Warning" ), 
1130                             tr( "The directory %1 is not writeable.\n"
1131                                 "Please, enter valid target directory path or change permissions" ).arg( fi.absFilePath() ), 
1132                             QMessageBox::Ok, 
1133                             QMessageBox::NoButton,
1134                             QMessageBox::NoButton );
1135       return false;
1136     }
1137     if ( hasSpace( fi.absFilePath() ) &&
1138          QMessageBox::warning( this,
1139                                tr( "Warning" ),
1140                                tr( "The target directory contains space symbols.\n"
1141                                    "This may cause problems with compiling or installing of products.\n\n"
1142                                    "Do you want to continue?"),
1143                                QMessageBox::Yes,
1144                                QMessageBox::No,
1145                                QMessageBox::NoButton ) == QMessageBox::No ) {
1146       return false;
1147     }
1148     // check sources/binaries archives directories existance
1149     int nbSources = 0, nbBinaries = 0; 
1150     QCheckListItem* nitem = (QCheckListItem*)( productsView->firstChild() );
1151     while( nitem ) {
1152       if ( productsMap.contains( nitem ) ) {
1153         if ( nitem->childCount() > 0 ) {
1154           if ( productsView->isBinaries( nitem ) )
1155             nbBinaries++;
1156           else if ( productsView->isSources( nitem ) )
1157             nbSources++;
1158         }
1159         else if ( nitem->isOn() ) {
1160           nbBinaries++;
1161           nbSources++;
1162         }
1163       }
1164       nitem = (QCheckListItem*)( nitem->nextSibling() );
1165     }
1166
1167     if ( nbBinaries > 0 ) {
1168       QString binDir = "./Products/BINARIES";
1169       if ( !myOS.isEmpty() )
1170         binDir += "/" + myOS;
1171       QFileInfo fib( QDir::cleanDirPath( binDir ) );
1172       if ( !fib.exists() ) {
1173         if ( QMessageBox::warning( this, 
1174                                    tr( "Warning" ), 
1175                                    tr( "The directory %1 doesn't exist.\n"
1176                                        "This directory must contain binaries archives.\n"
1177                                        "Continue?" ).arg( fib.absFilePath() ),
1178                                    QMessageBox::Yes,
1179                                    QMessageBox::No,
1180                                    QMessageBox::NoButton ) == QMessageBox::No )
1181           return false;
1182       }
1183     }
1184     if ( nbSources > 0 ) {
1185       QString srcDir = "./Products/SOURCES";
1186       QFileInfo fis( QDir::cleanDirPath( srcDir ) );
1187       if ( !fis.exists() ) {
1188         if ( QMessageBox::warning( this, 
1189                                    tr( "Warning" ), 
1190                                    tr( "The directory %1 doesn't exist.\n"
1191                                        "This directory must contain sources archives.\n"
1192                                        "Continue?" ).arg( fis.absFilePath() ),
1193                                    QMessageBox::Yes,
1194                                    QMessageBox::No,
1195                                    QMessageBox::NoButton ) == QMessageBox::No )
1196           return false;
1197       }
1198     }
1199     // run script that checks available disk space for installing of products    // returns 1 in case of error
1200     QString script = "./config_files/checkSize.sh '";
1201     script += fi.absFilePath();
1202     script += "' ";
1203     script += QString( "%1" ).arg( totSize );
1204     ___MESSAGE___( "script = " << script );
1205     if ( system( script ) ) {
1206       QMessageBox::critical( this, 
1207                              tr( "Out of space" ), 
1208                              tr( "There is no available disk space for installing of selected products" ), 
1209                              QMessageBox::Ok, 
1210                              QMessageBox::NoButton, 
1211                              QMessageBox::NoButton );
1212       return false;
1213     }
1214     // check temp directory
1215     if ( tempDir.isEmpty() ) {
1216       if ( moreMode ) {
1217         QMessageBox::warning( this, 
1218                               tr( "Warning" ), 
1219                               tr( "Please, enter valid temporary directory path" ), 
1220                               QMessageBox::Ok, 
1221                               QMessageBox::NoButton,
1222                               QMessageBox::NoButton );
1223         return false; 
1224       }
1225       else {
1226         tempDir = "/tmp";
1227         tempFolder->setText( tempDir );
1228       }
1229     }
1230     QFileInfo fit( QDir::cleanDirPath( tempDir ) );
1231     if ( !makeDir( fit.absFilePath() + TEMPDIRNAME, tmpCreated ) ) {
1232       QMessageBox::critical( this, 
1233                              tr( "Error" ), 
1234                              tr( "Can't use temporary directory.\nCheck permissions for the %1 directory.").arg( fit.absFilePath() ), 
1235                              QMessageBox::Ok, 
1236                              QMessageBox::NoButton, 
1237                              QMessageBox::NoButton );
1238       return false;
1239     }
1240     // run script that check available disk space for temporary files
1241     // returns 1 in case of error
1242     QString tscript = "./config_files/checkSize.sh '";
1243     tscript += fit.absFilePath();
1244     tscript += "' ";
1245     tscript += QString( "%1" ).arg( tempSize );
1246     ___MESSAGE___( "script = " << tscript );
1247     if ( system( tscript ) ) {
1248       QMessageBox::critical( this, 
1249                              tr( "Out of space" ), 
1250                              tr( "There is no available disk space for the temporary files" ), 
1251                              QMessageBox::Ok, 
1252                              QMessageBox::NoButton, 
1253                              QMessageBox::NoButton );
1254       return false;
1255     }
1256 // VSR: <------------------------------------------------------------------------------
1257     // ########## check native products
1258     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1259     QStringList natives;
1260     while( item ) {
1261       if ( productsMap.contains( item ) ) {
1262         if ( item->childCount() > 0 ) {
1263           // VSR : 29/01/05 : Check installation script even if product is not being installed
1264           //      if ( !productsView->isNone( item ) ) {
1265             if ( item->text(2).isEmpty() || item->text(2).isNull() ) {
1266               QMessageBox::warning( this, 
1267                                     tr( "Error" ), 
1268                                     tr( "The installation script for %1 is not defined.").arg(item->text(0)), 
1269                                     QMessageBox::Ok, 
1270                                     QMessageBox::NoButton, 
1271                                     QMessageBox::NoButton );
1272               if ( !moreMode )
1273                 onMoreBtn();
1274               productsView->setCurrentItem( item );
1275               productsView->setSelected( item, true );
1276               productsView->ensureItemVisible( item );
1277               //productsView->setNone( item );
1278               return false;
1279             } else {
1280               QFileInfo fi( QString("./config_files/") + item->text(2) );
1281               if ( !fi.exists() || !fi.isExecutable() ) {
1282                 QMessageBox::warning( this, 
1283                                       tr( "Error" ),  
1284                                       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)),  
1285                                       QMessageBox::Ok, 
1286                                       QMessageBox::NoButton, 
1287                                       QMessageBox::NoButton );
1288                 if ( !moreMode )
1289                   onMoreBtn();
1290                 productsView->setCurrentItem( item );
1291                 productsView->setSelected( item, true );
1292                 productsView->ensureItemVisible( item );
1293                 //productsView->setNone( item );
1294                 return false;
1295               }       
1296             }
1297             //    }
1298           // collect native products
1299           if ( productsView->isNative( item ) ) {
1300             if ( natives.find( item->text(0) ) == natives.end() )
1301               natives.append( item->text(0) );
1302           } 
1303           else if ( productsView->isBinaries( item ) || productsView->isSources( item ) ) {
1304             QStringList dependOn = productsMap[ item ].getDependancies();
1305             for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1306               QCheckListItem* depitem = findItem( dependOn[ i ] );
1307               if ( depitem ) {
1308                 if ( productsView->isNative( depitem ) && natives.find( depitem->text(0) ) == natives.end() )
1309                   natives.append( depitem->text(0) );
1310               } 
1311               else {
1312                 QMessageBox::warning( this, 
1313                                       tr( "Error" ), 
1314                                       tr( "%1 is required for %2 %3 installation.\n"
1315                                           "This product is missing in the configuration file %4.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)).arg(xmlFileName), 
1316                                       QMessageBox::Ok, 
1317                                       QMessageBox::NoButton, 
1318                                       QMessageBox::NoButton );
1319                 return false;
1320               }
1321             }
1322           }
1323         }
1324       }
1325       item = (QCheckListItem*)( item->nextSibling() );
1326     }
1327     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1328     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1329     myThread->clearCommands();
1330     if ( natives.count() > 0 ) {
1331       for ( unsigned i = 0; i < natives.count(); i++ ) {
1332         item = findItem( natives[ i ] );
1333         if ( item ) {
1334           QString dependOn = productsMap[ item ].getDependancies().join(" ");
1335           QString script = "cd ./config_files/;" + item->text(2) + " try_native " +
1336                   QFileInfo( tmpFolder ).absFilePath() + " " + QDir::currentDirPath() + "/Products " + QFileInfo( tgtFolder ).absFilePath() + " " +
1337                   QUOTE(dependOn) + " " + item->text(0);
1338
1339           myThread->addCommand( item, script );
1340         }
1341         else {
1342           QMessageBox::warning( this, 
1343                                 tr( "Warning" ), 
1344                                 tr( "%The product %1 %2 required for installation.\n"
1345                                     "This product is missing in the configuration file %4.").arg(item->text(0)).arg(item->text(1)).arg(xmlFileName),
1346                                 QMessageBox::Ok, 
1347                                 QMessageBox::NoButton, 
1348                                 QMessageBox::NoButton );
1349           return false;
1350         }
1351       }
1352       WarnDialog::showWarnDlg( this, true );
1353       myThread->start();
1354       return true; // return in order to avoid default postValidateEvent() action
1355     }
1356   }
1357   return InstallWizard::acceptData( pageTitle );
1358 }
1359 // ================================================================
1360 /*!
1361  *  SALOME_InstallWizard::checkSize
1362  *  Calculates disk space required for the installation
1363  */
1364 // ================================================================
1365 bool SALOME_InstallWizard::checkSize( long* totSize, long* tempSize )
1366 {
1367   long tots = 0, temps = 0;
1368   int nbSelected = 0;
1369
1370   MapProducts::Iterator mapIter;
1371   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1372     QCheckListItem* item = mapIter.key();
1373     Dependancies dep = mapIter.data();
1374     if ( productsView->isBinaries( item ) ) {
1375       tots += dep.getSize();
1376     }
1377     else if ( productsView->isSources( item ) ) {
1378       tots += dep.getSize(true);
1379       temps = max( temps, dep.getTempSize() );
1380     }
1381     if ( !productsView->isNone( item ) )
1382       nbSelected++;
1383   }
1384  
1385   if ( totSize )
1386     *totSize = tots;
1387   if ( tempSize )
1388     *tempSize = temps;
1389   return ( nbSelected > 0 );
1390 }
1391 // ================================================================
1392 /*!
1393  *  SALOME_InstallWizard::checkProductPage
1394  *  Checks products page validity (directories and products selection) and
1395  *  enabled/disables "Next" button for the Products page
1396  */
1397 // ================================================================
1398 void SALOME_InstallWizard::checkProductPage()
1399 {
1400   long tots = 0, temps = 0;
1401
1402   // check if any product is selected;
1403   bool isAnyProductSelected = checkSize( &tots, &temps );
1404   // check if target directory is valid
1405   bool isTargetDirValid = !targetFolder->text().stripWhiteSpace().isEmpty();
1406   // check if temp directory is valid
1407   bool isTempDirValid = !moreMode || !tempFolder->text().stripWhiteSpace().isEmpty();
1408
1409   // update required size information
1410   requiredSize->setText( QString::number( tots )  + " Kb");
1411   requiredTemp->setText( QString::number( temps ) + " Kb");
1412   
1413   // update <SALOME sources>, <SALOME binaries> check boxes state
1414   int totSrc = 0, selSrc = 0;
1415   int totBin = 0, selBin = 0;
1416   MapProducts::Iterator itProd;
1417   for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1418     bool srcctx = itProd.data().hasContext( "salome sources" );
1419     bool binctx = itProd.data().hasContext( "salome binaries" );
1420     if ( srcctx && !binctx ) {
1421       totSrc++;
1422       if ( productsView->isSources( itProd.key() ) )
1423         selSrc++;
1424     }
1425     if ( binctx && !srcctx ) {
1426       totBin++;
1427       if ( productsView->isBinaries( itProd.key() ) )
1428         selBin++;
1429     }
1430   }
1431   selectSrcBtn->blockSignals( true );
1432   selectBinBtn->blockSignals( true );
1433   selectSrcBtn->setState( selSrc == 0 ? QButton::Off : ( selSrc == totSrc ? QButton::On : QButton::NoChange  ) );
1434   selectBinBtn->setState( selBin == 0 ? QButton::Off : ( selBin == totBin ? QButton::On : QButton::NoChange  ) );
1435   selectSrcBtn->blockSignals( false );
1436   selectBinBtn->blockSignals( false );
1437
1438   // enable/disable "Next" button
1439   setNextEnabled( productsPage, isAnyProductSelected && isTargetDirValid && isTempDirValid );
1440 }
1441 // ================================================================
1442 /*!
1443  *  SALOME_InstallWizard::setPrerequisites
1444  *  Sets the product and all products this one depends on to be checked ( recursively )
1445  */
1446 // ================================================================
1447 void SALOME_InstallWizard::setPrerequisites( QCheckListItem* item )
1448 {
1449   if ( !productsMap.contains( item ) )
1450     return;
1451   if ( productsView->isNone( item ) )
1452     return;
1453   // get all prerequisites
1454   QStringList dependOn = productsMap[ item ].getDependancies();
1455   for ( int i = 0; i < (int)dependOn.count(); i++ ) {
1456     MapProducts::Iterator itProd;
1457     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
1458       if ( itProd.data().getName() == dependOn[ i ] ) {
1459         if ( productsView->isNone( itProd.key() ) ) {
1460           QString defMode = itProd.data().getDefault();
1461           if ( defMode.isEmpty() )
1462             defMode = tr( "install binaries" );
1463           if ( defMode == tr( "install binaries" ) )
1464             productsView->setBinaries( itProd.key() );
1465           else if ( defMode == tr( "install sources" ) )
1466             productsView->setSources( itProd.key() );
1467           else if ( defMode == tr( "use native" ) )
1468             productsView->setNative( itProd.key() );
1469           setPrerequisites( itProd.key() );
1470         }
1471       }
1472     }
1473   }
1474 }
1475 // ================================================================
1476 /*!
1477  *  SALOME_InstallWizard::launchScript
1478  *  Runs installation script
1479  */
1480 // ================================================================
1481 void SALOME_InstallWizard::launchScript()
1482 {
1483   // try to find product being processed now
1484   QString prodProc = progressView->findStatus( Processing );
1485   if ( !prodProc.isNull() ) {
1486     ___MESSAGE___( "Found <Processing>: " );
1487
1488     // if found - set status to "completed"
1489     progressView->setStatus( prodProc, Completed );
1490     // ... and call this method again
1491     launchScript();
1492     return;
1493   }
1494   // else try to find next product which is not processed yet
1495   prodProc = progressView->findStatus( Waiting );
1496   if ( !prodProc.isNull() ) {
1497     ___MESSAGE___( "Found <Waiting>: " << prodProc.latin1() );
1498     // if found - set status to "processed" and run script
1499     progressView->setStatus( prodProc, Processing );
1500     progressView->ensureVisible( prodProc );
1501
1502     QCheckListItem* item = findItem( prodProc );
1503     // fill in script parameters
1504     shellProcess->clearArguments();
1505     // ... script name
1506     shellProcess->setWorkingDirectory( QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() ) );
1507     shellProcess->addArgument( item->text(2) );
1508
1509     // ... temp folder
1510     QString tmpFolder = QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1511     //if( !tempFolder->isEnabled() )
1512     //tmpFolder = "/tmp";
1513
1514     // ... binaries ?
1515     if ( productsView->isBinaries( item ) ) {
1516       shellProcess->addArgument( "install_binary" );
1517       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1518       QString binDir = QDir::currentDirPath() + "/Products/BINARIES";
1519       if ( !myOS.isEmpty() )
1520         binDir += "/" + myOS;
1521       shellProcess->addArgument( binDir );
1522     }
1523     // ... sources ?
1524     else if ( productsView->isSources( item ) ) {
1525       shellProcess->addArgument( "install_source" );
1526       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1527       shellProcess->addArgument( QDir::currentDirPath() + "/Products/SOURCES" );
1528     }
1529     // ... native ?
1530     else if ( productsView->isNative( item ) ) {
1531       shellProcess->addArgument( "try_native" );
1532       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1533       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1534     }
1535     // ... not install : try to find preinstalled
1536     else {
1537       shellProcess->addArgument( "try_preinstalled" );
1538       shellProcess->addArgument( QFileInfo( tmpFolder ).absFilePath() );
1539       shellProcess->addArgument( QDir::currentDirPath() + "/Products" );
1540     }
1541     // ... target folder
1542     QString tgtFolder = QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() );
1543     shellProcess->addArgument( QFileInfo( tgtFolder ).absFilePath() );
1544     
1545
1546     QString depproducts = DefineDependeces(productsMap); 
1547     ___MESSAGE___( "Dependancies"<< depproducts.latin1() );
1548
1549     shellProcess->addArgument( depproducts );
1550     // ... product name - currently instaled product
1551     shellProcess->addArgument( item->text(0) );
1552
1553     // run script
1554     if ( !shellProcess->start() ) {
1555       // error handling can be here
1556       ___MESSAGE___( "error" );
1557     }
1558     return;
1559   }
1560   ___MESSAGE___( "All products have been installed successfully" );
1561   // all products are installed successfully
1562   QString workDir = QDir::cleanDirPath( QFileInfo( "./config_files/" ).absFilePath() );
1563   MapProducts::Iterator mapIter;
1564   ___MESSAGE___( "starting pick-up environment" );
1565   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1566     QCheckListItem* item = mapIter.key();
1567     Dependancies dep = mapIter.data();
1568     QString depproducts = QUOTE( DefineDependeces(productsMap) ); 
1569     if ( !productsView->isNone( item ) && dep.pickUpEnvironment() ) {
1570       ___MESSAGE___( "... for " << dep.getName() );
1571       QString script;
1572       script += "cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
1573       script += item->text(2) + " ";
1574       script += "pickup_env ";
1575       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
1576       script += QUOTE( QFileInfo( QDir::cleanDirPath( QDir::currentDirPath() + "/Products" ) ).absFilePath() ) + " ";
1577       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
1578       script += depproducts + " ";
1579       script += item->text(0);
1580       ___MESSAGE___( "... --> " << script.latin1() );
1581       if ( system( script.latin1() ) ) { 
1582         ___MESSAGE___( "ERROR" ); 
1583       }
1584     }
1585   }
1586   // <Next> button
1587   setNextEnabled( true );
1588   nextButton()->setText( tr( "&Next >" ) );
1589   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1590   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1591   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1592   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1593   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1594   // <Back> button
1595   setBackEnabled( true );
1596   // script parameters
1597   passedParams->clear();
1598   passedParams->setEnabled( false );
1599   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1600   installInfo->setFinished( true );
1601   if ( isMinimized() )
1602     showNormal();
1603   raise();
1604 }
1605 // ================================================================
1606 /*!
1607  *  SALOME_InstallWizard::onMoreBtn
1608  *  <More...> button slot
1609  */
1610 // ================================================================
1611 void SALOME_InstallWizard::onMoreBtn()
1612 {
1613   if ( moreMode ) {
1614     moreBox->hide();
1615     moreBtn->setText( tr( "More..." ) );
1616   }
1617   else {
1618     moreBox->show();
1619     moreBtn->setText( tr( "Less..." ) );
1620   }
1621   qApp->processEvents();
1622   moreMode = !moreMode;
1623   InstallWizard::layOut();
1624   qApp->processEvents();
1625   if ( !isMaximized() ) {
1626     //setGeometry( geometry().x(), geometry().y(), geometry().width(), 0 );
1627     resize( geometry().width(), 0 );
1628     qApp->processEvents();
1629   }
1630   checkProductPage();
1631 }
1632 // ================================================================
1633 /*!
1634  *  SALOME_InstallWizard::onFinishButton
1635  *  Operation buttons slot
1636  */
1637 // ================================================================
1638 void SALOME_InstallWizard::onFinishButton()
1639 {
1640   const QObject* btn = sender();
1641   ButtonList::Iterator it;
1642   for ( it = buttons.begin(); it != buttons.end(); ++it ) {
1643     if ( (*it).button() && (*it).button() == btn ) {
1644       QString script;
1645       script += "( cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
1646       script +=  + (*it).script();
1647       script += " execute ";
1648       script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
1649       script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
1650       script += " > /dev/null )";
1651       ___MESSAGE___( "script: " << script.latin1() );
1652       if ( (*it).script().isEmpty() || system( script.latin1() ) ) {
1653         QMessageBox::warning( this, 
1654                               tr( "Error" ), 
1655                               tr( "Can't perform action!"),
1656                               QMessageBox::Ok, 
1657                               QMessageBox::NoButton,
1658                               QMessageBox::NoButton );
1659       }
1660       return;
1661     }
1662   }
1663 }
1664 // ================================================================
1665 /*!
1666  *  SALOME_InstallWizard::onAbout
1667  *  <About> button slot: shows <About> dialog box
1668  */
1669 // ================================================================
1670 void SALOME_InstallWizard::onAbout()
1671 {
1672   AboutDlg d( this );
1673   d.exec();
1674 }
1675
1676 // ================================================================
1677 /*!
1678  *  SALOME_InstallWizard::findItem
1679  *  Searches product listview item with given symbolic name 
1680  */
1681 // ================================================================
1682 QCheckListItem* SALOME_InstallWizard::findItem( const QString& sName )
1683 {
1684   MapProducts::Iterator mapIter;
1685   for ( mapIter = productsMap.begin(); mapIter != productsMap.end(); ++mapIter ) {
1686     if ( mapIter.data().getName() == sName )
1687       return mapIter.key();
1688   }
1689   return 0;
1690 }
1691 // ================================================================
1692 /*!
1693  *  SALOME_InstallWizard::abort
1694  *  Sets progress state to Aborted
1695  */
1696 // ================================================================
1697 void SALOME_InstallWizard::abort()
1698 {
1699   QString prod = progressView->findStatus( Processing );
1700   while ( !prod.isNull() ) {
1701     progressView->setStatus( prod, Aborted );
1702     prod = progressView->findStatus( Processing );
1703   }
1704   prod = progressView->findStatus( Waiting );
1705   while ( !prod.isNull() ) {
1706     progressView->setStatus( prod, Aborted );
1707     prod = progressView->findStatus( Waiting );
1708   }
1709 }
1710 // ================================================================
1711 /*!
1712  *  SALOME_InstallWizard::reject
1713  *  Reject slot, clears temporary directory and closes application
1714  */
1715 // ================================================================
1716 void SALOME_InstallWizard::reject()
1717 {
1718   ___MESSAGE___( "REJECTED" );
1719   if ( !exitConfirmed ) {
1720     if ( QMessageBox::information( this, 
1721                                    tr( "Exit" ), 
1722                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
1723                                    tr( "&Yes" ), 
1724                                    tr( "&No" ),
1725                                    QString::null,
1726                                    0,
1727                                    1 ) == 1 ) {
1728       return;
1729     }
1730     exitConfirmed = true;
1731   }
1732   clean(true);
1733   InstallWizard::reject();
1734 }
1735 // ================================================================
1736 /*!
1737  *  SALOME_InstallWizard::accept
1738  *  Accept slot, clears temporary directory and closes application
1739  */
1740 // ================================================================
1741 void SALOME_InstallWizard::accept()
1742 {
1743   ___MESSAGE___( "ACCEPTED" );
1744   clean(true);
1745   InstallWizard::accept();
1746 }
1747 // ================================================================
1748 /*!
1749  *  SALOME_InstallWizard::clean
1750  *  Clears and (optionally) removes temporary directory
1751  */
1752 // ================================================================
1753 void SALOME_InstallWizard::clean(bool rmDir)
1754 {
1755   WarnDialog::showWarnDlg( 0, false );
1756   myThread->clearCommands();
1757   myWC.wakeAll();
1758   while ( myThread->running() );
1759   // VSR: first remove temporary files
1760   QString script = "cd ./config_files/; remove_tmp.sh '";
1761   script += tempFolder->text().stripWhiteSpace() + TEMPDIRNAME;
1762   script += "' ";
1763   script += QUOTE(DefineDependeces(productsMap));
1764   script += " > /dev/null";
1765   ___MESSAGE___( "script = " << script );
1766   if ( system( script.latin1() ) ) {
1767   }
1768   // VSR: then try to remove created temporary directory
1769   //script = "rm -rf " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME;
1770   if ( rmDir && !tmpCreated.isNull() ) {
1771     script = "rm -rf " + tmpCreated;
1772     script += " > /dev/null";
1773     if ( system( script.latin1() ) ) {
1774     }
1775     ___MESSAGE___( "script = " << script );
1776   }
1777 }
1778 // ================================================================
1779 /*!
1780  *  SALOME_InstallWizard::pageChanged
1781  *  Called when user moves from page to page
1782  */
1783 // ================================================================
1784 void SALOME_InstallWizard::pageChanged( const QString & mytitle)
1785 {
1786   nextButton()->setText( tr( "&Next >" ) );
1787   QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1788   QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
1789   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1790   disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1791   connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1792   cancelButton()->disconnect();
1793   connect( cancelButton(), SIGNAL( clicked()), this, SLOT( reject() ) );
1794
1795   QWidget* aPage = InstallWizard::page( mytitle );
1796   if ( !aPage )
1797     return;
1798   updateCaption();
1799   if ( aPage == productsPage ) {
1800     // products page
1801     onSelectionChanged();
1802     checkProductPage();
1803   }
1804   else if ( aPage == prestartPage ) {
1805     // prestart page
1806     showChoiceInfo();
1807   }
1808   else if ( aPage == progressPage ) {
1809     if ( previousPage == prestartPage ) {
1810       // progress page
1811       progressView->clear();
1812       installInfo->clear();
1813       installInfo->setFinished( false );
1814       passedParams->clear();
1815       passedParams->setEnabled( false );
1816       QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1817       nextButton()->setText( tr( "&Start" ) );
1818       QWhatsThis::add( nextButton(), tr( "Starts installation process" ) );
1819       QToolTip::add  ( nextButton(), tr( "Starts installation process" ) );
1820       // reconnect Next button - to use it as Start button
1821       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
1822       disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1823       connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
1824       setNextEnabled( true );
1825       // reconnect Cancel button to terminate process
1826       cancelButton()->disconnect();
1827       connect( cancelButton(), SIGNAL( clicked() ), this, SLOT( tryTerminate() ) );
1828     }
1829   }
1830   else if ( aPage == readmePage ) {
1831     ButtonList::Iterator it;
1832     for ( it = buttons.begin(); it != buttons.end(); ++it ) {
1833       if ( (*it).button() ) {
1834         QString script;
1835         script += "( cd " + QUOTE( QFileInfo( QDir::cleanDirPath( "./config_files/" ) ).absFilePath() ) + "; ";
1836         script +=  + (*it).script();
1837         script += " check_enabled ";
1838         script += QUOTE( QFileInfo( QDir::cleanDirPath( targetFolder->text().stripWhiteSpace() ) ).absFilePath() ) + " ";
1839         script += QUOTE( QFileInfo( QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + TEMPDIRNAME ).absFilePath() ) + " ";
1840         script += " > /dev/null )";
1841         ___MESSAGE___( "script: " << script.latin1() );
1842         (*it).button()->setEnabled( !(*it).script().isEmpty() && !system( script.latin1() ) );
1843       }
1844     }
1845     finishButton()->setEnabled( true );
1846   }
1847   previousPage = aPage;
1848   ___MESSAGE___( "previousPage = " << previousPage );
1849 }
1850 // ================================================================
1851 /*!
1852  *  SALOME_InstallWizard::helpClicked
1853  *  Shows help window
1854  */
1855 // ================================================================
1856 void SALOME_InstallWizard::helpClicked()
1857 {
1858   if ( helpWindow == NULL ) {
1859     helpWindow = HelpWindow::openHelp( this );
1860     if ( helpWindow ) {
1861       helpWindow->show();
1862       helpWindow->installEventFilter( this );
1863     }
1864     else {
1865       QMessageBox::warning( this, 
1866                             tr( "Help file not found" ), 
1867                             tr( "Sorry, help is unavailable" ) );
1868     }
1869   }
1870   else {
1871     helpWindow->raise();
1872     helpWindow->setActiveWindow();
1873   }
1874 }
1875 // ================================================================
1876 /*!
1877  *  SALOME_InstallWizard::browseDirectory
1878  *  Shows directory selection dialog
1879  */
1880 // ================================================================
1881 void SALOME_InstallWizard::browseDirectory()
1882 {
1883   const QObject* theSender = sender();
1884   QLineEdit* theFolder;
1885   if ( theSender == targetBtn )
1886     theFolder = targetFolder;
1887   else if (theSender == tempBtn)
1888     theFolder = tempFolder;
1889   else
1890     return;
1891   QString typedDir = QFileDialog::getExistingDirectory( QDir::cleanDirPath( theFolder->text().stripWhiteSpace() ), this );
1892   if ( !typedDir.isNull() ) {
1893     theFolder->setText( typedDir );
1894     theFolder->end( false );
1895   }
1896   checkProductPage();
1897 }
1898 // ================================================================
1899 /*!
1900  *  SALOME_InstallWizard::directoryChanged
1901  *  Called when directory path (target or temp) is changed
1902  */
1903 // ================================================================
1904 void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ )
1905 {
1906   checkProductPage();
1907 }
1908 // ================================================================
1909 /*!
1910  *  SALOME_InstallWizard::onStart
1911  *  <Start> button's slot - runs installation
1912  */
1913 // ================================================================
1914 void SALOME_InstallWizard::onStart()
1915 {
1916   if ( nextButton()->text() == tr( "&Stop" ) ) {
1917     shellProcess->kill();
1918     while( shellProcess->isRunning() );
1919     return;
1920   }
1921   progressView->clear();
1922   installInfo->clear();
1923   installInfo->setFinished( false );
1924   passedParams->clear();
1925   passedParams->setEnabled( false );
1926   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1927   // clear list of products to install ...
1928   toInstall.clear();
1929   // ... and fill it for new process
1930   QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
1931   while( item ) {
1932 //    if ( productsView->isBinaries( item ) || productsView->isSources( item ) || productsView->isNative( item ) ) {
1933       if ( productsMap.contains( item ) )
1934         toInstall.append( productsMap[item].getName() );
1935 //    }
1936     item = (QCheckListItem*)( item->nextSibling() );
1937   }
1938   // if something at all is selected
1939   if ( !toInstall.isEmpty() ) {
1940     clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory
1941     // disable <Next> button
1942     //setNextEnabled( false );
1943     nextButton()->setText( tr( "&Stop" ) );
1944     QWhatsThis::add( nextButton(), tr( "Aborts installation process" ) );
1945     QToolTip::add  ( nextButton(), tr( "Aborts installation process" ) );
1946     // disable <Back> button
1947     setBackEnabled( false );
1948     // enable script parameters line edit
1949     // VSR commented: 18/09/03: passedParams->setEnabled( true );
1950     // VSR commented: 18/09/03: passedParams->setFocus();
1951     // set status for all products
1952     for ( int i = 0; i < (int)toInstall.count(); i++ ) {
1953       item = findItem( toInstall[ i ] );
1954       QString type = "";
1955       if ( productsView->isBinaries( item ) )
1956         type = tr( "binaries" );
1957       else if ( productsView->isSources( item ) )
1958         type = tr( "sources" );
1959       else if ( productsView->isNative( item ) )
1960         type = tr( "native" );
1961       else 
1962         type = tr( "not install" );
1963       progressView->addProduct( item->text(0), type, item->text(2) );
1964     }
1965     // launch install script
1966     launchScript();
1967   }
1968 }
1969 // ================================================================
1970 /*!
1971  *  SALOME_InstallWizard::onReturnPressed
1972  *  Called when users tries to pass parameters for the script
1973  */
1974 // ================================================================
1975 void SALOME_InstallWizard::onReturnPressed()
1976 {
1977   QString txt = passedParams->text();
1978   installInfo->append( txt );
1979   txt += "\n";
1980   shellProcess->writeToStdin( txt );
1981   passedParams->clear();
1982   progressView->setFocus();
1983   passedParams->setEnabled( false );
1984   QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
1985 }
1986 /*!
1987   Callback function - as response for the script finishing
1988 */
1989 void SALOME_InstallWizard::productInstalled( )
1990 {
1991   ___MESSAGE___( "process exited" );
1992   if ( shellProcess->normalExit() ) {
1993     ___MESSAGE___( "...normal exit" );
1994     // normal exit - try to proceed installation further
1995     launchScript();
1996   }
1997   else {
1998     ___MESSAGE___( "...abnormal exit" );
1999     // installation aborted
2000     abort();
2001     // clear script passed parameters lineedit
2002     passedParams->clear();
2003     passedParams->setEnabled( false );
2004     QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f );
2005     installInfo->setFinished( true );
2006     // enable <Next> button
2007     setNextEnabled( true );
2008     nextButton()->setText( tr( "&Start" ) );
2009     QWhatsThis::add( nextButton(), tr( "Starts installation process" ) );
2010     QToolTip::add  ( nextButton(), tr( "Starts installation process" ) );
2011     // reconnect Next button - to use it as Start button
2012     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2013     disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2014     connect(    this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2015     //nextButton()->setText( tr( "&Next >" ) );
2016     //QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
2017     //QToolTip::add  ( nextButton(), tr( "Moves to the next step of the installation procedure" ) );
2018     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2019     //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) );
2020     //connect(    this, SIGNAL( nextClicked() ), this, SLOT( next() ) );
2021     // enable <Back> button
2022     setBackEnabled( true );
2023   }
2024 }
2025 // ================================================================
2026 /*!
2027  *  SALOME_InstallWizard::tryTerminate
2028  *  Slot, called when <Cancel> button is clicked during installation script running
2029  */
2030 // ================================================================
2031 void SALOME_InstallWizard::tryTerminate()
2032 {
2033   if ( shellProcess->isRunning() ) {
2034     if ( QMessageBox::information( this, 
2035                                    tr( "Exit" ), 
2036                                    tr( "Do you want to quit %1?" ).arg( getIWName() ), 
2037                                    tr( "&Yes" ), 
2038                                    tr( "&No" ),
2039                                    QString::null,
2040                                    0,
2041                                    1 ) == 1 ) {
2042       return;
2043     }
2044     exitConfirmed = true;
2045     // if process still running try to terminate it first
2046     shellProcess->tryTerminate();
2047     abort();
2048     //QTimer::singleShot( 3000, this, SLOT( onCancel() ) );
2049     connect( shellProcess, SIGNAL( processExited() ), this, SLOT( onCancel() ) );
2050   }
2051   else {
2052     // else just quit install wizard
2053     reject();
2054   }
2055 }
2056 // ================================================================
2057 /*!
2058  *  SALOME_InstallWizard::onCancel
2059  *  Kills installation process and quits application
2060  */
2061 // ================================================================
2062 void SALOME_InstallWizard::onCancel()
2063 {
2064   shellProcess->kill();
2065   reject();
2066 }
2067 // ================================================================
2068 /*!
2069  *  SALOME_InstallWizard::onSelectionChanged
2070  *  Called when selection is changed in the products list view
2071  */
2072 // ================================================================
2073 void SALOME_InstallWizard::onSelectionChanged()
2074 {
2075   productsInfo->clear();
2076   QListViewItem* item = productsView->selectedItem();
2077   if ( !item )
2078     return;
2079   if ( item->parent() )
2080     item = item->parent();
2081   QCheckListItem* aItem = (QCheckListItem*)item;
2082   if ( !productsMap.contains( aItem ) )
2083     return;
2084   Dependancies dep = productsMap[ aItem ];
2085   QString text = "<b>" + aItem->text(0) + "</b>" + "<br>";
2086   if ( !aItem->text(1).stripWhiteSpace().isEmpty() )
2087     text += tr( "Version" ) + ": " + aItem->text(1) + "<br>";
2088   text += "<br>";
2089   if ( !dep.getDescription().isEmpty() ) {
2090     text += "<i>" + dep.getDescription() + "</i><br><br>";
2091   }
2092   text += tr( "User choice" ) + ": ";
2093   long totSize = 0, tempSize = 0;
2094   if ( productsView->isBinaries( aItem ) ) {
2095     text += "<b>" + tr( "install binaries" ) + "</b>" + "<br>";
2096     totSize = dep.getSize();
2097   }
2098   else if ( productsView->isSources( aItem ) ) {
2099     text += "<b>" + tr( "install sources" ) + "</b>" + "<br>";
2100     totSize = dep.getSize( true );
2101     tempSize = dep.getTempSize();
2102   }
2103   else if ( productsView->isNative( aItem ) ) {
2104     text += "<b>" + tr( "use native" ) + "</b>" + "<br>";
2105   }
2106   else {
2107     text += "<b>" + tr( "not install" ) + "</b>" + "<br>";
2108   }
2109   
2110   text += tr( "Disk space required" ) + ": " + QString::number( totSize ) + " Kb<br>";
2111   text += tr( "Disk space for tmp files required" ) + ": " + QString::number( tempSize ) + " Kb<br>";
2112   text += "<br>";
2113   QString req = ( dep.getDependancies().count() > 0 ? dep.getDependancies().join(", ") : tr( "none" ) );
2114   text +=  tr( "Prerequisites" ) + ": " + req;
2115   productsInfo->setText( text );
2116 }
2117 // ================================================================
2118 /*!
2119  *  SALOME_InstallWizard::onItemToggled
2120  *  Called when user checks/unchecks any product item
2121  *  Recursively sets all prerequisites and updates "Next" button state
2122  */
2123 // ================================================================
2124 void SALOME_InstallWizard::onItemToggled( QCheckListItem* item )
2125 {
2126   if ( prerequisites->isChecked() ) {
2127     if ( item->parent() )
2128       item = (QCheckListItem*)( item->parent() );
2129     if ( productsMap.contains( item ) ) {
2130       productsView->blockSignals( true );
2131       setPrerequisites( item );
2132       productsView->blockSignals( false );
2133     }
2134   }
2135   onSelectionChanged();
2136   checkProductPage();
2137 }
2138 // ================================================================
2139 /*!
2140  *  SALOME_InstallWizard::onProdBtn
2141  *  This slot is called when user clicks one of <Select Sources>,
2142  *  <Select Binaries>, <Unselect All> buttons ( products page )
2143  */
2144 // ================================================================
2145 void SALOME_InstallWizard::onProdBtn()
2146 {
2147   const QObject* snd = sender();
2148   productsView->blockSignals( true );
2149   selectSrcBtn->blockSignals( true );
2150   selectBinBtn->blockSignals( true );
2151   if ( snd == unselectBtn ) {
2152     QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() );
2153     while( item ) {
2154       productsView->setNone( item );
2155       item = (QCheckListItem*)( item->nextSibling() );
2156     }
2157   }
2158   else if ( snd == selectSrcBtn )  {
2159     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
2160     if ( checkBox->state() == QButton::NoChange )
2161       checkBox->setState( QButton::On );
2162     MapProducts::Iterator itProd;
2163     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2164       if ( itProd.data().hasContext( "salome sources" ) ) {
2165         if ( checkBox->state() == QButton::Off ) {
2166           int selBin = 0;
2167           MapProducts::Iterator itProd1;
2168           for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
2169             if (  itProd1.data().hasContext( "salome binaries" ) && 
2170                  !itProd1.data().hasContext( "salome sources" ) &&
2171                   productsView->isBinaries( itProd1.key() ) )
2172               selBin++;
2173           }
2174           if ( !itProd.data().hasContext( "salome binaries" ) || !selBin )
2175             productsView->setNone( itProd.key() );
2176         }
2177         else {
2178           productsView->setSources( itProd.key() );
2179           if ( prerequisites->isChecked() )
2180             setPrerequisites( itProd.key() );
2181         }
2182       }
2183     }
2184   }
2185   else if ( snd == selectBinBtn )  {
2186     QMyCheckBox* checkBox = ( QMyCheckBox* )snd;
2187     if ( checkBox->state() == QButton::NoChange )
2188       checkBox->setState( QButton::On );
2189     MapProducts::Iterator itProd;
2190     for ( itProd = productsMap.begin(); itProd != productsMap.end(); ++itProd ) {
2191       if ( itProd.data().hasContext( "salome binaries" ) ) {
2192         if ( checkBox->state() == QButton::Off ) {
2193           int selSrc = 0;
2194           MapProducts::Iterator itProd1;
2195           for ( itProd1 = productsMap.begin(); itProd1 != productsMap.end(); ++itProd1 ) {
2196             if (  itProd1.data().hasContext( "salome sources" ) && 
2197                  !itProd1.data().hasContext( "salome binaries" ) &&
2198                   productsView->isSources( itProd1.key() ) )
2199               selSrc++;
2200           }
2201           if ( !itProd.data().hasContext( "salome sources" ) || !selSrc )
2202             productsView->setNone( itProd.key() );
2203         }
2204         else {
2205           productsView->setBinaries( itProd.key() );
2206           if ( prerequisites->isChecked() )
2207             setPrerequisites( itProd.key() );
2208         }
2209       }
2210     }
2211   }
2212   selectSrcBtn->blockSignals( false );
2213   selectBinBtn->blockSignals( false );
2214   productsView->blockSignals( false );
2215   onSelectionChanged();
2216   checkProductPage();
2217 }
2218 // ================================================================
2219 /*!
2220  *  SALOME_InstallWizard::wroteToStdin
2221  *  QProcess slot: -->something was written to stdin
2222  */
2223 // ================================================================
2224 void SALOME_InstallWizard::wroteToStdin( )
2225 {
2226   ___MESSAGE___( "Something was sent to stdin" );
2227 }
2228 // ================================================================
2229 /*!
2230  *  SALOME_InstallWizard::readFromStdout
2231  *  QProcess slot: -->something was written to stdout
2232  */
2233 // ================================================================
2234 void SALOME_InstallWizard::readFromStdout( )
2235 {
2236   ___MESSAGE___( "Something was sent to stdout" );
2237   while ( shellProcess->canReadLineStdout() ) {
2238     installInfo->append( QString( shellProcess->readLineStdout() ) );
2239     installInfo->scrollToBottom();
2240   }
2241   QString str( shellProcess->readStdout() );
2242   if ( !str.isEmpty() ) {
2243     installInfo->append( str );
2244     installInfo->scrollToBottom();
2245   }
2246 }
2247
2248 #define OUTLINE_TEXT(x) QString( "<font color=#FF0000><b>" ) + QString( x ) + QString( "</b></font>" )
2249
2250 // ================================================================
2251 /*!
2252  *  SALOME_InstallWizard::readFromStderr
2253  *  QProcess slot: -->something was written to stderr
2254  */
2255 // ================================================================
2256 void SALOME_InstallWizard::readFromStderr( )
2257 {
2258   ___MESSAGE___( "Something was sent to stderr" );
2259   while ( shellProcess->canReadLineStderr() ) {
2260     installInfo->append( OUTLINE_TEXT( QString( shellProcess->readLineStderr() ) ) );
2261     installInfo->scrollToBottom();
2262   }
2263   QString str( shellProcess->readStderr() );
2264   if ( !str.isEmpty() ) {
2265     installInfo->append( OUTLINE_TEXT( str ) );
2266     installInfo->scrollToBottom();
2267   }
2268   // VSR: 10/11/05 - disable answer mode ==>
2269   // passedParams->setEnabled( true );
2270   // passedParams->setFocus();
2271   // QFont f = parametersLab->font(); f.setBold( true ); parametersLab->setFont( f );
2272   // VSR: 10/11/05 - disable answer mode <==
2273 }
2274 // ================================================================
2275 /*!
2276  *  SALOME_InstallWizard::setDependancies
2277  *  Sets dependancies for the product item
2278  */
2279 // ================================================================
2280 void SALOME_InstallWizard::setDependancies( QCheckListItem* item, Dependancies dep)
2281 {
2282   productsMap[item] = dep;
2283 }
2284 // ================================================================
2285 /*!
2286  *  SALOME_InstallWizard::addFinishButton
2287  *  Add button for the <Finish> page
2288  */
2289 // ================================================================
2290 void SALOME_InstallWizard::addFinishButton( const QString& label, 
2291                                             const QString& tooltip, 
2292                                             const QString& script)
2293 {
2294   if ( !label.isEmpty() )
2295     buttons.append( Button( label, tooltip, script ) );
2296 }
2297 // ================================================================
2298 /*!
2299  *  SALOME_InstallWizard::polish
2300  *  Polishing of the widget - to set right initial size
2301  */
2302 // ================================================================
2303 void SALOME_InstallWizard::polish()
2304 {
2305   resize( 0, 0 );
2306   InstallWizard::polish();
2307 }
2308 // ================================================================
2309 /*!
2310  *  SALOME_InstallWizard::saveLog
2311  *  Save installation log to file
2312  */
2313 // ================================================================
2314 void SALOME_InstallWizard::saveLog()
2315 {
2316   QString txt = installInfo->text();
2317   if ( txt.length() <= 0 )
2318     return;
2319   QDateTime dt = QDateTime::currentDateTime();
2320   QString fileName = dt.toString("ddMMyy-hhmm");
2321   fileName.prepend("install-"); fileName.append(".html");
2322   fileName = QFileDialog::getSaveFileName( fileName,
2323                                            QString( "HTML files (*.htm *.html)" ),
2324                                            this, 0,
2325                                            tr( "Save Log file" ) );
2326   if ( !fileName.isEmpty() ) {
2327     QFile f( fileName );
2328     if ( f.open( IO_WriteOnly ) ) {
2329       QTextStream stream( &f );
2330       stream << txt;
2331       f.close();
2332     }
2333     else {
2334       QMessageBox::critical( this, 
2335                              tr( "Error" ), 
2336                              tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ), 
2337                              QMessageBox::Ok, 
2338                              QMessageBox::NoButton, 
2339                              QMessageBox::NoButton );
2340     }
2341   }
2342 }
2343 // ================================================================
2344 /*!
2345  *  SALOME_InstallWizard::updateCaption
2346  *  Updates caption according to the current page number
2347  */
2348 // ================================================================
2349 void SALOME_InstallWizard::updateCaption()
2350 {
2351   QWidget* aPage = InstallWizard::currentPage();
2352   if ( !aPage ) 
2353     return;
2354   InstallWizard::setCaption( tr( myCaption ) + " " +
2355                              tr( getIWName() ) + " - " +
2356                              tr( "Step %1 of %2").arg( QString::number( this->indexOf( aPage )+1 ) ).arg( QString::number( this->pageCount() ) ) );
2357 }
2358
2359 // ================================================================
2360 /*!
2361  *  SALOME_InstallWizard::processValidateEvent
2362  *  Processes validation event (<val> is validation code)
2363  */
2364 // ================================================================
2365 void SALOME_InstallWizard::processValidateEvent( const int val, void* data )
2366 {
2367   QWidget* aPage = InstallWizard::currentPage();
2368   if ( aPage != productsPage ) {
2369     InstallWizard::processValidateEvent( val, data );
2370     return;
2371   }
2372   myMutex.lock();
2373   myMutex.unlock();
2374   QCheckListItem* item = (QCheckListItem*)data;
2375   if ( val > 0 ) {
2376     if ( val == 2 ) {
2377       WarnDialog::showWarnDlg( 0, false );
2378       // when try_native returns 2 it means that native product version is higher than that is prerequisited
2379       if ( QMessageBox::warning( this, 
2380                                  tr( "Warning" ), 
2381                                  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)),
2382                                 QMessageBox::Yes, 
2383                                 QMessageBox::No, 
2384                                 QMessageBox::NoButton ) == QMessageBox::No ) {
2385         myThread->clearCommands();
2386         myWC.wakeAll();
2387         setNextEnabled( true );
2388         setBackEnabled( true );
2389         return;
2390       }
2391       WarnDialog::showWarnDlg( this, true );
2392     }
2393     else {
2394       WarnDialog::showWarnDlg( 0, false );
2395       bool binMode = productsView->hasBinaries( item );
2396       bool srcMode = productsView->hasSources( item );
2397       QStringList buttons;
2398       buttons.append( binMode ? tr( "Install binaries" ) : ( srcMode ? tr( "Install sources" ) : 
2399                                                                        tr( "Select manually" ) ) );
2400       buttons.append( binMode ? ( srcMode ? tr( "Install sources" ) : tr( "Select manually" ) ) :
2401                                 ( srcMode ? tr( "Select manually" ) : QString::null ) );
2402       buttons.append( binMode && srcMode ? tr( "Select manually" ) : QString::null );
2403       int answer = QMessageBox::warning( this, 
2404                                          tr( "Warning" ), 
2405                                          tr( "You don't have native %1 %2 on your computer.\nPlease, change your installation settings.").arg(item->text(0)).arg(item->text(1)), 
2406                                          buttons[0],
2407                                          buttons[1],
2408                                          buttons[2] );
2409       if ( buttons[ answer ] == tr( "Install binaries" ) )
2410         productsView->setBinaries( item );
2411       else if ( buttons[ answer ] == tr( "Install sources" ) )
2412         productsView->setSources( item );
2413       else {
2414         if ( !moreMode )
2415           onMoreBtn();
2416         productsView->setCurrentItem( item );
2417         productsView->setSelected( item, true );
2418         productsView->ensureItemVisible( item );
2419         myThread->clearCommands();
2420         myWC.wakeAll();
2421         setNextEnabled( true );
2422         setBackEnabled( true );
2423         return;
2424       }
2425       WarnDialog::showWarnDlg( this, true );
2426     }
2427   }
2428   if ( myThread->hasCommands() )
2429     myWC.wakeAll();
2430   else {
2431     WarnDialog::showWarnDlg( 0, false );
2432     InstallWizard::processValidateEvent( val, data );
2433   }
2434 }