⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qgsgrass.cpp

📁 一个非常好的GIS开源新版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************    qgsgrass.cpp  -  Data provider for GRASS format                             -------------------    begin                : March, 2004    copyright            : (C) 2004 by Radim Blazek    email                : blazek@itc.it ***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************//* $Id: qgsgrass.cpp 8350 2008-04-14 21:02:22Z jef $ */#include <iostream>#include "QString"#include "q3process.h"#include "QFile"#include "QFileInfo"#include "QFileDialog"#include "QDir"#include "QTextStream"#include "QSettings"#include <QMessageBox>#include <QCoreApplication>#include <QProcess>#include "qgsapplication.h"#include "qgsgrass.h"extern "C" {#ifndef _MSC_VER#include <unistd.h>#endif#include <grass/gis.h>#include <grass/Vect.h>#include <grass/version.h>}#if defined(WIN32)#include <windows.h>static QString getShortPath(const QString &path){  TCHAR buf[MAX_PATH];  GetShortPathName( path.ascii(), buf, MAX_PATH);  return buf;}#endifvoid GRASS_EXPORT QgsGrass::init( void ) {  // Warning!!!   // G_set_error_routine() once called from plugin  // is not valid in provider -> call it always   // Set error function  G_set_error_routine ( &error_routine );  if ( initialized ) return;  QSettings settings;  // Is it active mode ?  if ( getenv ("GISRC") ) {    active = true;     // Store default values    defaultGisdbase = G_gisdbase();    defaultLocation = G_location();    defaultMapset = G_mapset();  } else {    active = false;  }  // Don't use GISRC file and read/write GRASS variables (from location G_VAR_GISRC) to memory only.  G_set_gisrc_mode ( G_GISRC_MODE_MEMORY );   // Init GRASS libraries (required)  G_no_gisinit();  // Doesn't check write permissions for mapset compare to G_gisinit("libgrass++");   // Set program name  G_set_program_name ("QGIS");  // Require GISBASE to be set. This should point to the location of  // the GRASS installation. The GRASS libraries use it to know  // where to look for things.  // Look first to see if GISBASE env var is already set.  // This is set when QGIS is run from within GRASS  // or when set explicitly by the user.  // This value should always take precedence.  QString gisBase = getenv("GISBASE");#ifdef QGISDEBUG  qDebug( "%s:%d GRASS gisBase from GISBASE env var is: %s", __FILE__, __LINE__, (const char*)gisBase );#endif  if ( !isValidGrassBaseDir(gisBase) ) {    // Look for gisbase in QSettings    gisBase = settings.readEntry("/GRASS/gisbase", "");#ifdef QGISDEBUG    qDebug( "%s:%d GRASS gisBase from QSettings is: %s", __FILE__, __LINE__, (const char*)gisBase );#endif  }  if ( !isValidGrassBaseDir(gisBase) ) {    // Erase gisbase from settings because it does not exists     settings.writeEntry("/GRASS/gisbase", "");#ifdef WIN32    // Use the applicationDirPath()/grass    gisBase = getShortPath( QCoreApplication::applicationDirPath() + "/grass" );#ifdef QGISDEBUG    std::cerr << "GRASS gisBase = " << gisBase.ascii() << std::endl;#endif#else    // Use the location specified --with-grass during configure    gisBase = GRASS_BASE;#ifdef QGISDEBUG    qDebug( "%s:%d GRASS gisBase from configure is: %s", __FILE__, __LINE__, (const char*)gisBase );#endif#endif  }  bool userGisbase = false;  bool valid = false;  while ( !(valid = isValidGrassBaseDir(gisBase)) ) {    // ask user if he wants to specify GISBASE    QMessageBox::StandardButton res = QMessageBox::warning(0, QObject::tr("GRASS plugin"),      QObject::tr("QGIS couldn't find your GRASS installation.\n"      "Would you like to specify path (GISBASE) to your GRASS installation?"),      QMessageBox::Ok | QMessageBox::Cancel);    if (res != QMessageBox::Ok)    {      userGisbase = false;      break;    }    // XXX Need to subclass this and add explantory message above to left side    userGisbase = true;    // For Mac, GISBASE folder may be inside GRASS bundle. Use Qt file dialog    // since Mac native dialog doesn't allow user to browse inside bundles.    gisBase = QFileDialog::getExistingDirectory(      0, QObject::tr("Choose GRASS installation path (GISBASE)"), gisBase,      QFileDialog::DontUseNativeDialog);    if (gisBase == QString::null)    {      // User pressed cancel. No GRASS for you!      userGisbase = false;      break;    }#if defined(WIN32)    gisBase = getShortPath(gisBase);#endif  }  if (!valid)  {    // warn user    QMessageBox::information(0, QObject::tr("GRASS plugin"),      QObject::tr("GRASS data won't be available if GISBASE is not specified."));  }  if ( userGisbase )  {    settings.writeEntry("/GRASS/gisbase", gisBase);  }#ifdef QGISDEBUG  qDebug( "%s:%d Valid GRASS gisBase is: %s", __FILE__, __LINE__, (const char*)gisBase );#endif  QString gisBaseEnv = "GISBASE=" + gisBase;  /* _Correct_ putenv() implementation is not making copy! */   char *gisBaseEnvChar = new char[gisBaseEnv.length()+1];  strcpy ( gisBaseEnvChar, const_cast<char *>(gisBaseEnv.ascii()) );   putenv( gisBaseEnvChar );  // Add path to GRASS modules#ifdef WIN32  QString sep = ";";#else  QString sep = ":";#endif  QString path = "PATH=" + gisBase + "/bin";  path.append ( sep + gisBase + "/scripts" );  // On windows the GRASS libraries are in   // QgsApplication::prefixPath(), we have to add them  // to PATH to enable running of GRASS modules   // and database drivers#ifdef WIN32  // It seems that QgsApplication::prefixPath()   // is not initialized at this point  path.append ( sep + getShortPath(QCoreApplication::applicationDirPath()) );  // Add path to MSYS bin  // Warning: MSYS sh.exe will translate this path to '/bin'  path.append ( sep + getShortPath(QCoreApplication::applicationDirPath() + "/msys/bin/") );#endif  QString p = getenv ("PATH");  path.append ( sep + p );#ifdef QGISDEBUG  std::cerr << "set PATH: " << path.toLocal8Bit().data() << std::endl;#endif  char *pathEnvChar = new char[path.length()+1];  strcpy ( pathEnvChar, const_cast<char *>(path.ascii()) );  putenv( pathEnvChar );  // Set GRASS_PAGER if not set, it is necessary for some   // modules printing to terminal, e.g. g.list  // We use 'cat' because 'more' is not present in MSYS (Win)  // and it doesn't work well in built in shell (Unix/Mac)   // and 'less' is not user friendly (for example user must press  // 'q' to quit which is definitely difficult for normal user)  // Also scroling can be don in scrollable window in both   // MSYS terminal and built in shell.  if ( !getenv ("GRASS_PAGER") )   {    QString pager;    QStringList pagers;    //pagers << "more" << "less" << "cat"; // se notes above    pagers << "cat";    for ( int i = 0; i < pagers.size(); i++ )     {      int state;      QProcess p;      p.start ( pagers.at(i) );      p.waitForStarted();      state = p.state();      p.write("\004"); // Ctrl-D      p.closeWriteChannel();      p.waitForFinished(1000);      p.kill();      if ( state == QProcess::Running )      {        pager = pagers.at(i);        break;      }    }    if ( pager.length() > 0 )    {      pager.prepend ( "GRASS_PAGER=" );      char *pagerEnvChar = new char[pager.length()+1];      strcpy ( pagerEnvChar, const_cast<char *>(pager.ascii()) );      putenv( pagerEnvChar );    }  }  initialized = 1;}/* * Check if given directory contains a GRASS installation */bool QgsGrass::isValidGrassBaseDir(QString const gisBase){#ifdef QGISDEBUG  std::cerr << "isValidGrassBaseDir()" << std::endl;#endif  // GRASS currently doesn't handle paths with blanks  if ( gisBase.isEmpty() || gisBase.contains(" ") )  {    return FALSE;  }  /* TODO: G_is_gisbase() was added to GRASS 6.1 06-05-24,           enable its use after some period (others do update) */   /*  if ( QgsGrass::versionMajor() > 6 || QgsGrass::versionMinor() > 0 )   {  if ( G_is_gisbase( gisBase.toLocal8Bit().constData() ) ) return TRUE;  }   else  {  */  QFileInfo gbi ( gisBase + "/etc/element_list" );  if ( gbi.exists() ) return TRUE;  //}  return FALSE;}bool QgsGrass::activeMode( void ){  init();  return active;}QString QgsGrass::getDefaultGisdbase ( void ){  init();  return defaultGisdbase;}QString QgsGrass::getDefaultLocation ( void ){  init();  return defaultLocation;}QString QgsGrass::getDefaultMapset ( void ){  init();  return defaultMapset;}void QgsGrass::setLocation( QString gisdbase, QString location ){#ifdef QGISDEBUG  std::cerr << "QgsGrass::setLocation(): gisdbase = " << gisdbase.toLocal8Bit().data() << " location = "    << location.toLocal8Bit().data() << std::endl;#endif  init();  // Set principal GRASS variables (in memory)#if defined(WIN32)  G__setenv( (char *)"GISDBASE", (char *) getShortPath(gisdbase).ascii() );#else  G__setenv( (char *)"GISDBASE", (char *) gisdbase.ascii() );#endif  G__setenv( (char *)"LOCATION_NAME", (char *) location.ascii() );  G__setenv( (char *)"MAPSET", (char *)"PERMANENT"); // PERMANENT must always exist  // Add all available mapsets to search path  char **ms = G_available_mapsets();  for ( int i = 0; ms[i]; i++ )  G_add_mapset_to_search_path ( ms[i] );}void QgsGrass::setMapset( QString gisdbase, QString location, QString mapset ){#ifdef QGISDEBUG  std::cerr << "QgsGrass::setLocation(): gisdbase = " << gisdbase.toLocal8Bit().data() << " location = "    << location.toLocal8Bit().data() << " mapset = " << mapset.toLocal8Bit().data() << std::endl;#endif  init();  // Set principal GRASS variables (in memory)#if defined(WIN32)  G__setenv( (char *)"GISDBASE", (char *) getShortPath(gisdbase).ascii() );#else  G__setenv( (char *)"GISDBASE", (char *) gisdbase.ascii() );#endif  G__setenv( (char *)"LOCATION_NAME", (char *) location.ascii() );  G__setenv( (char *)"MAPSET", (char *) mapset.ascii() );   // Add all available mapsets to search path  char **ms = G_available_mapsets();  for ( int i = 0; ms[i]; i++ )  G_add_mapset_to_search_path ( ms[i] );}int QgsGrass::initialized = 0;bool QgsGrass::active = 0;QgsGrass::GERROR QgsGrass::error = QgsGrass::OK;QString QgsGrass::error_message;QString QgsGrass::defaultGisdbase;QString QgsGrass::defaultLocation;QString QgsGrass::defaultMapset;QString QgsGrass::mMapsetLock;QString QgsGrass::mGisrc;QString QgsGrass::mTmp;jmp_buf QgsGrass::mFatalErrorEnv;int QgsGrass::error_routine ( char *msg, int fatal){  return error_routine((const char*) msg, fatal);}int QgsGrass::error_routine ( const char *msg, int fatal){  std::cerr << "error_routine (fatal = " << fatal << "): " << msg << std::endl;  error_message = msg;  if ( fatal )  {     error = FATAL;    // we have to do a long jump here, otherwise GRASS >= 6.3 will kill our process    longjmp(mFatalErrorEnv, 1);  }  else    error = WARNING;  return 1;}void GRASS_EXPORT QgsGrass::resetError ( void ){  error = OK;}int GRASS_EXPORT QgsGrass::getError ( void ){  return error;}QString GRASS_EXPORT QgsGrass::getErrorMessage ( void ){  return error_message;}jmp_buf GRASS_EXPORT &QgsGrass::fatalErrorEnv(){  return mFatalErrorEnv;}QString GRASS_EXPORT QgsGrass::openMapset ( QString gisdbase, QString location, QString mapset ){#ifdef QGISDEBUG  std::cerr << "QgsGrass::openMapset" << std::endl;  std::cerr << "gisdbase = " << gisdbase.local8Bit().data() << std::endl;  std::cerr << "location = " << location.local8Bit().data() << std::endl;  std::cerr << "mapset = " << mapset.local8Bit().data() << std::endl;#endif  QString mapsetPath = gisdbase + "/" + location + "/" + mapset;  // Check if the mapset is in use  QString gisBase = getenv("GISBASE");  if ( gisBase.isNull() ) return QObject::tr("GISBASE is not set.");  QFileInfo fi( mapsetPath+ "/WIND" );  if ( !fi.exists() )  {    return mapsetPath + QObject::tr(" is not a GRASS mapset.");  }  QString lock = mapsetPath + "/.gislock";  QFile lockFile ( lock );  Q3Process *process = new Q3Process();  process->addArgument ( gisBase + "/etc/lock" ); // lock program  process->addArgument ( lock ); // lock file  // TODO: getpid() probably is not portable#ifndef _MSC_VER  int pid = getpid();#else  int pid = GetCurrentProcessId();#endif#ifdef QGISDEBUG  std::cerr << "pid = " << pid << std::endl;#endif  process->addArgument ( QString::number(pid) );   if ( !process->start() )   {    return QObject::tr("Cannot start ") + gisBase + "/etc/lock";  }  // TODO better wait   while ( process->isRunning () ) { }#ifndef WIN32  int status = process->exitStatus ();#ifdef QGISDEBUG  std::cerr << "status = " << status << std::endl;#endif#endif  delete process;  // TODO WIN32 (lock.exe does not work properly?)#ifndef WIN32  if ( status > 0 ) return QObject::tr("Mapset is already in use.");#endif  // Create temporary directory  QFileInfo info ( mapsetPath );  QString user = info.owner();  mTmp = QDir::tempPath () + "/grass6-" + user + "-" + QString::number(pid);  QDir dir ( mTmp );  if ( dir.exists() )  {    QFileInfo dirInfo(mTmp);    if ( !dirInfo.isWritable() )    {      lockFile.remove();      return QObject::tr("Temporary directory ") + mTmp + QObject::tr(" exist but is not writable");    }  }  else if ( !dir.mkdir( mTmp ) )  {    lockFile.remove();    return QObject::tr("Cannot create temporary directory ") + mTmp;  }  // Create GISRC file   QString globalGisrc =  QDir::home().path() + "/.grassrc6";  mGisrc = mTmp + "/gisrc";#ifdef QGISDEBUG  std::cerr << "globalGisrc = " << globalGisrc.local8Bit().data() << std::endl;  std::cerr << "mGisrc = " << mGisrc.local8Bit().data() << std::endl;#endif  QFile out ( mGisrc );  if ( !out.open( QIODevice::WriteOnly ) )   {    lockFile.remove();    return QObject::tr("Cannot create ") + mGisrc;   }  QTextStream stream ( &out );  QFile in ( globalGisrc );  QString line;  char buf[1000];  if ( in.open( QIODevice::ReadOnly ) )   {    while ( in.readLine( buf, 1000 ) != -1 )     {      line = buf;      if ( line.contains("GISDBASE:") ||         line.contains("LOCATION_NAME:") ||        line.contains("MAPSET:") )      {        continue;      }      stream << line;    }    in.close();  }  line = "GISDBASE: " + gisdbase + "\n";  stream << line;  line = "LOCATION_NAME: " + location + "\n";  stream << line;  line = "MAPSET: " + mapset + "\n";  stream << line;  out.close();  // Set GISRC enviroment variable

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -