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