Skip to content

Commit

Permalink
[GRASS] module input model file system watcher
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed Sep 9, 2015
1 parent c86dcd0 commit f9460f9
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 41 deletions.
221 changes: 183 additions & 38 deletions src/plugins/grass/qgsgrassmoduleinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,55 +57,207 @@ extern "C"
/**************************** QgsGrassModuleInputModel ****************************/
QgsGrassModuleInputModel::QgsGrassModuleInputModel( QObject *parent )
: QStandardItemModel( parent )
, mWatcher( 0 )
{
setColumnCount( 1 );
reload();

QString locationPath = QgsGrass::getDefaultLocationPath();
mWatcher = new QFileSystemWatcher( this );
mWatcher->addPath( locationPath );

// Watching all dirs in loacation because a dir may become a mapset later, when WIND is created

//QStringList mapsets = QgsGrass::mapsets( QgsGrass::getDefaultGisdbase(), QgsGrass::getDefaultLocation() );
QStringList dirNames = locationDirNames();
foreach ( QString dirName, dirNames )
{
QString dirPath = locationPath + "/" + dirName;
// Watch the dir in any case, WIND mabe created later
mWatcher->addPath( dirPath );

foreach ( QString watchedDir, watchedDirs() )
{
watch( dirPath + "/" + watchedDir );
}
}
connect( mWatcher, SIGNAL( directoryChanged( const QString & ) ), SLOT( onDirectoryChanged( const QString & ) ) );
}

void QgsGrassModuleInputModel::reload()
void QgsGrassModuleInputModel::onDirectoryChanged( const QString & path )
{
clear();
QStringList mapsets = QgsGrass::mapsets( QgsGrass::getDefaultGisdbase(), QgsGrass::getDefaultLocation() );
// Put current mapset on top
mapsets.removeOne( QgsGrass::getDefaultMapset() );
mapsets.prepend( QgsGrass::getDefaultMapset() );
QgsDebugMsg( "path = " + path );

foreach ( QString mapset, mapsets )
QString locationPath = QgsGrass::getDefaultLocationPath();
QDir parentDir( path );
parentDir.cdUp();
QString mapset;

if ( path == locationPath )
{
bool currentMapset = mapset == QgsGrass::getDefaultMapset();
QStandardItem *mapsetItem = new QStandardItem( mapset );
mapsetItem->setData( mapset, MapsetRole );
mapsetItem->setData( mapset, Qt::EditRole );
mapsetItem->setData( QgsGrassObject::None, TypeRole );
mapsetItem->setSelectable( false );
QgsDebugMsg( "location = " + path );
QStringList dirNames = locationDirNames();
//QStringList mapsets = QgsGrass::mapsets( QgsGrass::getDefaultGisdbase(), QgsGrass::getDefaultLocation() );

QList<QgsGrassObject::Type> types;
types << QgsGrassObject::Raster << QgsGrassObject::Vector;
foreach ( QgsGrassObject::Type type, types )
for ( int i = rowCount() - 1; i >= 0; i-- )
{
QStringList maps = QgsGrass::grassObjects( QgsGrass::getDefaultGisdbase() + "/" + QgsGrass::getDefaultLocation() + "/" + mapset, type );
foreach ( QString map, maps )
QString mapset = item( i )->text();
if ( !QgsGrass::isMapset( locationPath + "/" + mapset ) )
{
if ( map.startsWith( "qgis_import_tmp_" ) )
{
continue;
}
QString mapName = map;
// For now, for completer popup simplicity
// TODO: implement tree view in popup
if ( !currentMapset )
QgsDebugMsg( "removed mapset " + mapset );
removeRows( i, 1 );
}
}

foreach ( QString dirName, dirNames )
{
// Add to watcher in any case, either for WIND, cellhd or vector
QString dirPath = locationPath + "/" + dirName;
watch( dirPath );
if ( QgsGrass::isMapset( dirPath ) && findItems( dirName ).isEmpty() )
{
addMapset( dirName );
}
}
}
else if ( parentDir.canonicalPath() == QDir( locationPath ).canonicalPath() ) // mapset
{
QgsDebugMsg( "mapset = " + path );
QDir dir( path );
mapset = dir.dirName();
foreach ( QString watchedDir, watchedDirs() )
{
watch( path + "/" + watchedDir );
}
}
else // cellhd or vector dir
{
QgsDebugMsg( "cellhd/vector = " + path );
mapset = parentDir.dirName();
}
if ( !mapset.isEmpty() )
{
QList<QStandardItem *> items = findItems( mapset );
if ( items.size() == 1 )
{
refreshMapset( items[0], mapset );
}
}
}

void QgsGrassModuleInputModel::watch( const QString & path )
{
if ( !mWatcher->directories().contains( path ) && QFileInfo( path ).exists() )
{
mWatcher->addPath( path );
}
}

QStringList QgsGrassModuleInputModel::locationDirNames()
{
QString locationPath = QgsGrass::getDefaultLocationPath();
QDir locationDir( locationPath );
return locationDir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
}

void QgsGrassModuleInputModel::addMapset( const QString & mapset )
{
QgsDebugMsg( "mapset = " + mapset );


QStandardItem *mapsetItem = new QStandardItem( mapset );
mapsetItem->setData( mapset, MapsetRole );
mapsetItem->setData( mapset, Qt::EditRole );
mapsetItem->setData( QgsGrassObject::None, TypeRole );
mapsetItem->setSelectable( false );

refreshMapset( mapsetItem, mapset );

appendRow( mapsetItem );
}

void QgsGrassModuleInputModel::refreshMapset( QStandardItem *mapsetItem, const QString & mapset )
{
QgsDebugMsg( "mapset = " + mapset );
if ( !mapsetItem )
{
return;
}
bool currentMapset = mapset == QgsGrass::getDefaultMapset();
QList<QgsGrassObject::Type> types;
types << QgsGrassObject::Raster << QgsGrassObject::Vector;
foreach ( QgsGrassObject::Type type, types )
{
QStringList maps = QgsGrass::grassObjects( QgsGrass::getDefaultGisdbase() + "/" + QgsGrass::getDefaultLocation() + "/" + mapset, type );
QStringList mapNames;
foreach ( QString map, maps )
{
if ( map.startsWith( "qgis_import_tmp_" ) )
{
continue;
}
QString mapName = map;
// For now, for completer popup simplicity
// TODO: implement tree view in popup
if ( !currentMapset )
{
mapName += "@" + mapset;
}

bool found = false;
for ( int i = 0; i < mapsetItem->rowCount(); i++ )
{
QStandardItem * item = mapsetItem->child( i );
if ( item->text() == mapName && item->data( TypeRole ).toInt() == type )
{
mapName += "@" + mapset;
found = true;
break;
}
}
if ( !found )
{
QgsDebugMsg( "add map : " + mapName );
QStandardItem *mapItem = new QStandardItem( mapName );
mapItem->setData( mapName, Qt::EditRole );
mapItem->setData( map, MapRole );
mapItem->setData( mapset, MapsetRole );
mapItem->setData( type, TypeRole );
mapsetItem->appendRow( mapItem );
}
else
{
QgsDebugMsg( "map exists : " + mapName );
}
mapNames << mapName;
}

for ( int i = mapsetItem->rowCount() - 1; i >= 0; i-- )
{
if ( mapsetItem->child( i )->data( TypeRole ).toInt() != type )
{
continue;
}
QString mapName = mapsetItem->child( i )->text();
if ( !mapNames.contains( mapName ) )
{
QgsDebugMsg( "remove map : " + mapName );
mapsetItem->removeRows( i, 1 );
}
}
appendRow( mapsetItem );
}
}

void QgsGrassModuleInputModel::reload()
{
clear();
QStringList mapsets = QgsGrass::mapsets( QgsGrass::getDefaultGisdbase(), QgsGrass::getDefaultLocation() );
// Put current mapset on top
mapsets.removeOne( QgsGrass::getDefaultMapset() );
mapsets.prepend( QgsGrass::getDefaultMapset() );

foreach ( QString mapset, mapsets )
{
addMapset( mapset );
}
}

Expand Down Expand Up @@ -612,7 +764,7 @@ QgsGrassModuleInput::QgsGrassModuleInput( QgsGrassModule *module,

QVBoxLayout *layout = new QVBoxLayout( this );
// Map + region
QHBoxLayout *mapLayout = new QHBoxLayout( this );
QHBoxLayout *mapLayout = new QHBoxLayout();
layout->addLayout( mapLayout );

// Map input
Expand Down Expand Up @@ -651,7 +803,7 @@ QgsGrassModuleInput::QgsGrassModuleInput( QgsGrassModule *module,
// Vector layer + type
if ( mType == QgsGrassObject::Vector && !multiple() )
{
QHBoxLayout *layerLayout = new QHBoxLayout( this );
QHBoxLayout *layerLayout = new QHBoxLayout();
layout->addLayout( layerLayout );

mLayerLabel = new QLabel( tr( "Sublayer" ), this );
Expand All @@ -661,7 +813,7 @@ QgsGrassModuleInput::QgsGrassModuleInput( QgsGrassModule *module,
connect( mLayerComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( onLayerChanged() ) );
layerLayout->addWidget( mLayerComboBox );

QHBoxLayout *typeLayout = new QHBoxLayout( this );
QHBoxLayout *typeLayout = new QHBoxLayout();
layerLayout->addLayout( typeLayout );

// Vector types
Expand All @@ -686,13 +838,6 @@ QgsGrassModuleInput::QgsGrassModuleInput( QgsGrassModule *module,
layerLayout->addItem( new QSpacerItem( 10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
}


connect( QgsMapLayerRegistry::instance(), SIGNAL( layersAdded( QList<QgsMapLayer *> ) ),
this, SLOT( updateQgisLayers() ) );
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersRemoved( QStringList ) ),
this, SLOT( updateQgisLayers() ) );


if ( !mMapId.isEmpty() )
{
QgsGrassModuleParam *item = mModuleStandardOptions->item( mMapId );
Expand Down
20 changes: 17 additions & 3 deletions src/plugins/grass/qgsgrassmoduleinput.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <QComboBox>
#include <QCompleter>
#include <QFileSystemModel>
#include <QFileSystemWatcher>
#include <QGroupBox>
#include <QListView>
#include <QMap>
Expand Down Expand Up @@ -70,10 +71,20 @@ class QgsGrassModuleInputModel : public QStandardItemModel
/** Reload current mapset */
void reload();

signals:
void onDirectoryChanged( const QString & path );

protected:
signals:

private:
void addMapset( const QString & mapset );
void refreshMapset( QStandardItem *mapsetItem, const QString & mapset );
// Add to watched paths if exists and if not yet watched
void watch( const QString & path );
// mapset watched dirs
QStringList watchedDirs() { QStringList l; l << "cellhd" << "vector"; return l; }
// names of
QStringList locationDirNames();
QFileSystemWatcher *mWatcher;

};

Expand Down Expand Up @@ -171,11 +182,14 @@ class QgsGrassModuleInputComboBox : public QComboBox

class QgsGrassModuleInputSelectedDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit QgsGrassModuleInputSelectedDelegate( QObject *parent = 0 );

void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const override;

public slots:
void handlePressed( const QModelIndex &index );
void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const;

private:
mutable QModelIndex mPressedIndex;
Expand Down
10 changes: 10 additions & 0 deletions src/providers/grass/qgsgrass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,16 @@ QString QgsGrass::getDefaultLocation()
return defaultLocation;
}

QString QgsGrass::getDefaultLocationPath()
{
init();
if ( !active )
{
return QString();
}
return defaultGisdbase + "/" + defaultLocation;
}

QString QgsGrass::getDefaultMapset()
{
init();
Expand Down
3 changes: 3 additions & 0 deletions src/providers/grass/qgsgrass.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ class GRASS_LIB_EXPORT QgsGrass : public QObject
//! Get default LOCATION_NAME, returns LOCATION_NAME name or empty string if not in active mode
static QString getDefaultLocation();

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

//! Get default MAPSET, returns MAPSET name or empty string if not in active mode
static QString getDefaultMapset();

Expand Down

0 comments on commit f9460f9

Please sign in to comment.