Skip to content

Commit

Permalink
[GRASS] re-enabled module input cats selection in canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed Sep 25, 2015
1 parent 1da55fc commit 99bb8fd
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 41 deletions.
15 changes: 15 additions & 0 deletions src/plugins/grass/qgsgrassmoduleinput.cpp
Expand Up @@ -967,6 +967,21 @@ QStringList QgsGrassModuleInput::currentGeometryTypeNames()
return typeNames;
}

QStringList QgsGrassModuleInput::currentLayerCodes()
{
QStringList list;

if ( currentLayer() )
{
Q_FOREACH ( QString type, currentGeometryTypeNames() )
{
list << QString( "%1_%2" ).arg( currentLayer()->number() ).arg( type );
}
}
QgsDebugMsg( "list = " + list.join( "," ) );
return list;
}

void QgsGrassModuleInput::onChanged( const QString & text )
{
Q_UNUSED( text ) // silence warning
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/grass/qgsgrassmoduleinput.h
Expand Up @@ -265,6 +265,9 @@ class QgsGrassModuleInput : public QgsGrassModuleGroupBoxItem
void setGeometryTypeOption( const QString & optionName ) { mGeometryTypeOption = optionName; }
QString geometryTypeOption() const { return mGeometryTypeOption; }

// list of selected layers in <field>_<type> form, used by QgsGrassModuleSelection
QStringList currentLayerCodes();

public slots:
void onActivated( const QString & text );

Expand Down
212 changes: 173 additions & 39 deletions src/plugins/grass/qgsgrassmoduleparam.cpp
Expand Up @@ -28,6 +28,7 @@
#include "qgsvectorlayer.h"

#include "qgsgrass.h"
#include "qgsgrassfeatureiterator.h"
#include "qgsgrassmodule.h"
#include "qgsgrassmoduleinput.h"
#include "qgsgrassmoduleparam.h"
Expand Down Expand Up @@ -1207,73 +1208,206 @@ QgsGrassModuleSelection::QgsGrassModuleSelection(
if ( item )
{
mLayerInput = dynamic_cast<QgsGrassModuleInput *>( item );
connect( mLayerInput, SIGNAL( valueChanged() ), this, SLOT( updateSelection() ) );
connect( mLayerInput, SIGNAL( valueChanged() ), SLOT( onLayerChanged() ) );
}

QHBoxLayout *l = new QHBoxLayout( this );
mLineEdit = new QLineEdit( this );
//mLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
l->addWidget( mLineEdit );

mModeComboBox = new QComboBox( this );
//mComboBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
mModeComboBox->setSizeAdjustPolicy( QComboBox::AdjustToContents );
mModeComboBox->addItem( tr( "Manual entry" ), Manual );
connect( mModeComboBox, SIGNAL( currentIndexChanged( int ) ), SLOT( onModeChanged() ) );
l->addWidget( mModeComboBox );

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

// Fill in layer current fields
updateSelection();
onLayerChanged();
}

void QgsGrassModuleSelection::updateSelection()
void QgsGrassModuleSelection::onLayerChanged()
{
QgsDebugMsg( "entered" );

mLineEdit->setText( "" );
//QgsMapCanvas *canvas = mModule->qgisIface()->mapCanvas();
if ( mLayerInput == 0 )
if ( !mLayerInput )
{
return;
}

// TODO update to new input
#if 0
QgsMapLayer *layer = mLayerInput->currentLayer();
if ( !layer )
return;
QgsVectorLayer *vector = qobject_cast<QgsVectorLayer *>( layer );
QStringList layerIds;
// add new layers matching selected input layer if not yet present
Q_FOREACH ( QgsMapLayer *layer, QgsMapLayerRegistry::instance()->mapLayers().values() )
{
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
if ( vectorLayer && vectorLayer->providerType() == "grass" )
{
QString uri = vectorLayer->dataProvider()->dataSourceUri();
QgsDebugMsg( "uri = " + uri );
QString layerCode = uri.split( "/" ).last();
if ( mLayerInput->currentLayerCodes().contains( layerCode ) )
{
// Qt::UserRole+1 may be also uri (AddLayer) but hardly matching layer id
if ( mModeComboBox->findData( vectorLayer->id(), Qt::UserRole + 1 ) == -1 )
{
mModeComboBox->addItem( vectorLayer->name() + " " + tr( "layer selection" ), Layer );
mModeComboBox->setItemData( mModeComboBox->count() - 1, vectorLayer->id(), Qt::UserRole + 1 );
}
layerIds << vectorLayer->id();
}
}
}
// remove layers no more present
for ( int i = mModeComboBox->count() - 1; i >= 0; i-- )
{
if ( mModeComboBox->itemData( i ).toInt() != Layer )
{
continue;
}
QString id = mModeComboBox->itemData( i, Qt::UserRole + 1 ).toString();
if ( !layerIds.contains( id ) )
{
mModeComboBox->removeItem( i );
}
}

QgsGrassProvider *provider = ( QgsGrassProvider * ) vector->dataProvider();
QgsAttributeList allAttributes = provider->attributeIndexes();
const QgsFeatureIds& selected = vector->selectedFeaturesIds();
int keyField = provider->keyField();
// clear old AddLayer
for ( int i = mModeComboBox->count() - 1; i >= 0; i-- )
{
if ( mModeComboBox->itemData( i ).toInt() == AddLayer )
{
mModeComboBox->removeItem( i );
}
}

if ( keyField < 0 )
return;
if ( layerIds.size() == 0 ) // non of selected layer is in canvas
{
Q_FOREACH ( QString layerCode, mLayerInput->currentLayerCodes() )
{
if ( mLayerInput->currentLayer() )
{
mModeComboBox->addItem( tr( "Add to canvas layer" ) + " " + mLayerInput->currentMap() + " " + layerCode, AddLayer );
QgsGrassObject grassObject = mLayerInput->currentLayer()->grassObject();
QString uri = grassObject.mapsetPath() + "/" + grassObject.name() + "/" + layerCode;
QgsDebugMsg( "uri = " + uri );
// Qt::UserRole+1 may be also layer id (Layer) but hardly matching layer uri
if ( mModeComboBox->findData( uri, Qt::UserRole + 1 ) == -1 )
{
mModeComboBox->setItemData( mModeComboBox->count() - 1, uri, Qt::UserRole + 1 );
QString name = grassObject.name() + " " + layerCode;
mModeComboBox->setItemData( mModeComboBox->count() - 1, name, Qt::UserRole + 2 );
}
}
}
}
}

QString cats;
QgsFeatureIterator fi = provider->getFeatures( QgsFeatureRequest() );
QgsFeature feature;
QString QgsGrassModuleSelection::currentSelectionLayerId()
{
QString id;
int index = mModeComboBox->currentIndex();
if ( mModeComboBox->itemData( index ).toInt() == Layer )
{
id = mModeComboBox->itemData( index, Qt::UserRole + 1 ).toString();
}
return id;
}

int i = 0;
while ( fi.nextFeature( feature ) )
QgsVectorLayer * QgsGrassModuleSelection::currentSelectionLayer()
{
QString id = currentSelectionLayerId();
if ( id.isEmpty() )
{
if ( !selected.contains( feature.id() ) )
continue;
return 0;
}
QgsMapLayer *layer = QgsMapLayerRegistry::instance()->mapLayer( id );
return qobject_cast<QgsVectorLayer *>( layer );
}

QgsAttributes attr = feature.attributes();
if ( attr.size() > keyField )
void QgsGrassModuleSelection::onModeChanged()
{
QgsDebugMsg( "entered" );
int index = mModeComboBox->currentIndex();
if ( mModeComboBox->itemData( index ).toInt() == AddLayer )
{
QString uri = mModeComboBox->itemData( index, Qt::UserRole + 1 ).toString();
QString name = mModeComboBox->itemData( index, Qt::UserRole + 2 ).toString();
QgsDebugMsg( "uri = " + uri );

QgsVectorLayer *layer = new QgsVectorLayer( uri, name, "grass" );
QgsMapLayerRegistry::instance()->addMapLayer( layer );
onLayerChanged(); // update with added layer
}
else if ( mModeComboBox->itemData( index ).toInt() == Layer )
{
QString id = mModeComboBox->itemData( index, Qt::UserRole + 1 ).toString();
QgsMapLayer *layer = QgsMapLayerRegistry::instance()->mapLayer( id );
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
if ( vectorLayer )
{
if ( i > 0 )
cats.append( "," );
cats.append( attr[keyField].toString() );
i++;
onLayerSelectionChanged();
connect( vectorLayer, SIGNAL( selectionChanged( const QgsFeatureIds, const QgsFeatureIds, const bool ) ),
SLOT( onLayerSelectionChanged() ) );
}
}
if ( mVectorLayer != vector )
}

void QgsGrassModuleSelection::onLayerSelectionChanged()
{
QgsDebugMsg( "entered" );
mLineEdit->clear();

QgsVectorLayer *vectorLayer = currentSelectionLayer();
if ( !vectorLayer )
{
return;
}

QList<int> cats;
Q_FOREACH ( QgsFeatureId fid, vectorLayer->selectedFeaturesIds() )
{
cats << QgsGrassFeatureIterator::catFromFid( fid );
}
qSort( cats );
QString list;
// make ranges of cats
int last = -1;
int range = false;
Q_FOREACH ( int cat, cats )
{
if ( mVectorLayer )
if ( cat == 0 )
{
disconnect( mVectorLayer, SIGNAL( selectionChanged() ), this, SLOT( updateSelection() ) );
continue;
}

connect( vector, SIGNAL( selectionChanged() ), this, SLOT( updateSelection() ) );
mVectorLayer = vector;
if ( last == cat - 1 ) // begin or continue range
{
range = true;
}
else if ( range ) // close range and next cat
{
list += QString( "-%1,%2" ).arg( last ).arg( cat );
range = false;
}
else // next cat
{
if ( !list.isEmpty() )
{
list += ",";
}
list += QString::number( cat );
}
last = cat;
}
if ( range )
{
list += QString( "-%1" ).arg( last );
}

mLineEdit->setText( cats );
#endif
mLineEdit->setText( list );
}

QStringList QgsGrassModuleSelection::options()
Expand Down
26 changes: 25 additions & 1 deletion src/plugins/grass/qgsgrassmoduleparam.h
Expand Up @@ -25,6 +25,7 @@
#include <QVBoxLayout>

#include "qgis.h"
#include "qgsfeature.h"
#include "qgsfield.h"
#include "qgscoordinatereferencesystem.h"

Expand Down Expand Up @@ -469,6 +470,14 @@ class QgsGrassModuleSelection : public QgsGrassModuleGroupBoxItem
Q_OBJECT

public:
enum Mode
{
Manual, // manual entry
Layer, // current selection of select
AddLayer, // add current layer to canvas
Expression // expression builder - possible?
};

/** \brief Constructor
* \param qdesc option element in QGIS module description XML file
* \param gdesc GRASS module XML description file
Expand All @@ -487,10 +496,22 @@ class QgsGrassModuleSelection : public QgsGrassModuleGroupBoxItem
virtual QStringList options() override;

public slots:
// selected input layer changed
void onLayerChanged();

void onModeChanged();

//! Set selection list to currently selected features
void updateSelection();
void onLayerSelectionChanged();


private:
// currently selected map canvas layer id or empty string
QString currentSelectionLayerId();

// currently selected map canvas layer or null
QgsVectorLayer * currentSelectionLayer();

// Module options
QgsGrassModuleStandardOptions *mModuleStandardOptions;

Expand All @@ -508,6 +529,9 @@ class QgsGrassModuleSelection : public QgsGrassModuleGroupBoxItem

//! Line
QLineEdit *mLineEdit;

// selection mode
QComboBox *mModeComboBox;
};

/*********************** QgsGrassModuleFile **********************/
Expand Down
12 changes: 11 additions & 1 deletion src/providers/grass/qgsgrassprovider.cpp
Expand Up @@ -216,6 +216,11 @@ QgsGrassProvider::QgsGrassProvider( QString uri )
QgsDebugMsg( QString( "Cannot open map : %1" ).arg( myURI ) );
return;
}
if ( !mLayer->map() || !mLayer->map()->isValid() ) // may happen
{
QgsDebugMsg( QString( "GRASS map is not valid : %1" ).arg( myURI ) );
return;
}

mLayer = vectorMap->openLayer( mLayerField );

Expand All @@ -225,10 +230,15 @@ QgsGrassProvider::QgsGrassProvider( QString uri )
return;
}

if ( !mLayer->map()->map() ) // should not happen
{
QgsDebugMsg( QString( "GRASS map is null : %1" ).arg( myURI ) );
return;
}

loadMapInfo();
setTopoFields();


mLayer->map()->version();

connect( mLayer->map(), SIGNAL( dataChanged() ), SLOT( onDataChanged() ) );
Expand Down
2 changes: 2 additions & 0 deletions src/providers/grass/qgsgrassvector.h
Expand Up @@ -34,6 +34,8 @@ class GRASS_LIB_EXPORT QgsGrassVectorLayer : public QObject

~QgsGrassVectorLayer();

QgsGrassObject grassObject() const { return mGrassObject; }

/** Layer number (field) */
int number() { return mNumber; }

Expand Down

0 comments on commit 99bb8fd

Please sign in to comment.