void QgsGrassModule::run() { QgsDebugMsg( "called." ); if ( mProcess.state() == QProcess::Running ) { mProcess.kill(); mRunButton->setText( tr( "Run" ) ); } else { //QString command; QStringList arguments; //mProcess.clearArguments(); //mProcess.addArgument( mXName ); //command = mXName; // Check if options are ready QStringList readyErrors = mOptions->ready(); if ( readyErrors.size() > 0 ) { QString err; for ( int i = 0; i < readyErrors.size(); i++ ) { err.append( readyErrors.at( i ) + "<br>" ); } QMessageBox::warning( 0, tr( "Warning" ), err ); return; } // Check/set region struct Cell_head tempWindow; bool resetRegion = false; QgsCoordinateReferenceSystem crs; if ( mOptions->requestsRegion() ) // direct always { if ( !mOptions->inputRegion( &tempWindow, crs, false ) ) { QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot get input region" ) ); return; } resetRegion = true; } else if ( mOptions->usesRegion() ) { QStringList outsideRegion = mOptions->checkRegion(); if ( outsideRegion.size() > 0 ) { QMessageBox questionBox( QMessageBox::Question, tr( "Warning" ), tr( "Input %1 outside current region!" ).arg( outsideRegion.join( QStringLiteral( "," ) ) ), QMessageBox::Ok | QMessageBox::Cancel ); QPushButton *resetButton = nullptr; if ( QgsGrass::versionMajor() > 6 || ( QgsGrass::versionMajor() == 6 && QgsGrass::versionMinor() >= 1 ) ) { resetButton = questionBox.addButton( tr( "Use Input Region" ), QMessageBox::DestructiveRole ); } questionBox.exec(); QAbstractButton *clicked = questionBox.clickedButton(); if ( clicked == questionBox.button( QMessageBox::Cancel ) ) return; if ( clicked == resetButton ) resetRegion = true; if ( resetRegion ) { if ( !mOptions->inputRegion( &tempWindow, crs, true ) ) { QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot get input region" ) ); return; } } } } // In direct mode user is warned by select file dialog if ( !mDirect ) { // Check if output exists QStringList outputExists = mOptions->checkOutput(); if ( outputExists.size() > 0 ) { QMessageBox::StandardButton ret = QMessageBox::question( 0, QStringLiteral( "Warning" ), tr( "Output %1 exists! Overwrite?" ).arg( outputExists.join( QStringLiteral( "," ) ) ), QMessageBox::Ok | QMessageBox::Cancel ); if ( ret == QMessageBox::Cancel ) return; arguments.append( QStringLiteral( "--o" ) ); } } // Remember output maps mOutputVector = mOptions->output( QgsGrassModuleOption::Vector ); QgsDebugMsg( QString( "mOutputVector.size() = %1" ).arg( mOutputVector.size() ) ); mOutputRaster = mOptions->output( QgsGrassModuleOption::Raster ); QgsDebugMsg( QString( "mOutputRaster.size() = %1" ).arg( mOutputRaster.size() ) ); mSuccess = false; mViewButton->setEnabled( false ); QStringList list = mOptions->arguments(); list << arguments; QStringList argumentsHtml; for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { QgsDebugMsg( "option: " + ( *it ) ); //command.append ( " " + *it ); arguments.append( *it ); //mProcess.addArgument( *it ); // Quote options with special characters so that user // can copy-paste-run the command if ( it->contains( QRegExp( "[ <>\\$|;&]" ) ) ) { argumentsHtml.append( "\"" + *it + "\"" ); } else { argumentsHtml.append( *it ); } } /* WARNING - TODO: there was a bug in GRASS 6.0.0 / 6.1.CVS (< 2005-04-29): * db_start_driver set GISRC_MODE_MEMORY eviroment variable to 1 if * G_get_gisrc_mode() == G_GISRC_MODE_MEMORY but the variable wasn't unset * if G_get_gisrc_mode() == G_GISRC_MODE_FILE. Because QGIS GRASS provider starts drivers in * G_GISRC_MODE_MEMORY mode, the variable remains set in variable when a module is run * -> unset GISRC_MODE_MEMORY. Remove later once 6.1.x / 6.0.1 is widespread. * */ putenv( ( char * ) "GISRC_MODE_MEMORY" ); // unset mOutputTextBrowser->clear(); QProcessEnvironment environment = processEnvironment( mDirect ); environment.insert( QStringLiteral( "GRASS_HTML_BROWSER" ), QgsGrassUtils::htmlBrowserPath() ); // Warning: it is not useful to write requested region to WIND file and // reset then to original because it is reset before // the region is read by a module even if waitForStarted() is used // -> necessary to pass region as environment variable // but the feature is available in GRASS 6.1 only since 23.3.2006 if ( resetRegion ) { QString reg = QgsGrass::regionString( &tempWindow ); QgsDebugMsg( "reg: " + reg ); environment.insert( QStringLiteral( "GRASS_REGION" ), reg ); } if ( mDirect ) { QStringList variables; setDirectLibraryPath( environment ); #ifdef Q_OS_WIN variables << "PATH"; #elif defined(Q_OS_MAC) variables << "DYLD_LIBRARY_PATH"; #else variables << QStringLiteral( "LD_LIBRARY_PATH" ); #endif environment.insert( QStringLiteral( "QGIS_PREFIX_PATH" ), QgsApplication::prefixPath() ); if ( crs.isValid() ) // it should always be valid { environment.insert( QStringLiteral( "QGIS_GRASS_CRS" ), crs.toProj4() ); } // Suppress debug output environment.insert( QStringLiteral( "QGIS_DEBUG" ), QStringLiteral( "-1" ) ); // Print some important variables variables << QStringLiteral( "QGIS_PREFIX_PATH" ) << QStringLiteral( "QGIS_GRASS_CRS" ) << QStringLiteral( "GRASS_REGION" ); Q_FOREACH ( const QString &v, variables ) { mOutputTextBrowser->append( v + "=" + environment.value( v ) + "<BR>" ); } } QString commandHtml = mXName + " " + argumentsHtml.join( QStringLiteral( " " ) ); QgsDebugMsg( "command: " + commandHtml ); commandHtml.replace( QLatin1String( "&" ), QLatin1String( "&" ) ); commandHtml.replace( QLatin1String( "<" ), QLatin1String( "<" ) ); commandHtml.replace( QLatin1String( ">" ), QLatin1String( ">" ) ); mOutputTextBrowser->append( "<B>" + commandHtml + "</B>" ); // I was not able to get scripts working on Windows // via QProcess and sh.exe (MinGW). g.parser runs wellQProcessEnvironment::systemE // and it sets parameters correctly as environment variables // but it fails (without error) to re-run the script with // execlp(). And I could not figure out why it fails. // Because of this problem we simulate here what g.parser // normally does and that way we can avoid it. QStringList execArguments = QgsGrassModule::execArguments( mXName ); if ( execArguments.size() == 0 ) { QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot find module %1" ).arg( mXName ) ); return; } #ifdef Q_OS_WIN // we already know it exists from execArguments() QString exe = QgsGrass::findModule( mXName ); QFileInfo fi( exe ); if ( !fi.isExecutable() ) { QStringList usedFlagNames; // Set environment variables for ( int i = 0; i < arguments.size(); i++ ) { QString arg = arguments.at( i ); //QString env; if ( arg.at( 0 ) == '-' ) //flag { //env = "GIS_FLAG_" + QString( arg.at( 1 ).toUpper() ) + "=1"; environment.insert( "GIS_FLAG_" + QString( arg.at( 1 ).toUpper() ), "1" ); usedFlagNames.append( arg.at( 1 ) ); } else // option { QStringList opt = arg.split( "=" ); //env = "GIS_OPT_" + opt.takeFirst().toUpper(); //env += "=" + opt.join( "=" ); // rejoin rest environment.insert( "GIS_OPT_" + opt.takeFirst().toUpper(), opt.join( "=" ) ); } //environment.append( env ); } // Set remaining flags QStringList allFlagNames = mOptions->flagNames(); for ( int i = 0; i < allFlagNames.size(); i++ ) { bool used = false; for ( int j = 0; j < usedFlagNames.size(); j++ ) { if ( usedFlagNames.at( j ) == allFlagNames.at( i ) ) { used = true; break; } } if ( used ) continue; //QString env = "GIS_FLAG_" // + QString( allFlagNames.at( i ).toUpper() ) // + "=0"; //QgsDebugMsg( "set: " + env ); //environment.append( env ); environment.insert( "GIS_FLAG_" + QString( allFlagNames.at( i ).toUpper() ), "0" ); } arguments.clear(); arguments.append( "@ARGS_PARSED@" ); } #endif QString cmd = execArguments.takeFirst(); execArguments += arguments; // Freeze output vector on Windows mOptions->freezeOutput(); mProcess.setProcessEnvironment( environment ); mProcess.start( cmd, execArguments ); emit moduleStarted(); mProcess.waitForStarted(); if ( mProcess.state() != QProcess::Running ) { QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot start module: %1" ).arg( mProcess.errorString() ) ); return; } mTabWidget->setCurrentIndex( 1 ); mRunButton->setText( tr( "Stop" ) ); }
void QgsGrassTools::runModule( QString name, bool direct ) { if ( name.length() == 0 ) return; // Section #ifdef HAVE_OPENPTY QgsGrassShell* sh = 0; #endif QString path = QgsApplication::pkgDataPath() + "/grass/modules/" + name; QgsDebugMsg( QString( "path = %1" ).arg( path ) ); QWidget *m; if ( name == "shell" ) { #ifdef WIN32 QgsGrass::putEnv( "GRASS_HTML_BROWSER", QgsApplication::libexecPath() + "grass/bin/qgis.g.browser" ); if ( !QProcess::startDetached( getenv( "COMSPEC" ) ) ) { QMessageBox::warning( 0, "Warning", tr( "Cannot start command shell (%1)" ).arg( getenv( "COMSPEC" ) ) ); } return; #else #ifdef HAVE_OPENPTY sh = new QgsGrassShell( this, mTabWidget ); m = qobject_cast<QWidget *>( sh ); #else QMessageBox::warning( 0, tr( "Warning" ), tr( "GRASS Shell is not compiled." ) ); #endif // HAVE_OPENPTY #endif // ! WIN32 } else { QgsGrassModule *gmod = new QgsGrassModule( this, name, mIface, path, direct, mTabWidget ); connect( gmod, SIGNAL( moduleStarted() ), mBrowser, SLOT( moduleStarted() ) ); connect( gmod, SIGNAL( moduleFinished() ), mBrowser, SLOT( moduleFinished() ) ); m = qobject_cast<QWidget *>( gmod ); } int height = mTabWidget->iconSize().height(); QPixmap pixmap = QgsGrassModule::pixmap( path, height ); // Icon size in QT4 does not seem to be variable // -> reset the width to max icon width if ( mTabWidget->iconSize().width() < pixmap.width() ) { mTabWidget->setIconSize( QSize( pixmap.width(), mTabWidget->iconSize().height() ) ); } QIcon is; is.addPixmap( pixmap ); mTabWidget->addTab( m, is, "" ); mTabWidget->setCurrentIndex( mTabWidget->count() - 1 ); // We must call resize to reset COLUMNS environment variable // used by bash !!! #if 0 /* TODO: Implement something that resizes the terminal without * crashes. */ #ifdef HAVE_OPENPTY if ( sh ) sh->resizeTerminal(); #endif #endif }