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