diff --git a/src/plugins/grass/CMakeLists.txt b/src/plugins/grass/CMakeLists.txt index b384d475f10..6ba1351be19 100644 --- a/src/plugins/grass/CMakeLists.txt +++ b/src/plugins/grass/CMakeLists.txt @@ -126,6 +126,7 @@ INCLUDE_DIRECTORIES( ${GDAL_INCLUDE_DIR} ${PROJ_INCLUDE_DIR} ${GEOS_INCLUDE_DIR} + ${POSTGRES_INCLUDE_DIR} qtermwidget ) @@ -195,7 +196,7 @@ INSTALL (FILES ${GMLS} INSTALL (FILES themes/default/grass_arrow.svg themes/default/grass_plus.svg themes/default/grass_arrow.png themes/default/grass_plus.png DESTINATION ${QGIS_DATA_DIR}/grass/modules) -FOREACH(GRASS_BUILD_VERSION 6) # GRASS 6, but not yet GRASS 7 +FOREACH(GRASS_BUILD_VERSION 6 7) # GRASS 6 and GRASS 7 IF(GRASS_FOUND${GRASS_BUILD_VERSION}) ADD_SUBDIRECTORY(${GRASS_BUILD_VERSION}) ENDIF(GRASS_FOUND${GRASS_BUILD_VERSION}) diff --git a/src/plugins/grass/qgsgrassmapcalc.cpp b/src/plugins/grass/qgsgrassmapcalc.cpp index 02788dc7213..7b88c4bda30 100644 --- a/src/plugins/grass/qgsgrassmapcalc.cpp +++ b/src/plugins/grass/qgsgrassmapcalc.cpp @@ -481,11 +481,13 @@ QStringList QgsGrassMapcalc::checkRegion() QList l = mCanvasScene->items(); struct Cell_head currentWindow; - if ( !QgsGrass::region( QgsGrass::getDefaultGisdbase(), - QgsGrass::getDefaultLocation(), - QgsGrass::getDefaultMapset(), ¤tWindow ) ) + try { - QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot get current region" ) ); + QgsGrass::region( ¤tWindow ); + } + catch ( QgsGrass::Exception &e ) + { + QgsGrass::warning( e ); return list; } @@ -536,11 +538,13 @@ bool QgsGrassMapcalc::inputRegion( struct Cell_head *window, QgsCoordinateRefere Q_UNUSED( all ); QgsDebugMsg( "entered." ); - if ( !QgsGrass::region( QgsGrass::getDefaultGisdbase(), - QgsGrass::getDefaultLocation(), - QgsGrass::getDefaultMapset(), window ) ) + try { - QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot get current region" ) ); + QgsGrass::region( window ); + } + catch ( QgsGrass::Exception &e ) + { + QgsGrass::warning( e ); return false; } diff --git a/src/plugins/grass/qgsgrassmodule.cpp b/src/plugins/grass/qgsgrassmodule.cpp index cd089834166..cc554fdecdf 100644 --- a/src/plugins/grass/qgsgrassmodule.cpp +++ b/src/plugins/grass/qgsgrassmodule.cpp @@ -970,11 +970,13 @@ QStringList QgsGrassModuleStandardOptions::checkRegion() QStringList list; struct Cell_head currentWindow; - if ( !QgsGrass::region( QgsGrass::getDefaultGisdbase(), - QgsGrass::getDefaultLocation(), - QgsGrass::getDefaultMapset(), ¤tWindow ) ) + try { - QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot get current region" ) ); + QgsGrass::region( ¤tWindow ); + } + catch ( QgsGrass::Exception &e ) + { + QgsGrass::warning( e ); return list; } @@ -1047,10 +1049,13 @@ bool QgsGrassModuleStandardOptions::inputRegion( struct Cell_head *window, QgsCo window->rows = ( int ) mCanvas->mapSettings().outputSize().height(); window->cols = ( int ) mCanvas->mapSettings().outputSize().width(); - char* err = G_adjust_Cell_head( window, 1, 1 ); - if ( err ) + try { - QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot set region" ) + QString( err ) ); + QgsGrass::adjustCellHead( window, 1, 1 ); + } + catch ( QgsGrass::Exception &e ) + { + QgsGrass::warning( e ); return false; } } @@ -1063,11 +1068,13 @@ bool QgsGrassModuleStandardOptions::inputRegion( struct Cell_head *window, QgsCo else { // Get current resolution - if ( !QgsGrass::region( QgsGrass::getDefaultGisdbase(), - QgsGrass::getDefaultLocation(), - QgsGrass::getDefaultMapset(), window ) ) + try { - QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot get current region" ) ); + QgsGrass::region( window ); + } + catch ( QgsGrass::Exception &e ) + { + QgsGrass::warning( e ); return false; } } @@ -1152,10 +1159,13 @@ bool QgsGrassModuleStandardOptions::inputRegion( struct Cell_head *window, QgsCo mapWindow.cols = provider->xSize(); mapWindow.rows = provider->ySize(); - char* err = G_adjust_Cell_head( &mapWindow, 1, 1 ); - if ( err ) + try { - QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot set region" ) + QString( err ) ); + QgsGrass::adjustCellHead( &mapWindow, 1, 1 ); + } + catch ( QgsGrass::Exception &e ) + { + QgsGrass::warning( e ); return false; } } diff --git a/src/plugins/grass/qgsgrassplugin.cpp b/src/plugins/grass/qgsgrassplugin.cpp index 37b1500c2ae..ccc32d95d8b 100644 --- a/src/plugins/grass/qgsgrassplugin.cpp +++ b/src/plugins/grass/qgsgrassplugin.cpp @@ -485,25 +485,14 @@ void QgsGrassPlugin::displayRegion() if ( !QgsGrass::activeMode() ) return; - QString gisdbase = QgsGrass::getDefaultGisdbase(); - QString location = QgsGrass::getDefaultLocation(); - QString mapset = QgsGrass::getDefaultMapset(); - - if ( gisdbase.isEmpty() || location.isEmpty() || mapset.isEmpty() ) - { - QMessageBox::warning( 0, tr( "Warning" ), - tr( "GISDBASE, LOCATION_NAME or MAPSET is not set, cannot display current region." ) ); - return; - } - - QgsGrass::setLocation( gisdbase, location ); - struct Cell_head window; - char *err = G__get_window( &window, ( char * ) "", ( char * ) "WIND", mapset.toLatin1().data() ); - - if ( err ) + try { - QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot read current region: %1" ).arg( err ) ); + QgsGrass::region( &window ); + } + catch ( QgsGrass::Exception &e ) + { + QgsGrass::warning( e ); return; } diff --git a/src/plugins/grass/qgsgrassregion.cpp b/src/plugins/grass/qgsgrassregion.cpp index 8d0f9de550e..8ba160b4e89 100644 --- a/src/plugins/grass/qgsgrassregion.cpp +++ b/src/plugins/grass/qgsgrassregion.cpp @@ -33,7 +33,7 @@ #include -/** map tool which uses rubber band for changing grass region */ +/** Map tool which uses rubber band for changing grass region */ QgsGrassRegionEdit::QgsGrassRegionEdit( QgsMapCanvas* canvas ) : QgsMapTool( canvas ) { @@ -232,22 +232,13 @@ QgsGrassRegion::QgsGrassRegion( QgsGrassPlugin *plugin, QgisInterface *iface, connect( mRadioGroup, SIGNAL( buttonClicked( int ) ), this, SLOT( radioChanged() ) ); // Set values to current region - QString gisdbase = QgsGrass::getDefaultGisdbase(); - QString location = QgsGrass::getDefaultLocation(); - QString mapset = QgsGrass::getDefaultMapset(); - - if ( gisdbase.isEmpty() || location.isEmpty() || mapset.isEmpty() ) + try { - QMessageBox::warning( 0, tr( "Warning" ), - tr( "GISDBASE, LOCATION_NAME or MAPSET is not set, cannot display current region." ) ); + QgsGrass::region( &mWindow ); } - - QgsGrass::setLocation( gisdbase, location ); - char *err = G__get_window( &mWindow, ( char * ) "", ( char * ) "WIND", mapset.toLatin1().data() ); - - if ( err ) + catch ( QgsGrass::Exception &e ) { - QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot read current region: %1" ).arg( QString::fromUtf8( err ) ) ); + QgsGrass::warning( e ); return; } diff --git a/src/providers/grass/qgsgrass.cpp b/src/providers/grass/qgsgrass.cpp index 3018942f2eb..eb775d5f0c6 100644 --- a/src/providers/grass/qgsgrass.cpp +++ b/src/providers/grass/qgsgrass.cpp @@ -1368,22 +1368,26 @@ bool GRASS_LIB_EXPORT QgsGrass::defaultRegion( const QString& gisdbase, const QS } } -bool GRASS_LIB_EXPORT QgsGrass::region( const QString& gisdbase, +void GRASS_LIB_EXPORT QgsGrass::region( const QString& gisdbase, const QString& location, const QString& mapset, - struct Cell_head *window ) + struct Cell_head *window ) throw( QgsGrass::Exception ) { QgsGrass::setLocation( gisdbase, location ); #if GRASS_VERSION_MAJOR < 7 if ( G__get_window( window, ( char * ) "", ( char * ) "WIND", mapset.toUtf8().data() ) ) { - return false; + throw QgsGrass::Exception( QObject::tr( "Cannot get current region" ) ); } #else - // TODO7: unfortunately G__get_window does not return error code and calls G_fatal_error on error - G__get_window( window, ( char * ) "", ( char * ) "WIND", mapset.toUtf8().data() ); + // In GRASS 7 G__get_window does not return error code and calls G_fatal_error on error + G_FATAL_THROW( G__get_window( window, ( char * ) "", ( char * ) "WIND", mapset.toUtf8().data() ) ); #endif - return true; +} + +void GRASS_LIB_EXPORT QgsGrass::region( struct Cell_head *window ) throw( QgsGrass::Exception ) +{ + region( getDefaultGisdbase(), getDefaultLocation(), getDefaultMapset(), window ); } bool GRASS_LIB_EXPORT QgsGrass::writeRegion( const QString& gisbase, @@ -1549,10 +1553,13 @@ bool GRASS_LIB_EXPORT QgsGrass::mapRegion( QgsGrassObject::Type type, QString gi else if ( type == QgsGrassObject::Vector ) { // Get current projection - if ( !region( gisdbase, location, mapset, window ) ) + try { - QMessageBox::warning( 0, QObject::tr( "Warning" ), - QObject::tr( "Cannot read vector map region" ) ); + QgsGrass::region( gisdbase, location, mapset, window ); + } + catch ( QgsGrass::Exception &e ) + { + QgsGrass::warning( e ); return false; } @@ -2166,6 +2173,19 @@ bool GRASS_LIB_EXPORT QgsGrass::isExternal( const QgsGrassObject & object ) return isExternal; } +void GRASS_LIB_EXPORT QgsGrass::adjustCellHead( struct Cell_head *cellhd, int row_flag, int col_flag ) throw( QgsGrass::Exception ) +{ +#if (GRASS_VERSION_MAJOR < 7) + char* err = G_adjust_Cell_head( cellhd, row_flag, col_flag ); + if ( err ) + { + throw QgsGrass::Exception( QObject::tr( "Cannot adjust region" ) + QString( err ) ); + } +#else + G_FATAL_THROW( G_adjust_Cell_head( cellhd, row_flag, col_flag ) ); +#endif +} + // GRASS version constants have been changed on 26.4.2007 // http://freegis.org/cgi-bin/viewcvs.cgi/grass6/include/version.h.in.diff?r1=1.4&r2=1.5 // The following lines workaround this change @@ -2248,6 +2268,11 @@ void GRASS_LIB_EXPORT QgsGrass::putEnv( QString name, QString value ) putenv( envChar ); } +void GRASS_LIB_EXPORT QgsGrass::warning( QgsGrass::Exception &e ) +{ + QMessageBox::warning( 0, QObject::tr( "Warning" ), e.what() ); +} + struct Map_info GRASS_LIB_EXPORT *QgsGrass::vectNewMapStruct() { // In OSGeo4W there is GRASS compiled by MinGW while QGIS compiled by MSVC, the compilers diff --git a/src/providers/grass/qgsgrass.h b/src/providers/grass/qgsgrass.h index 8d4152fbda8..494fa7d9eaa 100644 --- a/src/providers/grass/qgsgrass.h +++ b/src/providers/grass/qgsgrass.h @@ -49,13 +49,21 @@ class QgsRectangle; #define EXPAND(x) STR(x) #define GRASS_VERSION_RELEASE_STRING EXPAND( GRASS_VERSION_RELEASE ) +// try/catch like macros using setjmp #if (GRASS_VERSION_MAJOR < 7) -#define G_TRY try { if( !setjmp( QgsGrass::jumper ) ) +#define G_TRY try { if( !setjmp(QgsGrass::jumper) ) #else #define G_TRY try { if( !setjmp(*G_fatal_longjmp(1)) ) #endif #define G_CATCH else { throw QgsGrass::Exception( QgsGrass::errorMessage() ); } } catch +// Throw QgsGrass::Exception if G_fatal_error happens when calling F +#if (GRASS_VERSION_MAJOR < 7) +#define G_FATAL_THROW(F) if( !setjmp(QgsGrass::jumper) ) { F; } else { throw QgsGrass::Exception( QgsGrass::errorMessage() ); } +#else +#define G_FATAL_THROW(F) if( !setjmp(*G_fatal_longjmp(1)) ) { F; } else { throw QgsGrass::Exception( QgsGrass::errorMessage() ); } +#endif + #if GRASS_VERSION_MAJOR >= 7 #define G_available_mapsets G_get_available_mapsets #define G__mapset_permissions2 G_mapset_permissions2 @@ -272,9 +280,16 @@ class QgsGrass static GRASS_LIB_EXPORT bool defaultRegion( const QString& gisdbase, const QString& location, struct Cell_head *window ); - // ! Read current mapset region - static GRASS_LIB_EXPORT bool region( const QString& gisdbase, const QString& location, const QString& mapset, - struct Cell_head *window ); + /** Read mapset current region (WIND) + * @throws QgsGrass::Exception + */ + static GRASS_LIB_EXPORT void region( const QString& gisdbase, const QString& location, const QString& mapset, + struct Cell_head *window ) throw( QgsGrass::Exception ); + + /** Read default mapset current region (WIND) + * @throws QgsGrass::Exception + */ + static GRASS_LIB_EXPORT void region( struct Cell_head *window ) throw( QgsGrass::Exception ); // ! Write current mapset region static GRASS_LIB_EXPORT bool writeRegion( const QString& gisbase, const QString& location, const QString& mapset, @@ -398,6 +413,10 @@ class QgsGrass /** Returns true if object is link to external data (created by r.external) */ static GRASS_LIB_EXPORT bool isExternal( const QgsGrassObject & object ); + /** Adjust cell header, G_adjust_Cell_head wrapper + * @throws QgsGrass::Exception */ + static GRASS_LIB_EXPORT void adjustCellHead( struct Cell_head *cellhd, int row_flag, int col_flag ) throw( QgsGrass::Exception ); + //! Library version static GRASS_LIB_EXPORT int versionMajor(); static GRASS_LIB_EXPORT int versionMinor(); @@ -425,6 +444,9 @@ class QgsGrass return QgsApplication::libexecPath() + "grass/modules"; } + /** Show warning dialog with exception message */ + static GRASS_LIB_EXPORT void warning( QgsGrass::Exception &e ); + // Allocate struct Map_info static GRASS_LIB_EXPORT struct Map_info * vectNewMapStruct(); // Free struct Map_info diff --git a/tests/src/providers/grass/testqgsgrassprovider.cpp b/tests/src/providers/grass/testqgsgrassprovider.cpp index 35b76a79c02..3677ca48cfb 100644 --- a/tests/src/providers/grass/testqgsgrassprovider.cpp +++ b/tests/src/providers/grass/testqgsgrassprovider.cpp @@ -335,12 +335,18 @@ void TestQgsGrassProvider::region() reportHeader( "TestQgsGrassProvider::region" ); struct Cell_head window; struct Cell_head windowCopy; - bool ok = QgsGrass::region( mGisdbase, mLocation, "PERMANENT", &window ); - if ( !ok ) + bool ok = true; + try + { + QgsGrass::region( mGisdbase, mLocation, "PERMANENT", &window ); + } + catch ( QgsGrass::Exception &e ) { reportRow( "QgsGrass::region() failed" ); + ok = false; } - else + + if ( ok ) { QString expectedRegion = "proj:3;zone:0;north:90N;south:90S;east:180E;west:180W;cols:1000;rows:500;e-w resol:0:21:36;n-s resol:0:21:36;"; QString region = QgsGrass::regionString( &window );