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