From 8abe726c74c49a42e4cacc5ba5eadaa71253441a Mon Sep 17 00:00:00 2001 From: Radim Blazek Date: Thu, 21 May 2015 18:04:12 +0200 Subject: [PATCH] [GRASS] raster import: create link by r.external if crs are the same; link icon --- src/providers/grass/qgsgrass.cpp | 43 +++++++++--- src/providers/grass/qgsgrass.h | 3 + src/providers/grass/qgsgrassimport.cpp | 49 +++++++++++++ src/providers/grass/qgsgrassimport.h | 16 +++++ .../grass/qgsgrassprovidermodule.cpp | 69 ++++++++++++++----- src/providers/grass/qgsgrassprovidermodule.h | 9 +-- 6 files changed, 157 insertions(+), 32 deletions(-) diff --git a/src/providers/grass/qgsgrass.cpp b/src/providers/grass/qgsgrass.cpp index 78061a66b31..e8cd8de44d7 100644 --- a/src/providers/grass/qgsgrass.cpp +++ b/src/providers/grass/qgsgrass.cpp @@ -56,6 +56,11 @@ extern "C" #endif } +#if GRASS_VERSION_MAJOR >= 7 +#define G_get_gdal_link Rast_get_gdal_link +#define G_close_gdal_link Rast_close_gdal_link +#endif + #if !defined(GRASS_VERSION_MAJOR) || \ !defined(GRASS_VERSION_MINOR) || \ GRASS_VERSION_MAJOR<6 || \ @@ -139,7 +144,7 @@ QString QgsGrassObject::elementName() const return elementName( mType ); } -QString QgsGrassObject::elementName( Type type ) +QString GRASS_LIB_EXPORT QgsGrassObject::elementName( Type type ) { if ( type == Raster ) return "raster"; @@ -156,7 +161,7 @@ QString QgsGrassObject::dirName() const return dirName( mType ); } -QString QgsGrassObject::dirName( Type type ) +QString GRASS_LIB_EXPORT QgsGrassObject::dirName( Type type ) { if ( type == Raster ) return "cellhd"; @@ -187,7 +192,7 @@ bool QgsGrassObject::mapsetIdentical( const QgsGrassObject &other ) const return fi == otherFi; } -QRegExp QgsGrassObject::newNameRegExp( Type type ) +QRegExp GRASS_LIB_EXPORT QgsGrassObject::newNameRegExp( Type type ) { QRegExp rx; if ( type == QgsGrassObject::Vector ) @@ -1852,7 +1857,7 @@ QMap GRASS_LIB_EXPORT QgsGrass::query( QString gisdbase, QStri return result; } -void QgsGrass::renameObject( const QgsGrassObject & object, const QString& newName ) +void GRASS_LIB_EXPORT QgsGrass::renameObject( const QgsGrassObject & object, const QString& newName ) { QgsDebugMsg( "entered" ); QString cmd = "g.rename"; @@ -1865,7 +1870,7 @@ void QgsGrass::renameObject( const QgsGrassObject & object, const QString& newNa QgsGrass::runModule( object.gisdbase(), object.location(), object.mapset(), cmd, arguments, timeout, false ); } -void QgsGrass::copyObject( const QgsGrassObject & srcObject, const QgsGrassObject & destObject ) +void GRASS_LIB_EXPORT QgsGrass::copyObject( const QgsGrassObject & srcObject, const QgsGrassObject & destObject ) { QgsDebugMsg( "srcObject = " + srcObject.toString() ); QgsDebugMsg( "destObject = " + destObject.toString() ); @@ -1886,7 +1891,7 @@ void QgsGrass::copyObject( const QgsGrassObject & srcObject, const QgsGrassObjec QgsGrass::runModule( destObject.gisdbase(), destObject.location(), destObject.mapset(), cmd, arguments, timeout, false ); } -bool QgsGrass::deleteObject( const QgsGrassObject & object ) +bool GRASS_LIB_EXPORT QgsGrass::deleteObject( const QgsGrassObject & object ) { QgsDebugMsg( "entered" ); @@ -1921,7 +1926,7 @@ bool QgsGrass::deleteObject( const QgsGrassObject & object ) return true; } -bool QgsGrass::deleteObjectDialog( const QgsGrassObject & object ) +bool GRASS_LIB_EXPORT QgsGrass::deleteObjectDialog( const QgsGrassObject & object ) { QgsDebugMsg( "entered" ); @@ -1930,7 +1935,7 @@ bool QgsGrass::deleteObjectDialog( const QgsGrassObject & object ) QMessageBox::Yes | QMessageBox::No ) == QMessageBox::Yes; } -void QgsGrass::createTable( dbDriver *driver, const QString tableName, const QgsFields &fields ) +void GRASS_LIB_EXPORT QgsGrass::createTable( dbDriver *driver, const QString tableName, const QgsFields &fields ) { if ( !driver ) // should not happen { @@ -1989,8 +1994,8 @@ void QgsGrass::createTable( dbDriver *driver, const QString tableName, const Qgs } } -void QgsGrass::insertRow( dbDriver *driver, const QString tableName, - const QgsAttributes& attributes ) +void GRASS_LIB_EXPORT QgsGrass::insertRow( dbDriver *driver, const QString tableName, + const QgsAttributes& attributes ) { if ( !driver ) // should not happen { @@ -2052,6 +2057,24 @@ void QgsGrass::insertRow( dbDriver *driver, const QString tableName, } } +bool GRASS_LIB_EXPORT QgsGrass::isExternal( const QgsGrassObject & object ) +{ + if ( object.type() != QgsGrassObject::Raster ) + { + return false; + } + bool isExternal = false; + QgsGrass::setLocation( object.gisdbase(), object.location() ); + struct GDAL_link *gdal; + gdal = G_get_gdal_link( object.name().toUtf8().data(), object.mapset().toUtf8().data() ); + if ( gdal ) + { + isExternal = true; + G_close_gdal_link( gdal ); + } + return isExternal; +} + // 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 diff --git a/src/providers/grass/qgsgrass.h b/src/providers/grass/qgsgrass.h index 319613fdc9c..e73fbda9704 100644 --- a/src/providers/grass/qgsgrass.h +++ b/src/providers/grass/qgsgrass.h @@ -384,6 +384,9 @@ class QgsGrass static GRASS_LIB_EXPORT void insertRow( dbDriver *driver, const QString tableName, const QgsAttributes& attributes ); + /** Returns true if object is link to external data (created by r.external) */ + static GRASS_LIB_EXPORT bool isExternal( const QgsGrassObject & object ); + //! Library version static GRASS_LIB_EXPORT int versionMajor(); static GRASS_LIB_EXPORT int versionMinor(); diff --git a/src/providers/grass/qgsgrassimport.cpp b/src/providers/grass/qgsgrassimport.cpp index a53e0badc3c..2ef57b12ae1 100644 --- a/src/providers/grass/qgsgrassimport.cpp +++ b/src/providers/grass/qgsgrassimport.cpp @@ -495,3 +495,52 @@ QString QgsGrassCopy::srcDescription() const { return mSrcObject.toString(); } + +//------------------------------ QgsGrassExternal ------------------------------------ +QgsGrassExternal::QgsGrassExternal( const QString& gdalSource, const QgsGrassObject& destObject ) + : QgsGrassImport( destObject ) + , mSource( gdalSource ) +{ +} + +QgsGrassExternal::~QgsGrassExternal() +{ +} + +bool QgsGrassExternal::import() +{ + QgsDebugMsg( "entered" ); + + try + { + QString cmd = "r.external"; + QStringList arguments; + + if ( QFileInfo( mSource ).exists() ) + { + arguments << "input=" + mSource; + } + else + { + arguments << "source=" + mSource; + } + arguments << "output=" + mGrassObject.name(); + + // TODO: best timeout + int timeout = -1; + // throws QgsGrass::Exception + QgsGrass::runModule( mGrassObject.gisdbase(), mGrassObject.location(), mGrassObject.mapset(), cmd, arguments, timeout, false ); + } + catch ( QgsGrass::Exception &e ) + { + setError( e.what() ); + return false; + } + + return true; +} + +QString QgsGrassExternal::srcDescription() const +{ + return mSource; +} diff --git a/src/providers/grass/qgsgrassimport.h b/src/providers/grass/qgsgrassimport.h index 17be9f7ac60..829fcd6c3cb 100644 --- a/src/providers/grass/qgsgrassimport.h +++ b/src/providers/grass/qgsgrassimport.h @@ -113,4 +113,20 @@ class GRASS_LIB_EXPORT QgsGrassCopy : public QgsGrassImport }; +// Creates link to GDAL data source with r.external +class GRASS_LIB_EXPORT QgsGrassExternal : public QgsGrassImport +{ + Q_OBJECT + public: + // takes provider ownership + QgsGrassExternal( const QString& gdalSource, const QgsGrassObject& destObject ); + ~QgsGrassExternal(); + bool import() override; + QString srcDescription() const override; + + private: + QString mSource; + +}; + #endif // QGSGRASSIMPORT_H diff --git a/src/providers/grass/qgsgrassprovidermodule.cpp b/src/providers/grass/qgsgrassprovidermodule.cpp index 70c0a316339..6034544c254 100644 --- a/src/providers/grass/qgsgrassprovidermodule.cpp +++ b/src/providers/grass/qgsgrassprovidermodule.cpp @@ -159,7 +159,14 @@ QVector QgsGrassMapsetItem::createChildren() QgsDebugMsg( "uri = " + uri ); QgsGrassObject rasterObject( mGisdbase, mLocation, mName, name, QgsGrassObject::Raster ); - QgsGrassRasterItem *layer = new QgsGrassRasterItem( this, rasterObject, path, uri ); + bool isExternal = false; + if ( QgsGrass::isExternal( rasterObject ) ) + { + isExternal = true; + //rasterObject.setName( rasterObject.name() + " external" ); + } + QgsGrassRasterItem *layer = new QgsGrassRasterItem( this, rasterObject, path, uri, QgsGrass::isExternal( rasterObject ) ); + items.append( layer ); } @@ -348,24 +355,34 @@ bool QgsGrassMapsetItem::handleDrop( const QMimeData * data, Qt::DropAction ) QgsCoordinateReferenceSystem providerCrs = rasterProvider->crs(); QgsDebugMsg( "providerCrs = " + providerCrs.toWkt() ); QgsDebugMsg( "mapsetCrs = " + mapsetCrs.toWkt() ); - if ( providerCrs.isValid() && mapsetCrs.isValid() && providerCrs != mapsetCrs ) - { - QgsRasterProjector * projector = new QgsRasterProjector; - projector->setCRS( providerCrs, mapsetCrs ); - if ( useSrcRegion ) - { - projector->destExtentSize( rasterProvider->extent(), rasterProvider->xSize(), rasterProvider->ySize(), - newExtent, newXSize, newYSize ); - } - pipe->set( projector ); - } - QgsDebugMsg( "newExtent = " + newExtent.toString() ); - QgsDebugMsg( QString( "newXSize = %1 newYSize = %2" ).arg( newXSize ).arg( newYSize ) ); - - QString path = mPath + "/" + "raster" + "/" + u.name; QgsGrassObject rasterObject( mGisdbase, mLocation, mName, destName, QgsGrassObject::Raster ); - import = new QgsGrassRasterImport( pipe, rasterObject, newExtent, newXSize, newYSize ); // takes pipe ownership + if ( providerCrs.isValid() && mapsetCrs.isValid() && providerCrs == mapsetCrs + && rasterProvider->name() == "gdal" ) + { + import = new QgsGrassExternal( rasterProvider->dataSourceUri(), rasterObject ); + delete rasterProvider; + } + else + { + if ( providerCrs.isValid() && mapsetCrs.isValid() && providerCrs != mapsetCrs ) + { + QgsRasterProjector * projector = new QgsRasterProjector; + projector->setCRS( providerCrs, mapsetCrs ); + if ( useSrcRegion ) + { + projector->destExtentSize( rasterProvider->extent(), rasterProvider->xSize(), rasterProvider->ySize(), + newExtent, newXSize, newYSize ); + } + + pipe->set( projector ); + } + QgsDebugMsg( "newExtent = " + newExtent.toString() ); + QgsDebugMsg( QString( "newXSize = %1 newYSize = %2" ).arg( newXSize ).arg( newYSize ) ); + + //QString path = mPath + "/" + "raster" + "/" + u.name; + import = new QgsGrassRasterImport( pipe, rasterObject, newExtent, newXSize, newYSize ); // takes pipe ownership + } } else if ( u.layerType == "vector" ) { @@ -610,11 +627,27 @@ QString QgsGrassVectorLayerItem::layerName() const //----------------------- QgsGrassRasterItem ------------------------------ QgsGrassRasterItem::QgsGrassRasterItem( QgsDataItem* parent, QgsGrassObject grassObject, - QString path, QString uri ) + QString path, QString uri, bool isExternal ) : QgsGrassObjectItem( parent, grassObject, grassObject.name(), path, uri, QgsLayerItem::Raster, "grassraster" ) + , mExternal( isExternal ) { } +QIcon QgsGrassRasterItem::icon() +{ + static QIcon linkIcon; + + if ( mExternal ) + { + if ( linkIcon.isNull() ) + { + linkIcon = QgsApplication::getThemeIcon( "/mIconRasterLink.svg" ); + } + return linkIcon; + } + return QgsDataItem::icon(); +} + //----------------------- QgsGrassImportItem ------------------------------ QgsGrassImportItem::QgsGrassImportItem( QgsDataItem* parent, const QString& name, const QString& path, QgsGrassImport* import ) diff --git a/src/providers/grass/qgsgrassprovidermodule.h b/src/providers/grass/qgsgrassprovidermodule.h index 0a222c9db50..7cb6b392c7c 100644 --- a/src/providers/grass/qgsgrassprovidermodule.h +++ b/src/providers/grass/qgsgrassprovidermodule.h @@ -130,12 +130,13 @@ class QgsGrassRasterItem : public QgsGrassObjectItem Q_OBJECT public: QgsGrassRasterItem( QgsDataItem* parent, QgsGrassObject grassObject, - QString path, QString uri ); + QString path, QString uri, bool isExternal ); - //virtual QList actions() override; + virtual QIcon icon() override; - public slots: - //void deleteMap(); + private: + // is external created by r.external + bool mExternal; }; // item representing a layer being imported