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