📄 qgsgrassmodule.cpp
字号:
if ( typeid(*(mItems[i])) == typeid (QgsGrassModuleInput) ) { QgsGrassModuleInput *item = dynamic_cast<QgsGrassModuleInput *>(mItems[i]); if ( item->useRegion() ) return true; } /* It only make sense to check input, right? * Output has no region yet */ if ( typeid(*(mItems[i])) == typeid (QgsGrassModuleOption) ) { QgsGrassModuleOption *item = dynamic_cast<QgsGrassModuleOption *> ( mItems[i] ); if ( item->usesRegion() ) return true; } } QgsDebugMsg("NO usesRegion()"); return false;}QgsGrassModuleStandardOptions::~QgsGrassModuleStandardOptions(){}QString QgsGrassModule::label ( QString path ) { QgsDebugMsg("called."); // Open QGIS module description path.append ( ".qgm" ); QFile qFile ( path ); if ( !qFile.exists() ) { return QString ( tr("Not available, description not found (") + path + tr(")") ); } if ( ! qFile.open( QIODevice::ReadOnly ) ) { return QString ( tr("Not available, cannot open description (") + path + tr(")") ) ; } QDomDocument qDoc ( "qgisgrassmodule" ); QString err; int line, column; if ( !qDoc.setContent( &qFile, &err, &line, &column ) ) { QString errmsg = tr("Cannot read module file (") + path + tr("):\n") + err + tr("\nat line ") + QString::number(line) + tr(" column ") + QString::number(column); QgsDebugMsg(errmsg); QMessageBox::warning( 0, tr("Warning"), errmsg ); qFile.close(); return QString ( tr("Not available, incorrect description (") + path + tr(")") ); } qFile.close(); QDomElement qDocElem = qDoc.documentElement(); return ( qDocElem.attribute("label") );}QPixmap QgsGrassModule::pixmap ( QString path, int height ) { QgsDebugMsg("called."); std::vector<QPixmap> pixmaps; // Create vector of available pictures int cnt = 1; while ( 1 ) { // SVG QString fpath = path + "." + QString::number(cnt) + ".svg"; QFileInfo fi ( fpath ); if ( fi.exists() ) { Q3Picture pic; if ( ! pic.load ( fpath, "svg" ) ) break; QRect br = pic.boundingRect(); double scale = 1. * height / br.height(); int width = (int) ( scale * br.width() ); if ( width <= 0 ) width = height; // should not happen QPixmap pixmap ( width, height ); pixmap.fill ( QColor(255,255,255) ); QPainter painter ( &pixmap ); painter.setRenderHint(QPainter::Antialiasing); // I am not sure if this factor is OK scale *= 72.0 / pixmap.logicalDpiX() ; painter.scale ( scale, scale ); painter.drawPicture ( -br.x(), -br.y(), pic ); painter.end(); pixmaps.push_back ( pixmap ); } else // PNG { fpath = path + "." + QString::number(cnt) + ".png"; fi.setFile ( fpath ); if ( !fi.exists() ) break; QPixmap pixmap; if ( ! pixmap.load(fpath, "PNG" ) ) break; double scale = 1. * height / pixmap.height(); int width = (int) ( scale * pixmap.width() ); QImage img = pixmap.convertToImage(); img = img.smoothScale ( width, height ); pixmap.convertFromImage ( img ); pixmaps.push_back ( pixmap ); } cnt++; } // Get total width int width = 0; for ( unsigned int i = 0; i < pixmaps.size(); i++ ) { width += pixmaps[i].width(); } if ( width <= 0 ) width = height; //should not happen int plusWidth = 8; // + int arrowWidth = 9; // -> int buffer = 10; // buffer around a sign if ( pixmaps.size() > 1 ) width += arrowWidth + 2 * buffer; // -> if ( pixmaps.size() > 2 ) width += plusWidth + 2 * buffer; // + QPixmap pixmap ( width, height ); pixmap.fill(QColor(255,255,255)); QPainter painter ( &pixmap ); QColor color(200,200,200); painter.setBrush(QBrush(color)); painter.setRenderHint(QPainter::Antialiasing); int pos = 0; for ( unsigned int i = 0; i < pixmaps.size(); i++ ) { if ( i == 1 && pixmaps.size() == 3 ) { // + pos += buffer; painter.setPen( QPen(color,3) ); painter.drawLine ( pos, height/2, pos+plusWidth, height/2 ); painter.drawLine ( pos+plusWidth/2, height/2-plusWidth/2, pos+plusWidth/2, height/2+plusWidth/2 ); pos += buffer + plusWidth; } if ( (i == 1 && pixmaps.size() == 2) || (i == 2 && pixmaps.size() == 3) ) { // -> pos += buffer; painter.setPen( QPen(color,3) ); painter.drawLine ( pos, height/2, pos+arrowWidth-arrowWidth/2, height/2 ); Q3PointArray pa(3); pa.setPoint(0, pos+arrowWidth/2+1, height/2-arrowWidth/2); pa.setPoint(1, pos+arrowWidth, height/2 ); pa.setPoint(2, pos+arrowWidth/2+1, height/2+arrowWidth/2); painter.setPen( QPen(color,1) ); painter.drawPolygon ( pa ); pos += buffer + arrowWidth; } painter.drawPixmap ( pos,0, pixmaps[i] ); pos += pixmaps[i].width(); } painter.end(); return pixmap;}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; if ( mOptions->requestsRegion() ) { if ( !mOptions->inputRegion ( &tempWindow, 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, "Warning", "Input " + outsideRegion.join(",") + " outside current region!", QMessageBox::Ok | QMessageBox::Cancel ); QPushButton *resetButton = NULL; 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, true ) ) { QMessageBox::warning ( 0, tr("Warning"), tr("Cannot get input region" ) ); return; } } } } // Check if output exists QStringList outputExists = mOptions->checkOutput(); if ( outputExists.size() > 0 ) { QMessageBox::StandardButton ret = QMessageBox::question ( 0, "Warning", "Output " + outputExists.join(",") + " exists! Overwrite?", QMessageBox::Ok | QMessageBox::Cancel ); if ( ret == QMessageBox::Cancel ) return; // r.mapcalc does not use standard parser if ( typeid(*mOptions) != typeid(QgsGrassMapcalc) ) { arguments.append ( "--o" ); //mProcess.addArgument( "--o" ); //command.append ( " --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(); 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(); QString commandHtml = mXName + " " + argumentsHtml.join(" "); QgsDebugMsg("command: " + commandHtml); commandHtml.replace ( "&", "&" ); commandHtml.replace ( "<", "<" ); commandHtml.replace ( ">", ">" ); mOutputTextBrowser->append( "<B>" + commandHtml + "</B>" ); // Warning: it is not useful to write requested region to WIND file and // reset then to original beacuse it is reset before // the region is read by a module even if waitForStarted() is used // -> necessary to pass region as enviroment variable // but the feature is available in GRASS 6.1 only since 23.3.2006 QStringList environment = QProcess::systemEnvironment(); if ( resetRegion ) { QString reg = QgsGrass::regionString( &tempWindow ); QgsDebugMsg("reg: " + reg); environment.append ( "GRASS_REGION=" + reg ); } // I was not able to get scripts working on Windows // via QProcess and sh.exe (MinGW). g.parser runs well // and it sets parameters correctly as enviroment 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 // normaly 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 ") + mXName ); return; }#if defined(WIN32) // we already know it exists from execArguments() QString exe = QgsGrassModule::findExec ( mXName ); QFileInfo fi ( exe ); if ( !fi.isExecutable() ) { QStringList usedFlagNames; // Set enviroment 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"; usedFlagNames.append(arg.at(1)); } else // option { QStringList opt = arg.split("="); env = "GIS_OPT_" + opt.takeFirst().toUpper(); env += "=" + opt.join("="); // rejoin rest } QgsDebugMsg("set: " + env); 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); } arguments.clear(); arguments.append ( "@ARGS_PARSED@" ); }#endif QString cmd = execArguments.takeFirst(); execArguments += arguments; // Freeze output vector on Windows mOptions->freezeOutput(); mProcess.setEnvironment ( environment ); mProcess.start( cmd, execArguments ); mProcess.waitForStarted(); if ( mProcess.state() != QProcess::Running ) { QMessageBox::warning( 0, tr("Warning"), tr("Cannot start module: ") + mProcess.errorString() ); return; } mTabWidget->setCurrentPage(1); mRunButton->setText( tr("Stop") ); }}void QgsGrassModule::finished(int exitCode, QProcess::ExitStatus exitStatus ){ QgsDebugMsg("called."); QgsDebugMsg( QString("exitCode = %1").arg(exitCode) ); if ( exitStatus == QProcess::NormalExit ) { if ( exitCode == 0 ) { mOutputTextBrowser->append( tr("<B>Successfully finished</B>") ); mProgressBar->setProgress ( 100, 100 ); mSuccess = true; mViewButton->setEnabled(true); mOptions->thawOutput(); } else { mOutputTextBrowser->append( tr("<B>Finished with error</B>") ); } } else { mOutputTextBrowser->append( tr("<B>Module crashed or killed</B>") ); } mRunButton->setText( tr("Run") );}void QgsGrassModule::readStdout(){ QgsDebugMsg("called."); QString line; QRegExp rxpercent ( "GRASS_INFO_PERCENT: (\\d+)" ); mProcess.setReadChannel ( QProcess::StandardOutput ); while ( mProcess.canReadLine() ) { //line = QString::fromLocal8Bit( mProcess.readLineStdout().ascii() ); QByteArray ba = mProcess.readLine(); line = QString::fromLocal8Bit( QString(ba).ascii() ); // GRASS_INFO_PERCENT is catched here only because of bugs in GRASS, // normaly it should be printed to stderr if ( rxpercent.search ( line ) != -1 ) { int progress = rxpercent.cap(1).toInt(); mProgressBar->setProgress ( progress, 100 ); } else { mOutputTextBrowser->append ( line ); } }}void QgsGrassModule::readStderr(){ QgsDebugMsg("called.");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -