Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[processing] Fix incorrect OGR warnings when loading raster layer results #7608

Merged
merged 1 commit into from
Aug 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Details for layers to load into projects.
%End
public:

LayerDetails( const QString &name, QgsProject *project, const QString &outputName = QString() );
LayerDetails( const QString &name, QgsProject *project, const QString &outputName = QString(), QgsProcessingUtils::LayerHint layerTypeHint = QgsProcessingUtils::UnknownType );
%Docstring
Constructor for LayerDetails.
%End
Expand All @@ -140,6 +140,8 @@ Default constructor

QString outputName;

QgsProcessingUtils::LayerHint layerTypeHint;

QgsProcessingLayerPostProcessorInterface *postProcessor() const;
%Docstring
Layer post-processor. May be None if no post-processing is required.
Expand Down
11 changes: 10 additions & 1 deletion python/core/auto_generated/processing/qgsprocessingutils.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,14 @@ value.
.. seealso:: :py:func:`compatibleVectorLayers`
%End

static QgsMapLayer *mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers = true );
enum LayerHint
{
UnknownType,
Vector,
Raster,
};

static QgsMapLayer *mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers = true, LayerHint typeHint = UnknownType );
%Docstring
Interprets a string as a map layer within the supplied ``context``.

Expand All @@ -81,6 +88,8 @@ within the context's project or temporary layer store then this layer will be re
If the string is a file path and ``allowLoadingNewLayers`` is true, then the layer at this
file path will be loaded and added to the context's temporary layer store.
Ownership of the layer remains with the ``context`` or the context's current project.

The ``typeHint`` can be used to dictate the type of map layer expected.
%End

static QgsProcessingFeatureSource *variantToSource( const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue = QVariant() ) /Factory/;
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/gui/Postprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def handleAlgorithmResults(alg, context, feedback=None, showResults=True):
feedback.setProgress(100 * i / float(len(context.layersToLoadOnCompletion())))

try:
layer = QgsProcessingUtils.mapLayerFromString(l, context)
layer = QgsProcessingUtils.mapLayerFromString(l, context, typeHint=details.layerTypeHint)
if layer is not None:
if not ProcessingConfig.getSetting(ProcessingConfig.USE_FILENAME_AS_LAYER_NAME):
layer.setName(details.name)
Expand Down
2 changes: 1 addition & 1 deletion src/core/processing/models/qgsprocessingmodelalgorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> QgsProcessingMode
}
if ( !featureSource )
{
if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( value.toString(), context ) ) )
if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( value.toString(), context, true, QgsProcessingUtils::Vector ) ) )
featureSource = vl;
}

Expand Down
11 changes: 10 additions & 1 deletion src/core/processing/qgsprocessingcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "qgsmaplayerlistutils.h"
#include "qgsexception.h"
#include "qgsprocessingfeedback.h"
#include "qgsprocessingutils.h"

class QgsProcessingLayerPostProcessorInterface;

Expand Down Expand Up @@ -169,9 +170,10 @@ class CORE_EXPORT QgsProcessingContext
/**
* Constructor for LayerDetails.
*/
LayerDetails( const QString &name, QgsProject *project, const QString &outputName = QString() )
LayerDetails( const QString &name, QgsProject *project, const QString &outputName = QString(), QgsProcessingUtils::LayerHint layerTypeHint = QgsProcessingUtils::UnknownType )
: name( name )
, outputName( outputName )
, layerTypeHint( layerTypeHint )
, project( project )
{}

Expand All @@ -184,6 +186,13 @@ class CORE_EXPORT QgsProcessingContext
//! Associated output name from algorithm which generated the layer.
QString outputName;

/**
* Layer type hint.
*
* \since QGIS 3.4
*/
QgsProcessingUtils::LayerHint layerTypeHint = QgsProcessingUtils::UnknownType;

/**
* Layer post-processor. May be nullptr if no post-processing is required.
* \see setPostProcessor()
Expand Down
25 changes: 16 additions & 9 deletions src/core/processing/qgsprocessingparameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ int QgsProcessingParameters::parameterAsInt( const QgsProcessingParameterDefinit
//double too large to fit in int
return 0;
}
return std::round( dbl );
return static_cast< int >( std::round( dbl ) );
}

return val.toInt();
Expand Down Expand Up @@ -290,7 +290,7 @@ QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingPar
QString outputName;
if ( definition )
outputName = definition->name();
context.addLayerToLoadOnCompletion( destinationIdentifier, QgsProcessingContext::LayerDetails( destName, destinationProject, outputName ) );
context.addLayerToLoadOnCompletion( destinationIdentifier, QgsProcessingContext::LayerDetails( destName, destinationProject, outputName, QgsProcessingUtils::Vector ) );
}

return sink.release();
Expand Down Expand Up @@ -363,7 +363,7 @@ QString QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( const Qgs
if ( layerRef.isEmpty() )
return QString();

vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context ) );
vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context, true, QgsProcessingUtils::Vector ) );
}
}

Expand Down Expand Up @@ -462,7 +462,14 @@ QString QgsProcessingParameters::parameterAsOutputLayer( const QgsProcessingPara
}
if ( definition )
outputName = definition->name();
context.addLayerToLoadOnCompletion( dest, QgsProcessingContext::LayerDetails( destName, destinationProject, outputName ) );

QgsProcessingUtils::LayerHint layerTypeHint = QgsProcessingUtils::UnknownType;
if ( definition->type() == QgsProcessingParameterVectorDestination::typeName() )
layerTypeHint = QgsProcessingUtils::Vector;
else if ( definition->type() == QgsProcessingParameterRasterDestination::typeName() )
layerTypeHint = QgsProcessingUtils::Raster;

context.addLayerToLoadOnCompletion( dest, QgsProcessingContext::LayerDetails( destName, destinationProject, outputName, layerTypeHint ) );
}

return dest;
Expand Down Expand Up @@ -2450,7 +2457,7 @@ bool QgsProcessingParameterRasterLayer::checkValueIsAcceptable( const QVariant &
}

// try to load as layer
if ( QgsProcessingUtils::mapLayerFromString( input.toString(), *context ) )
if ( QgsProcessingUtils::mapLayerFromString( input.toString(), *context, true, QgsProcessingUtils::Raster ) )
return true;

return false;
Expand Down Expand Up @@ -2849,7 +2856,7 @@ bool QgsProcessingParameterVectorLayer::checkValueIsAcceptable( const QVariant &
}

// try to load as layer
if ( QgsProcessingUtils::mapLayerFromString( var.toString(), *context ) )
if ( QgsProcessingUtils::mapLayerFromString( var.toString(), *context, true, QgsProcessingUtils::Vector ) )
return true;

return false;
Expand Down Expand Up @@ -3180,7 +3187,7 @@ bool QgsProcessingParameterFeatureSource::checkValueIsAcceptable( const QVariant
}

// try to load as layer
if ( QgsProcessingUtils::mapLayerFromString( var.toString(), *context ) )
if ( QgsProcessingUtils::mapLayerFromString( var.toString(), *context, true, QgsProcessingUtils::Vector ) )
return true;

return false;
Expand All @@ -3207,7 +3214,7 @@ QString QgsProcessingParameterFeatureSource::valueAsPythonString( const QVariant
{
QString layerString = fromVar.source.staticValue().toString();
// prefer to use layer source instead of id if possible (since it's persistent)
if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProcessingUtils::mapLayerFromString( layerString, context ) ) )
if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProcessingUtils::mapLayerFromString( layerString, context, true, QgsProcessingUtils::Vector ) ) )
layerString = layer->source();
return QgsProcessingUtils::stringToPythonLiteral( layerString );
}
Expand All @@ -3232,7 +3239,7 @@ QString QgsProcessingParameterFeatureSource::valueAsPythonString( const QVariant
QString layerString = value.toString();

// prefer to use layer source if possible (since it's persistent)
if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProcessingUtils::mapLayerFromString( layerString, context ) ) )
if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( QgsProcessingUtils::mapLayerFromString( layerString, context, true, QgsProcessingUtils::Vector ) ) )
layerString = layer->source();

return QgsProcessingUtils::stringToPythonLiteral( layerString );
Expand Down
68 changes: 45 additions & 23 deletions src/core/processing/qgsprocessingutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ QList<QgsMapLayer *> QgsProcessingUtils::compatibleLayers( QgsProject *project,
return layers;
}

QgsMapLayer *QgsProcessingUtils::mapLayerFromStore( const QString &string, QgsMapLayerStore *store )
QgsMapLayer *QgsProcessingUtils::mapLayerFromStore( const QString &string, QgsMapLayerStore *store, QgsProcessingUtils::LayerHint typeHint )
{
if ( !store || string.isEmpty() )
return nullptr;
Expand All @@ -117,19 +117,35 @@ QgsMapLayer *QgsProcessingUtils::mapLayerFromStore( const QString &string, QgsMa
return true;
} ), layers.end() );

Q_FOREACH ( QgsMapLayer *l, layers )
auto isCompatibleType = [typeHint]( QgsMapLayer * l ) -> bool
{
if ( l->id() == string )
switch ( typeHint )
{
case UnknownType:
return true;

case Vector:
return l->type() == QgsMapLayer::VectorLayer;

case Raster:
return l->type() == QgsMapLayer::RasterLayer;
}
return true;
};

for ( QgsMapLayer *l : qgis::as_const( layers ) )
{
if ( isCompatibleType( l ) && l->id() == string )
return l;
}
Q_FOREACH ( QgsMapLayer *l, layers )
for ( QgsMapLayer *l : qgis::as_const( layers ) )
{
if ( l->name() == string )
if ( isCompatibleType( l ) && l->name() == string )
return l;
}
Q_FOREACH ( QgsMapLayer *l, layers )
for ( QgsMapLayer *l : qgis::as_const( layers ) )
{
if ( normalizeLayerSource( l->source() ) == normalizeLayerSource( string ) )
if ( isCompatibleType( l ) && normalizeLayerSource( l->source() ) == normalizeLayerSource( string ) )
return l;
}
return nullptr;
Expand Down Expand Up @@ -157,7 +173,7 @@ class ProjectionSettingRestorer
};
///@endcond PRIVATE

QgsMapLayer *QgsProcessingUtils::loadMapLayerFromString( const QString &string )
QgsMapLayer *QgsProcessingUtils::loadMapLayerFromString( const QString &string, LayerHint typeHint )
{
QStringList components = string.split( '|' );
if ( components.isEmpty() )
Expand All @@ -178,24 +194,30 @@ QgsMapLayer *QgsProcessingUtils::loadMapLayerFromString( const QString &string )
QString name = fi.baseName();

// brute force attempt to load a matching layer
QgsVectorLayer::LayerOptions options;
options.loadDefaultStyle = false;
std::unique_ptr< QgsVectorLayer > layer( new QgsVectorLayer( string, name, QStringLiteral( "ogr" ), options ) );
if ( layer->isValid() )
if ( typeHint == UnknownType || typeHint == Vector )
{
return layer.release();
QgsVectorLayer::LayerOptions options;
options.loadDefaultStyle = false;
std::unique_ptr< QgsVectorLayer > layer( new QgsVectorLayer( string, name, QStringLiteral( "ogr" ), options ) );
if ( layer->isValid() )
{
return layer.release();
}
}
QgsRasterLayer::LayerOptions rasterOptions;
rasterOptions.loadDefaultStyle = false;
std::unique_ptr< QgsRasterLayer > rasterLayer( new QgsRasterLayer( string, name, QStringLiteral( "gdal" ), rasterOptions ) );
if ( rasterLayer->isValid() )
if ( typeHint == UnknownType || typeHint == Raster )
{
return rasterLayer.release();
QgsRasterLayer::LayerOptions rasterOptions;
rasterOptions.loadDefaultStyle = false;
std::unique_ptr< QgsRasterLayer > rasterLayer( new QgsRasterLayer( string, name, QStringLiteral( "gdal" ), rasterOptions ) );
if ( rasterLayer->isValid() )
{
return rasterLayer.release();
}
}
return nullptr;
}

QgsMapLayer *QgsProcessingUtils::mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers )
QgsMapLayer *QgsProcessingUtils::mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers, LayerHint typeHint )
{
if ( string.isEmpty() )
return nullptr;
Expand All @@ -204,19 +226,19 @@ QgsMapLayer *QgsProcessingUtils::mapLayerFromString( const QString &string, QgsP
QgsMapLayer *layer = nullptr;
if ( context.project() )
{
QgsMapLayer *layer = mapLayerFromStore( string, context.project()->layerStore() );
QgsMapLayer *layer = mapLayerFromStore( string, context.project()->layerStore(), typeHint );
if ( layer )
return layer;
}

layer = mapLayerFromStore( string, context.temporaryLayerStore() );
layer = mapLayerFromStore( string, context.temporaryLayerStore(), typeHint );
if ( layer )
return layer;

if ( !allowLoadingNewLayers )
return nullptr;

layer = loadMapLayerFromString( string );
layer = loadMapLayerFromString( string, typeHint );
if ( layer )
{
context.temporaryLayerStore()->addMapLayer( layer );
Expand Down Expand Up @@ -274,7 +296,7 @@ QgsProcessingFeatureSource *QgsProcessingUtils::variantToSource( const QVariant
if ( layerRef.isEmpty() )
return nullptr;

QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context ) );
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context, true, Vector ) );
if ( !vl )
return nullptr;

Expand Down
19 changes: 16 additions & 3 deletions src/core/processing/qgsprocessingutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ class CORE_EXPORT QgsProcessingUtils
*/
static QList< QgsMapLayer * > compatibleLayers( QgsProject *project, bool sort = true );

/**
* Layer type hints.
* \since QGIS 3.4
*/
enum LayerHint
{
UnknownType, //!< Unknown layer type
Vector, //!< Vector layer type
Raster, //!< Raster layer type
};

/**
* Interprets a string as a map layer within the supplied \a context.
*
Expand All @@ -95,8 +106,10 @@ class CORE_EXPORT QgsProcessingUtils
* If the string is a file path and \a allowLoadingNewLayers is true, then the layer at this
* file path will be loaded and added to the context's temporary layer store.
* Ownership of the layer remains with the \a context or the context's current project.
*
* The \a typeHint can be used to dictate the type of map layer expected.
*/
static QgsMapLayer *mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers = true );
static QgsMapLayer *mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers = true, LayerHint typeHint = UnknownType );

/**
* Converts a variant \a value to a new feature source.
Expand Down Expand Up @@ -265,15 +278,15 @@ class CORE_EXPORT QgsProcessingUtils
* returned.
* \see mapLayerFromString()
*/
static QgsMapLayer *mapLayerFromStore( const QString &string, QgsMapLayerStore *store );
static QgsMapLayer *mapLayerFromStore( const QString &string, QgsMapLayerStore *store, LayerHint typeHint = UnknownType );

/**
* Interprets a string as a map layer. The method will attempt to
* load a layer matching the passed \a string. E.g. if the string is a file path,
* then the layer at this file path will be loaded.
* The caller takes responsibility for deleting the returned map layer.
*/
static QgsMapLayer *loadMapLayerFromString( const QString &string );
static QgsMapLayer *loadMapLayerFromString( const QString &string, LayerHint typeHint = UnknownType );

static void parseDestinationString( QString &destination, QString &providerKey, QString &uri, QString &layerName, QString &format, QMap<QString, QVariant> &options, bool &useWriter );

Expand Down
Loading