From 896eed97e1d0ae195b9130de5bd056a1b5b08621 Mon Sep 17 00:00:00 2001 From: vsr Date: Thu, 29 Dec 2005 14:43:22 +0000 Subject: [PATCH] Bugs: - for qt-3.3.3 "Check native products" dialog box is not closed after check finiching - check existence and execute permissions for installation scripts (even for products which are not being installed) - compilation problems on Mandrake 10.1 Imps: - provide "Save installation log" operation - provide "Stop" button to stop/restart installation - use bash instead csh to launch SALOME (fix pb with long environment variables) --- src/SALOME_InstallWizard.cxx | 178 ++++++++++++++++++++++++++++------- src/SALOME_InstallWizard.hxx | 104 ++++++++++---------- src/globals.h | 3 +- 3 files changed, 198 insertions(+), 87 deletions(-) diff --git a/src/SALOME_InstallWizard.cxx b/src/SALOME_InstallWizard.cxx index f85b34b..b6c2aaf 100644 --- a/src/SALOME_InstallWizard.cxx +++ b/src/SALOME_InstallWizard.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #ifdef WNT #include @@ -56,17 +57,17 @@ QString tmpDirName() { return QString( "/INSTALLWORK" ) + QString::number( getp // ================================================================ /*! - * QProcessThread + * ProcessThread * Class for executing systen commands */ // ================================================================ static QMutex myMutex(false); static QWaitCondition myWC; -class QProcessThread: public QThread +class ProcessThread: public QThread { typedef QPtrList ItemList; public: - QProcessThread( SALOME_InstallWizard* iw ) : QThread(), myWizard( iw ) { myItems.setAutoDelete( false ); } + ProcessThread( SALOME_InstallWizard* iw ) : QThread(), myWizard( iw ) { myItems.setAutoDelete( false ); } void addCommand( QCheckListItem* item, const QString& cmd ) { myItems.append( item ); @@ -78,9 +79,9 @@ public: virtual void run() { while ( hasCommands() ) { - ___MESSAGE___( "QProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() ); + ___MESSAGE___( "ProcessThread::run - Processing command : " << myCommands[ 0 ].latin1() ); int result = system( myCommands[ 0 ] ) / 256; // return code is * 256 - ___MESSAGE___( "QProcessThread::run - Result : " << result ); + ___MESSAGE___( "ProcessThread::run - Result : " << result ); QCheckListItem* item = myItems.first(); myCommands.pop_front(); myItems.removeFirst(); @@ -124,8 +125,11 @@ class WarnDialog: public QDialog } void accept() { return; } void reject() { return; } - void closeEvent( QCloseEvent* e) { if ( !myCloseFlag ) return; QDialog::closeEvent( e ); } - + void closeEvent( QCloseEvent* e ) + { if ( !myCloseFlag ) return; + e->accept(); + QDialog::closeEvent( e ); + } ~WarnDialog() { myDlg = 0; } public: static void showWarnDlg( QWidget* parent, bool show ) { @@ -151,6 +155,48 @@ public: }; WarnDialog* WarnDialog::myDlg = 0; +// ================================================================ +/*! + * InstallInfo + * Installation progress info window class + */ +// ================================================================ +class InstallInfo : public QTextEdit +{ +public: + InstallInfo( QWidget* parent ) : QTextEdit( parent ), finished( false ) {} + void setFinished( const bool f ) { finished = f; } +protected: + QPopupMenu* createPopupMenu( const QPoint& ) + { + int para1, col1, para2, col2; + getSelection(¶1, &col1, ¶2, &col2); + bool allSelected = hasSelectedText() && + para1 == 0 && para2 == paragraphs()-1 && col1 == 0 && col2 == paragraphLength(para2); + QPopupMenu* popup = new QPopupMenu( this ); + int id = popup->insertItem( tr( "&Copy" ) ); + popup->setItemEnabled( id, hasSelectedText() ); + popup->connectItem ( id, this, SLOT( copy() ) ); + id = popup->insertItem( tr( "Select &All" ) ); + popup->setItemEnabled( id, (bool)text().length() && !allSelected ); + popup->connectItem ( id, this, SLOT( selectAll() ) ); + if ( finished ) { + QWidget* p = parentWidget(); + while ( p && !p->inherits( "SALOME_InstallWizard" ) ) + p = p->parentWidget(); + if ( p && p->inherits( "SALOME_InstallWizard" ) ) { + popup->insertSeparator(); + id = popup->insertItem( tr( "&Save Log" ) ); + popup->setItemEnabled( id, (bool)text().length() ); + popup->connectItem ( id, (SALOME_InstallWizard*)p, SLOT( saveLog() ) ); + } + } + return popup; + } +private: + bool finished; +}; + // ================================================================ /*! * DefineDependeces [ static ] @@ -368,7 +414,7 @@ SALOME_InstallWizard::SALOME_InstallWizard(QString aXmlFileName) connect(shellProcess, SIGNAL( wroteToStdin() ), this, SLOT( wroteToStdin() ) ); // create validation thread - myThread = new QProcessThread( this ); + myThread = new ProcessThread( this ); } // ================================================================ /*! @@ -687,7 +733,7 @@ void SALOME_InstallWizard::setupProgressPage() QGridLayout* layout = new QGridLayout( widget ); layout->setMargin( 0 ); layout->setSpacing( 6 ); // installation progress view box - installInfo = new QTextEdit( widget ); + installInfo = new InstallInfo( widget ); installInfo->setReadOnly( true ); installInfo->setTextFormat( RichText ); installInfo->setUndoRedoEnabled ( false ); @@ -797,16 +843,16 @@ void SALOME_InstallWizard::showChoiceInfo() text += "
"; } if ( !myOS.isEmpty() ) { - text += tr( "Target platform" ) + ": " + myOS + "
"; + text += tr( "Reference Linux platform" ) + ": " + myOS + "
"; text += "
"; } - text += tr( "Products to be used" ) + ":
    "; + text += tr( "Native products to be used" ) + ":
      "; QCheckListItem* item = (QCheckListItem*)( productsView->firstChild() ); while( item ) { if ( productsMap.contains( item ) ) { if ( item->childCount() > 0 ) { if ( productsView->isNative( item ) ) { - text += "
    • " + item->text() + " " + tr( "as native" ) + "
      "; + text += "
    • " + item->text() + "
      "; nbProd++; } } @@ -824,11 +870,11 @@ void SALOME_InstallWizard::showChoiceInfo() if ( productsMap.contains( item ) ) { if ( item->childCount() > 0 ) { if ( productsView->isBinaries( item ) ) { - text += "
    • " + item->text() + " " + tr( "as binaries" ) + "
      "; + text += "
    • " + item->text() + " " + item->text(1) + " " + tr( "as binaries" ) + "
      "; nbProd++; } else if ( productsView->isSources( item ) ) { - text+= "
    • " + item->text() + " " + tr( "as sources" ) + "
      "; + text+= "
    • " + item->text() + " " + item->text(1) + " " + tr( "as sources" ) + "
      "; nbProd++; } } @@ -850,7 +896,7 @@ void SALOME_InstallWizard::showChoiceInfo() // VSR: Temporary folder is used always now and it is not necessary to disable it --> // if ( tempSize > 0 ) // VSR: <---------------------------------------------------------------------------- - text += tr( "Temp directory:" ) + " " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "
      "; + text += tr( "Temporary directory:" ) + " " + QDir::cleanDirPath( tempFolder->text().stripWhiteSpace() ) + "
      "; text += "
      "; choices->setText( text ); } @@ -907,7 +953,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) QMessageBox::warning( this, tr( "Warning" ), tr( "The directory %1 doesn't exist.\n" - "Do you want to create directory?" ).arg( fi.absFilePath() ), + "Create directory?" ).arg( fi.absFilePath() ), QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton ) == QMessageBox::Yes; @@ -926,7 +972,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) if ( !fi.isDir() ) { QMessageBox::warning( this, tr( "Warning" ), - tr( "The directory %1 is not a directory.\n" + tr( "%1 is not a directory.\n" "Please, enter valid target directory path" ).arg( fi.absFilePath() ), QMessageBox::Ok, QMessageBox::NoButton, @@ -973,7 +1019,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) if ( system( script ) ) { QMessageBox::critical( this, tr( "Out of space" ), - tr( "There is not available disk space for installing of selected products" ), + tr( "There is no available disk space for installing of selected products" ), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -984,7 +1030,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) if ( moreMode ) { QMessageBox::warning( this, tr( "Warning" ), - tr( "Please, enter valid temp directory path" ), + tr( "Please, enter valid temporary directory path" ), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1015,7 +1061,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) if ( system( tscript ) ) { QMessageBox::critical( this, tr( "Out of space" ), - tr( "There is not available disk space for the temporary files" ), + tr( "There is no available disk space for the temporary files" ), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1028,11 +1074,12 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) while( item ) { if ( productsMap.contains( item ) ) { if ( item->childCount() > 0 ) { - if ( !productsView->isNone( item ) ) { + // VSR : 29/01/05 : Check installation script even if product is not being installed + // if ( !productsView->isNone( item ) ) { if ( item->text(2).isEmpty() || item->text(2).isNull() ) { QMessageBox::warning( this, tr( "Error" ), - tr( "You don't have a defined script for %1").arg(item->text(0)), + tr( "The installation script for %1 is not defined.").arg(item->text(0)), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1045,10 +1092,10 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) return false; } else { QFileInfo fi( QString("./config_files/") + item->text(2) ); - if ( !fi.exists() ) { + if ( !fi.exists() || !fi.isExecutable() ) { QMessageBox::warning( this, tr( "Error" ), - tr( "%1 required for %2 doesn't exist.").arg("./config_files/" + item->text(2)).arg(item->text(0)), + 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)), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1061,7 +1108,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) return false; } } - } + // } // collect native products if ( productsView->isNative( item ) ) { if ( natives.find( item->text(0) ) == natives.end() ) @@ -1077,9 +1124,9 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) } else { QMessageBox::warning( this, - tr( "Warning" ), + tr( "Error" ), tr( "%1 is required for %2 %3 installation.\n" - "Please, add this product in config.xml file.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)), + "This product is missing in the configuration file %4.").arg(dependOn[ i ]).arg(item->text(0)).arg(item->text(1)).arg(xmlFileName), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1109,7 +1156,7 @@ bool SALOME_InstallWizard::acceptData( const QString& pageTitle ) QMessageBox::warning( this, tr( "Warning" ), tr( "%The product %1 %2 required for installation.\n" - "Please, add this product in config.xml file.").arg(item->text(0)).arg(item->text(1)), + "This product is missing in the configuration file %4.").arg(item->text(0)).arg(item->text(1)).arg(xmlFileName), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); @@ -1366,6 +1413,7 @@ void SALOME_InstallWizard::launchScript() passedParams->clear(); passedParams->setEnabled( false ); QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f ); + installInfo->setFinished( true ); if ( isMinimized() ) showNormal(); raise(); @@ -1410,15 +1458,15 @@ void SALOME_InstallWizard::onLaunchSalome() QCheckListItem* item = findItem( "KERNEL-Bin" ); if ( item ) { QFileInfo fi( targetFolder->text() + "/KERNEL_" + item->text(1) + "/bin/salome/runSalome" ); - QFileInfo fienv( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.csh" ); + QFileInfo fienv( targetFolder->text() + "/KERNEL_" + item->text(1) + "/salome.sh" ); if ( fienv.exists() ) { if ( fi.exists() ) { QString script; script += "cd " + targetFolder->text() + "/KERNEL_" + item->text(1) + "; "; - script += "source salome.csh; "; + script += "source salome.sh; "; script += "cd bin/salome; "; script += "runSalome > /dev/null"; - script = "(csh -c '" + script + "')"; + script = "(bash -c '" + script + "')"; ___MESSAGE___( "script: " << script.latin1() ); if ( !system( script.latin1() ) ) return; @@ -1575,6 +1623,7 @@ void SALOME_InstallWizard::pageChanged( const QString & mytitle) // progress page progressView->clear(); installInfo->clear(); + installInfo->setFinished( false ); passedParams->clear(); passedParams->setEnabled( false ); QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f ); @@ -1667,6 +1716,17 @@ void SALOME_InstallWizard::directoryChanged( const QString& /*text*/ ) // ================================================================ void SALOME_InstallWizard::onStart() { + if ( nextButton()->text() == tr( "&Stop" ) ) { + shellProcess->kill(); + while( shellProcess->isRunning() ); + return; + } + progressView->clear(); + installInfo->clear(); + installInfo->setFinished( false ); + passedParams->clear(); + passedParams->setEnabled( false ); + QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f ); // clear list of products to install ... toInstall.clear(); // ... and fill it for new process @@ -1682,7 +1742,10 @@ void SALOME_InstallWizard::onStart() if ( !toInstall.isEmpty() ) { clean(false); // VSR 07/02/05 - bug fix: first we should clear temporary directory // disable button - setNextEnabled( false ); + //setNextEnabled( false ); + nextButton()->setText( tr( "&Stop" ) ); + QWhatsThis::add( nextButton(), tr( "Aborts installation process" ) ); + QToolTip::add ( nextButton(), tr( "Aborts installation process" ) ); // disable button setBackEnabled( false ); // enable script parameters line edit @@ -1742,14 +1805,22 @@ void SALOME_InstallWizard::productInstalled( ) passedParams->clear(); passedParams->setEnabled( false ); QFont f = parametersLab->font(); f.setBold( false ); parametersLab->setFont( f ); + installInfo->setFinished( true ); // enable button setNextEnabled( true ); - nextButton()->setText( tr( "&Next >" ) ); - QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) ); - QToolTip::add ( nextButton(), tr( "Moves to the next step of the installation procedure" ) ); + nextButton()->setText( tr( "&Start" ) ); + QWhatsThis::add( nextButton(), tr( "Starts installation process" ) ); + QToolTip::add ( nextButton(), tr( "Starts installation process" ) ); + // reconnect Next button - to use it as Start button disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) ); disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) ); - connect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) ); + connect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) ); + //nextButton()->setText( tr( "&Next >" ) ); + //QWhatsThis::add( nextButton(), tr( "Moves to the next step of the installation procedure" ) ); + //QToolTip::add ( nextButton(), tr( "Moves to the next step of the installation procedure" ) ); + //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) ); + //disconnect( this, SIGNAL( nextClicked() ), this, SLOT( onStart() ) ); + //connect( this, SIGNAL( nextClicked() ), this, SLOT( next() ) ); // enable button setBackEnabled( true ); } @@ -2005,6 +2076,41 @@ void SALOME_InstallWizard::polish() InstallWizard::polish(); } // ================================================================ +/*! + * SALOME_InstallWizard::saveLog + * Save installation log to file + */ +// ================================================================ +void SALOME_InstallWizard::saveLog() +{ + QString txt = installInfo->text(); + if ( txt.length() <= 0 ) + return; + QDateTime dt = QDateTime::currentDateTime(); + QString fileName = dt.toString("ddMMyy-hhmm"); + fileName.prepend("install-"); fileName.append(".html"); + fileName = QFileDialog::getSaveFileName( fileName, + QString( "HTML files (*.htm *.html)" ), + this, 0, + tr( "Save Log file" ) ); + if ( !fileName.isEmpty() ) { + QFile f( fileName ); + if ( f.open( IO_WriteOnly ) ) { + QTextStream stream( &f ); + stream << txt; + f.close(); + } + else { + QMessageBox::critical( this, + tr( "Error" ), + tr( "Can't save file %1.\nCheck path and permissions.").arg( fileName ), + QMessageBox::Ok, + QMessageBox::NoButton, + QMessageBox::NoButton ); + } + } +} +// ================================================================ /*! * SALOME_InstallWizard::updateCaption * Updates caption according to the current page number diff --git a/src/SALOME_InstallWizard.hxx b/src/SALOME_InstallWizard.hxx index dd9e4d7..37800cd 100644 --- a/src/SALOME_InstallWizard.hxx +++ b/src/SALOME_InstallWizard.hxx @@ -97,10 +97,11 @@ class QProcess; class QCheckBox; class QSplitter; class QMyCheckBox; -class QProcessThread; +class ProcessThread; class ProductsView; class ProgressView; class HelpWindow; +class InstallInfo; typedef QMap MapProducts; @@ -153,6 +154,9 @@ class SALOME_InstallWizard: public InstallWizard QString getOS() { return myOS; } // get InstallWizard's name QString getIWName() { return myIWName; } + + // save install log to file + void saveLog(); protected: // updates caption according to the current page number @@ -235,63 +239,63 @@ class SALOME_InstallWizard: public InstallWizard void readFromStderr(); private: - QString myIWName; // Installation Wizard's name - QString myVersion; // version info - QString myCaption; // application name - QString myCopyright; // copyright info - QString myLicense; // license info - QString myOS; // operation system + QString myIWName; // Installation Wizard's name + QString myVersion; // version info + QString myCaption; // application name + QString myCopyright; // copyright info + QString myLicense; // license info + QString myOS; // operation system - HelpWindow* helpWindow; // help window - QProcess* shellProcess; // shell process (install script) - MapProducts productsMap; // products info (name, dependancies, disk space ) - QStringList toInstall; // list of products being installed - QString xmlFileName; // xml file - bool moreMode; // advanced mode flag - QWidget* previousPage; // previous page - QString tmpCreated; // created temporary directory - bool exitConfirmed; // flag: "Exit confirmed" + HelpWindow* helpWindow; // help window + QProcess* shellProcess; // shell process (install script) + MapProducts productsMap; // products info (name, dependancies, disk space ) + QStringList toInstall; // list of products being installed + QString xmlFileName; // xml file + bool moreMode; // advanced mode flag + QWidget* previousPage; // previous page + QString tmpCreated; // created temporary directory + bool exitConfirmed; // flag: "Exit confirmed" // Widgets // --> introduction page - QWidget* introPage; // page itself - QLabel* logoLab; // logo pixmap - QLabel* versionLab; // vesrsion info - QLabel* copyrightLab; // copyright info - QLabel* licenseLab; // license info - QLabel* info; // program info + QWidget* introPage; // page itself + QLabel* logoLab; // logo pixmap + QLabel* versionLab; // vesrsion info + QLabel* copyrightLab; // copyright info + QLabel* licenseLab; // license info + QLabel* info; // program info // --> products page - QWidget* productsPage; // page itself - QLineEdit* targetFolder; // target directory for installing of products - QPushButton* targetBtn; // browse target directory button - QLineEdit* tempFolder; // directory for the temporary files: /tmp by default - QPushButton* tempBtn; // browse temp directory button - QLabel* requiredSize; // label - QLabel* requiredTemp; // label - QPushButton* moreBtn; // button - QWidget* moreBox; // container for the mode widgets - ProductsView* productsView; // products list view - QTextBrowser* productsInfo; // products info box - QCheckBox* prerequisites; // checkbox - QMyCheckBox* selectSrcBtn; // check box - QMyCheckBox* selectBinBtn; // check box - QPushButton* unselectBtn; // button + QWidget* productsPage; // page itself + QLineEdit* targetFolder; // target directory for installing of products + QPushButton* targetBtn; // browse target directory button + QLineEdit* tempFolder; // directory for the temporary files: /tmp by default + QPushButton* tempBtn; // browse temp directory button + QLabel* requiredSize; // label + QLabel* requiredTemp; // label + QPushButton* moreBtn; // button + QWidget* moreBox; // container for the mode widgets + ProductsView* productsView; // products list view + QTextBrowser* productsInfo; // products info box + QCheckBox* prerequisites; // checkbox + QMyCheckBox* selectSrcBtn; // check box + QMyCheckBox* selectBinBtn; // check box + QPushButton* unselectBtn; // button // --> prestart page - QWidget* prestartPage; // page itself - QTextEdit* choices; // choice text view + QWidget* prestartPage; // page itself + QTextEdit* choices; // choice text view // --> progress page - QWidget* progressPage; // page itself - QSplitter* splitter; // splitter window - QTextEdit* installInfo; // information about running installation scripts - QLabel* parametersLab; // answer field's label - QLineEdit* passedParams; // user can pass data to running script - QTextEdit* installProgress;// contains information about progress of installing selected products - ProgressView* progressView; // displays information about progress of installing selected products + QWidget* progressPage; // page itself + QSplitter* splitter; // splitter window + InstallInfo* installInfo; // information about running installation scripts + QLabel* parametersLab; // answer field's label + QLineEdit* passedParams; // user can pass data to running script + QTextEdit* installProgress;// contains information about progress of installing selected products + ProgressView* progressView; // displays information about progress of installing selected products // --> readme page - QWidget* readmePage; // page itself - QTextEdit* readme; // Readme information window - QPushButton* runSalomeBtn; // buttnon + QWidget* readmePage; // page itself + QTextEdit* readme; // Readme information window + QPushButton* runSalomeBtn; // buttnon - QProcessThread* myThread; // validation thread + ProcessThread* myThread; // validation thread }; #endif diff --git a/src/globals.h b/src/globals.h index cb6868b..1a7c369 100644 --- a/src/globals.h +++ b/src/globals.h @@ -13,10 +13,11 @@ // ======================== #include +#include #ifdef QT_DEBUG -#define ___MESSAGE___( x ) cout << x << endl; +#define ___MESSAGE___( x ) std::cout << x << std::endl; #else -- 2.39.2