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