Skip to content

Commit

Permalink
[GRASS] restrict module input by SEARCH_PATH
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed Oct 8, 2015
1 parent 814e848 commit 74f8d47
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 3 deletions.
27 changes: 25 additions & 2 deletions src/plugins/grass/qgsgrassmoduleinput.cpp
Expand Up @@ -67,6 +67,8 @@ QgsGrassModuleInputModel::QgsGrassModuleInputModel( QObject *parent )

connect( QgsGrass::instance(), SIGNAL( mapsetChanged() ), SLOT( onMapsetChanged() ) );

connect( QgsGrass::instance(), SIGNAL( mapsetSearchPathChanged() ), SLOT( onMapsetSearchPathChanged() ) );

reload();
}

Expand Down Expand Up @@ -268,6 +270,12 @@ void QgsGrassModuleInputModel::onMapsetChanged()
}
}

void QgsGrassModuleInputModel::onMapsetSearchPathChanged()
{
QgsDebugMsg( "entered" );
emit dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ) );
}

QgsGrassModuleInputModel::~QgsGrassModuleInputModel()
{

Expand Down Expand Up @@ -317,8 +325,23 @@ bool QgsGrassModuleInputProxy::filterAcceptsRow( int sourceRow, const QModelInde

QgsDebugMsg( QString( "mType = %1 item type = %2" ).arg( mType ).arg( sourceModel()->data( sourceIndex, QgsGrassModuleInputModel::TypeRole ).toInt() ) );
QgsGrassObject::Type itemType = ( QgsGrassObject::Type )( sourceModel()->data( sourceIndex, QgsGrassModuleInputModel::TypeRole ).toInt() );
// TODO: filter out mapsets without given type? May be confusing.
return itemType == QgsGrassObject::Mapset || mType == itemType;

if ( itemType == QgsGrassObject::Mapset )
{
// TODO: filter out mapsets which have no map of given type? May be confusin if user does not see existing mapset in the tree.
QString mapset = sourceModel()->data( sourceIndex, QgsGrassModuleInputModel::MapsetRole ).toString();
if ( QgsGrass::instance()->isMapsetInSearchPath( mapset ) )
{
return true;
}
else
{
QgsDebugMsg( "mapset " + mapset + " is not in search path" );
return false;
}
}

return mType == itemType;
}

bool QgsGrassModuleInputProxy::lessThan( const QModelIndex & left, const QModelIndex & right ) const
Expand Down
1 change: 1 addition & 0 deletions src/plugins/grass/qgsgrassmoduleinput.h
Expand Up @@ -77,6 +77,7 @@ class QgsGrassModuleInputModel : public QStandardItemModel
void onMapsetChanged();

void onDirectoryChanged( const QString & path );
void onMapsetSearchPathChanged();

private:
void addMapset( const QString & mapset );
Expand Down
125 changes: 124 additions & 1 deletion src/providers/grass/qgsgrass.cpp
Expand Up @@ -262,6 +262,11 @@ bool QgsGrassObject::operator==( const QgsGrassObject& other ) const
&& mName == other.mName && mType == other.mType;
}

QgsGrass::QgsGrass()
: mMapsetSearchPathWatcher( 0 )
{
}

QString QgsGrass::pathSeparator()
{
#ifdef Q_OS_WIN
Expand Down Expand Up @@ -316,8 +321,8 @@ bool QgsGrass::init( void )
lock();
QgsDebugMsg( "do init" );

// Is it active mode ?
active = false;
// Is it active mode ?
if ( getenv( "GISRC" ) )
{
G_TRY
Expand Down Expand Up @@ -352,6 +357,12 @@ bool QgsGrass::init( void )
return false;
}

if ( active )
{
QgsGrass::instance()->loadMapsetSearchPath(); // must be after G_no_gisinit()
QgsGrass::instance()->setMapsetSearchPathWatcher();
}

// I think that mask should not be used in QGIS as it can only confuses people,
// anyway, I don't think anybody is using MASK
// TODO7: Rast_suppress_masking (see G_suppress_masking() macro above) needs MAPSET
Expand Down Expand Up @@ -545,6 +556,11 @@ QString QgsGrass::getDefaultMapset()
return defaultMapset;
}

QString QgsGrass::getDefaultMapsetPath()
{
return getDefaultLocationPath() + "/" + defaultMapset;
}

void QgsGrass::setLocation( QString gisdbase, QString location )
{
QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) );
Expand Down Expand Up @@ -601,6 +617,109 @@ void QgsGrass::setMapset( QgsGrassObject grassObject )
setMapset( grassObject.gisdbase(), grassObject.location(), grassObject.mapset() );
}

bool QgsGrass::isMapsetInSearchPath( QString mapset )
{
return mMapsetSearchPath.contains( mapset );
}

void QgsGrass::loadMapsetSearchPath()
{
QgsDebugMsg( "entered" );
// do not lock, it is called from locked function
QStringList oldMapsetSearchPath = mMapsetSearchPath;
mMapsetSearchPath.clear();
if ( !activeMode() )
{
QgsDebugMsg( "not active" );
emit mapsetSearchPathChanged();
return;
}
G_TRY
{
QgsGrass::setMapset( getDefaultGisdbase(), getDefaultLocation(), getDefaultMapset() );
const char *mapset = 0;
#if GRASS_VERSION_MAJOR >= 7
G_reset_mapsets();
for ( int i = 0; ( mapset = G_get_mapset_name( i ) ); i++ )
#else
int result = G_reset_mapsets();
Q_UNUSED( result );
for ( int i = 0; ( mapset = G__mapset_name( i ) ); i++ )
#endif
{
QgsDebugMsg( QString( "mapset = %1" ).arg( mapset ) );
if ( G_is_mapset_in_search_path( mapset ) )
{
mMapsetSearchPath << mapset;
}
}
}
G_CATCH( QgsGrass::Exception &e )
{
QgsDebugMsg( "cannot load mapset search path: " + QString( e.what() ) );
}
QgsDebugMsg( "mMapsetSearchPath = " + mMapsetSearchPath.join( "," ) );
if ( mMapsetSearchPath != oldMapsetSearchPath )
{
emit mapsetSearchPathChanged();
}
}

void QgsGrass::setMapsetSearchPathWatcher()
{
QgsDebugMsg( "etered" );
if ( mMapsetSearchPathWatcher )
{
delete mMapsetSearchPathWatcher;
mMapsetSearchPathWatcher = 0;
}
if ( !activeMode() )
{
return;
}
mMapsetSearchPathWatcher = new QFileSystemWatcher( this );

QString searchFilePath = getDefaultMapsetPath() + "/SEARCH_PATH";

if ( QFileInfo( searchFilePath ).exists() )
{
QgsDebugMsg( "add watcher on SEARCH_PATH file " + searchFilePath );
mMapsetSearchPathWatcher->addPath( searchFilePath );
connect( mMapsetSearchPathWatcher, SIGNAL( fileChanged( const QString & ) ), SLOT( onSearchPathFileChanged( const QString & ) ) );
}
else
{
QgsDebugMsg( "add watcher on mapset " + getDefaultMapsetPath() );
mMapsetSearchPathWatcher->addPath( getDefaultMapsetPath() );
connect( mMapsetSearchPathWatcher, SIGNAL( directoryChanged( const QString & ) ), SLOT( onSearchPathFileChanged( const QString & ) ) );
}
}

void QgsGrass::onSearchPathFileChanged( const QString & path )
{
QgsDebugMsg( "path = " + path );
QString searchFilePath = getDefaultMapsetPath() + "/SEARCH_PATH";
if ( path == searchFilePath )
{
// changed or removed
loadMapsetSearchPath();
if ( !QFileInfo( searchFilePath ).exists() ) // removed
{
// reset watcher to mapset
setMapsetSearchPathWatcher();
}
}
else
{
// mapset directory changed
if ( QFileInfo( searchFilePath ).exists() ) // search path file added
{
loadMapsetSearchPath();
setMapsetSearchPathWatcher();
}
}
}

jmp_buf QgsGrass::jumper;

bool QgsGrass::mNonInitializable = false;
Expand Down Expand Up @@ -860,6 +979,9 @@ QString QgsGrass::openMapset( const QString& gisdbase,

active = true;

QgsGrass::instance()->loadMapsetSearchPath();
QgsGrass::instance()->setMapsetSearchPathWatcher();

// closeMapset() added at the beginning
#if 0
#ifndef Q_OS_WIN
Expand Down Expand Up @@ -936,6 +1058,7 @@ QString QgsGrass::closeMapset()
}
}

QgsGrass::instance()->setMapsetSearchPathWatcher(); // unset watcher
emit QgsGrass::instance()->mapsetChanged();
return QString::null;
}
Expand Down
23 changes: 23 additions & 0 deletions src/providers/grass/qgsgrass.h
Expand Up @@ -36,6 +36,7 @@ extern "C"
#include "qgsfeature.h"
#include "qgsfield.h"
#include <qgsrectangle.h>
#include <QFileSystemWatcher>
#include <QProcess>
#include <QString>
#include <QMap>
Expand Down Expand Up @@ -172,6 +173,8 @@ class GRASS_LIB_EXPORT QgsGrass : public QObject
int red1, red2, green1, green2, blue1, blue2;
};

QgsGrass();

/** Get singleton instance of this class. Used as signals proxy between provider and plugin. */
static QgsGrass* instance();

Expand All @@ -198,6 +201,9 @@ class GRASS_LIB_EXPORT QgsGrass : public QObject
//! Get default MAPSET, returns MAPSET name or empty string if not in active mode
static QString getDefaultMapset();

//! Get default path to MAPSET (gisdbase/location/mapset) or empty string if not in active mode
static QString getDefaultMapsetPath();

//! Init or reset GRASS library
/*!
\param gisdbase full path to GRASS GISDBASE.
Expand All @@ -217,6 +223,10 @@ class GRASS_LIB_EXPORT QgsGrass : public QObject
* @param grassObject */
static void setMapset( QgsGrassObject grassObject );

/** Check if mapset is in search pat set by g.mapsets
* @return true if in search path */
bool isMapsetInSearchPath( QString mapset );

//! Error codes returned by error()
enum GERROR
{
Expand Down Expand Up @@ -592,13 +602,22 @@ class GRASS_LIB_EXPORT QgsGrass : public QObject

void openOptions();

/** Read mapset search path from GRASS location */
void loadMapsetSearchPath();

void setMapsetSearchPathWatcher();
void onSearchPathFileChanged( const QString & path );

signals:
/** Signal emitted when user changed GISBASE */
void gisbaseChanged();

/** Signal emitted after mapset was opened */
void mapsetChanged();

/** Signal emited when mapset search path changed (SEARCH_PATH file changed and it was loaded to mMapsetSearchPath) */
void mapsetSearchPathChanged();

/** Emitted when path to modules config dir changed */
void modulesConfigChanged();

Expand Down Expand Up @@ -627,6 +646,10 @@ class GRASS_LIB_EXPORT QgsGrass : public QObject
static QString defaultLocation;
static QString defaultMapset;

// Mapsets in current search path
QStringList mMapsetSearchPath;
QFileSystemWatcher *mMapsetSearchPathWatcher;

/* last error in GRASS libraries */
static GERROR lastError; // static, because used in constructor
static QString error_message;
Expand Down

0 comments on commit 74f8d47

Please sign in to comment.