Port some processing dataobjects routines to c++

This commit is contained in:
Nyall Dawson 2017-04-05 14:37:06 +10:00
parent d5f930adad
commit 8ffdb362cc
19 changed files with 455 additions and 117 deletions

View File

@ -277,6 +277,7 @@
%Include processing/qgsprocessingfeedback.sip
%Include processing/qgsprocessingprovider.sip
%Include processing/qgsprocessingregistry.sip
%Include processing/qgsprocessingutils.sip
%Include raster/qgsbilinearrasterresampler.sip
%Include raster/qgsbrightnesscontrastfilter.sip

View File

@ -0,0 +1,77 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/processing/qgsprocessingutils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsProcessingUtils
{
%Docstring
Utility functions for use with processing classes.
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include "qgsprocessingutils.h"
%End
public:
static QList< QgsRasterLayer * > compatibleRasterLayers( QgsProject *project, bool sort = true );
%Docstring
Returns a list of raster layers from a project which are compatible with the processing
framework.
If the sort argument is true then the layers will be sorted by their QgsMapLayer.name()
value.
\see compatibleVectorLayers()
\see compatibleLayers()
%End
static QList< QgsVectorLayer * > compatibleVectorLayers( QgsProject *project,
const QList< QgsWkbTypes::GeometryType > &geometryTypes = QList< QgsWkbTypes::GeometryType >(),
bool sort = true );
%Docstring
Returns a list of vector layers from a project which are compatible with the processing
framework.
If the geometryTypes list is non-empty then the layers will be sorted so that only
layers with geometry types included in the list will be returned. Leaving the geometryTypes
list empty will cause all vector layers, regardless of their geometry type, to be returned.
If the sort argument is true then the layers will be sorted by their QgsMapLayer.name()
value.
\see compatibleRasterLayers()
\see compatibleLayers()
%End
static QList< QgsMapLayer * > compatibleLayers( QgsProject *project, bool sort = true );
%Docstring
Returns a list of map layers from a project which are compatible with the processing
framework.
If the sort argument is true then the layers will be sorted by their QgsMapLayer.name()
value.
\see compatibleRasterLayers()
\see compatibleVectorLayers()
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/processing/qgsprocessingutils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -31,7 +31,9 @@ import re
from qgis.PyQt.QtCore import QUrl
from qgis.core import (QgsApplication,
QgsVectorFileWriter)
QgsVectorFileWriter,
QgsProcessingUtils,
QgsProject)
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.algs.gdal.GdalAlgorithmDialog import GdalAlgorithmDialog
@ -58,7 +60,7 @@ class GdalAlgorithm(GeoAlgorithm):
def processAlgorithm(self, feedback):
commands = self.getConsoleCommands()
layers = dataobjects.getVectorLayers()
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
supported = QgsVectorFileWriter.supportedFormatExtensions()
for i, c in enumerate(commands):
for layer in layers:

View File

@ -34,7 +34,9 @@ from processing.core.outputs import OutputRaster
from processing.tools import dataobjects
from processing.algs.gdal.GdalUtils import GdalUtils
from qgis.core import (QgsApplication,
QgsRectangle)
QgsRectangle,
QgsProcessingUtils,
QgsProject)
from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.algs.qgis.ui.RasterCalculatorWidgets import LayersListWidgetWrapper, ExpressionWidgetWrapper
@ -108,7 +110,7 @@ class RasterCalculator(GeoAlgorithm):
layers = [dataobjects.getObjectFromUri(f) for f in layersValue.split(";")]
layersDict = {os.path.basename(lyr.source().split(".")[0]): lyr for lyr in layers}
for lyr in dataobjects.getRasterLayers():
for lyr in QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance()):
name = lyr.name()
if (name + "@") in expression:
layersDict[name] = lyr

View File

@ -35,7 +35,9 @@ from qgis.PyQt.QtWidgets import QDialog, QFileDialog, QApplication, QMessageBox
from qgis.PyQt.QtGui import QCursor
from qgis.core import (QgsExpressionContextUtils,
QgsProcessingFeedback,
QgsSettings)
QgsSettings,
QgsProcessingUtils,
QgsProject)
from qgis.gui import QgsEncodingFileDialog
from processing.core.ProcessingConfig import ProcessingConfig
@ -101,7 +103,7 @@ class FieldsCalculatorDialog(BASE, WIDGET):
self.mOutputFieldTypeComboBox.blockSignals(False)
self.cmbInputLayer.blockSignals(True)
layers = dataobjects.getVectorLayers()
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
for layer in layers:
self.cmbInputLayer.addItem(layer.name())
self.cmbInputLayer.blockSignals(False)

View File

@ -35,7 +35,10 @@ from qgis.PyQt.QtGui import QBrush
from qgis.PyQt.QtWidgets import QComboBox, QHeaderView, QLineEdit, QSpacerItem, QMessageBox, QSpinBox, QStyledItemDelegate
from qgis.PyQt.QtCore import QItemSelectionModel, QAbstractTableModel, QModelIndex, QVariant, Qt, pyqtSlot
from qgis.core import QgsExpression, QgsProject, QgsApplication
from qgis.core import (QgsExpression,
QgsProject,
QgsApplication,
QgsProcessingUtils)
from qgis.gui import QgsFieldExpressionWidget
from processing.gui.wrappers import WidgetWrapper, DIALOG_STANDARD, DIALOG_MODELER
@ -473,8 +476,7 @@ class FieldsMappingPanel(BASE, WIDGET):
self.model.index(end, self.model.columnCount() - 1))
def updateLayerCombo(self):
layers = dataobjects.getTables()
layers.sort(key=lambda lay: lay.name())
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
for layer in layers:
self.layerCombo.addItem(layer.name(), layer)
@ -496,7 +498,7 @@ class FieldsMappingWidgetWrapper(WidgetWrapper):
if wrapper.param.name == self.param.parent:
wrapper.widgetValueHasChanged.connect(self.parentLayerChanged)
break
layers = dataobjects.getTables()
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
if len(layers) > 0:
# as first item in combobox is already selected
self.widget.setLayer(layers[0])

View File

@ -1,3 +1,5 @@
from qgis.core import (QgsProcessingUtils,
QgsProject)
from processing.gui.wrappers import WidgetWrapper, DIALOG_STANDARD, DIALOG_BATCH
from processing.tools import dataobjects
from processing.tools.system import userFolder
@ -170,7 +172,7 @@ class ExpressionWidgetWrapper(WidgetWrapper):
def createWidget(self):
if self.dialogType == DIALOG_STANDARD:
layers = dataobjects.getRasterLayers(sorting=False)
layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
options = {}
for lyr in layers:
for n in range(lyr.bandCount()):
@ -185,7 +187,7 @@ class ExpressionWidgetWrapper(WidgetWrapper):
return self._panel(options)
def refresh(self):
layers = dataobjects.getRasterLayers()
layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance())
options = {}
for lyr in layers:
for n in range(lyr.bandCount()):
@ -229,11 +231,11 @@ class LayersListWidgetWrapper(WidgetWrapper):
return self.param.setValue(self.widget.selectedoptions)
else:
if self.param.datatype == dataobjects.TYPE_RASTER:
options = dataobjects.getRasterLayers(sorting=False)
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
elif self.param.datatype == dataobjects.TYPE_VECTOR_ANY:
options = dataobjects.getVectorLayers(sorting=False)
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
else:
options = dataobjects.getVectorLayers([self.param.datatype], sorting=False)
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.datatype], False)
return [options[i] for i in self.widget.selectedoptions]
elif self.dialogType == DIALOG_BATCH:
return self.widget.getText()

View File

@ -35,7 +35,9 @@ from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsApplication,
QgsProcessingFeedback,
QgsSettings,
QgsProcessingAlgorithm)
QgsProcessingAlgorithm,
QgsProject,
QgsProcessingUtils)
from builtins import str
from builtins import object
@ -339,7 +341,7 @@ class GeoAlgorithm(QgsProcessingAlgorithm):
raise GeoAlgorithmExecutionException(str(e))
def setOutputCRS(self):
layers = dataobjects.getAllLayers()
layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance())
for param in self.parameters:
if isinstance(param, (ParameterRaster, ParameterVector, ParameterMultipleInput)):
if param.value:
@ -365,7 +367,7 @@ class GeoAlgorithm(QgsProcessingAlgorithm):
pass
def resolveDataObjects(self):
layers = dataobjects.getAllLayers()
layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance())
for param in self.parameters:
if isinstance(param, (ParameterRaster, ParameterVector, ParameterTable,
ParameterMultipleInput)):

View File

@ -319,7 +319,7 @@ class OutputVector(Output):
def hasGeometry(self):
if self.base_layer is None:
return True
return dataobjects.canUseVectorLayer(self.base_layer, [-1])
return self.base_layer.hasGeometryType()
def getSupportedOutputVectorLayerExtensions(self):
exts = QgsVectorFileWriter.supportedFormatExtensions()

View File

@ -36,6 +36,7 @@ from inspect import isclass
from copy import deepcopy
import numbers
from qgis.core import QgsProcessingUtils
from qgis.utils import iface
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsRasterLayer, QgsVectorLayer, QgsMapLayer, QgsCoordinateReferenceSystem,
@ -90,7 +91,7 @@ def _expressionContext():
def _resolveLayers(value):
layers = dataobjects.getAllLayers()
layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance())
if value:
inputlayers = value.split(';')
for i, inputlayer in enumerate(inputlayers):
@ -727,7 +728,7 @@ class ParameterMultipleInput(ParameterDataObject):
return str(value.dataProvider().dataSourceUri())
else:
s = str(value)
layers = dataobjects.getRasterLayers()
layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance())
for layer in layers:
if layer.name() == s:
return str(layer.dataProvider().dataSourceUri())
@ -740,7 +741,10 @@ class ParameterMultipleInput(ParameterDataObject):
return str(value.source())
else:
s = str(value)
layers = dataobjects.getVectorLayers([self.datatype])
if self.datatype != dataobjects.TYPE_VECTOR_ANY:
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.datatype], False)
else:
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
for layer in layers:
if layer.name() == s:
return str(layer.source())
@ -1317,7 +1321,7 @@ class ParameterTable(ParameterDataObject):
return True
else:
self.value = str(obj)
layers = dataobjects.getTables()
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
for layer in layers:
if layer.name() == self.value or layer.source() == self.value:
source = str(layer.source())

View File

@ -30,7 +30,8 @@ from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtWidgets import QMessageBox, QApplication, QPushButton, QWidget, QVBoxLayout, QSizePolicy
from qgis.PyQt.QtGui import QCursor, QColor, QPalette
from qgis.core import QgsProject
from qgis.core import (QgsProject,
QgsProcessingUtils)
from qgis.gui import QgsMessageBar
from qgis.utils import iface
@ -113,7 +114,7 @@ class AlgorithmDialog(AlgorithmDialogBase):
unmatchingCRS = False
hasExtent = False
projectCRS = iface.mapCanvas().mapSettings().destinationCrs()
layers = dataobjects.getAllLayers()
layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance())
for param in self.alg.parameters:
if isinstance(param, (ParameterRaster, ParameterVector, ParameterMultipleInput)):
if param.value:

View File

@ -33,7 +33,10 @@ from qgis.PyQt.QtCore import pyqtSignal
from qgis.PyQt.QtWidgets import QWidget, QHBoxLayout, QMenu, QPushButton, QLineEdit, QSizePolicy, QAction, QFileDialog
from qgis.PyQt.QtGui import QCursor
from qgis.core import QgsMapLayer, QgsSettings
from qgis.core import (QgsMapLayer,
QgsSettings,
QgsProject,
QgsProcessingUtils)
from processing.gui.MultipleInputDialog import MultipleInputDialog
@ -99,15 +102,18 @@ class BatchInputSelectionPanel(QWidget):
if (isinstance(self.param, ParameterRaster) or
(isinstance(self.param, ParameterMultipleInput) and
self.param.datatype == dataobjects.TYPE_RASTER)):
layers = dataobjects.getRasterLayers()
layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance())
elif isinstance(self.param, ParameterTable):
layers = dataobjects.getTables()
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
else:
if isinstance(self.param, ParameterVector):
datatype = self.param.datatype
else:
datatype = [self.param.datatype]
layers = dataobjects.getVectorLayers(datatype)
if datatype != dataobjects.TYPE_VECTOR_ANY:
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [datatype])
else:
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
dlg = MultipleInputDialog([layer.name() for layer in layers])
dlg.exec_()

View File

@ -34,7 +34,8 @@ from qgis.PyQt.QtGui import QCursor
from qgis.gui import QgsMessageBar
from qgis.utils import iface
from qgis.core import (QgsProcessingUtils,
QgsProject)
from processing.gui.RectangleMapTool import RectangleMapTool
from processing.core.ProcessingConfig import ProcessingConfig
from processing.tools import dataobjects
@ -108,7 +109,7 @@ class ExtentSelectionPanel(BASE, WIDGET):
extentsDict[CANVAS_KEY] = {"extent": iface.mapCanvas().extent(),
"authid": iface.mapCanvas().mapSettings().destinationCrs().authid()}
extents = [CANVAS_KEY]
layers = dataobjects.getAllLayers()
layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance())
for layer in layers:
authid = layer.crs().authid()
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF) \

View File

@ -40,7 +40,8 @@ from qgis.core import (
QgsWkbTypes,
QgsSettings,
QgsProject,
QgsMapLayer
QgsMapLayer,
QgsProcessingUtils
)
from qgis.PyQt.QtWidgets import (
QCheckBox,
@ -519,13 +520,11 @@ class MultipleInputWidgetWrapper(WidgetWrapper):
return MultipleInputPanel(datatype=dataobjects.TYPE_FILE)
else:
if self.param.datatype == dataobjects.TYPE_RASTER:
options = dataobjects.getRasterLayers(sorting=False)
elif self.param.datatype == dataobjects.TYPE_VECTOR_ANY:
options = dataobjects.getVectorLayers(sorting=False)
elif self.param.datatype == dataobjects.TYPE_TABLE:
options = dataobjects.getTables(sorting=False)
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
elif self.param.datatype in (dataobjects.TYPE_VECTOR_ANY, dataobjects.TYPE_TABLE):
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
else:
options = dataobjects.getVectorLayers([self.param.datatype], sorting=False)
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.datatype], False)
opts = [getExtendedLayerName(opt) for opt in options]
return MultipleInputPanel(opts)
elif self.dialogType == DIALOG_BATCH:
@ -539,13 +538,11 @@ class MultipleInputWidgetWrapper(WidgetWrapper):
def refresh(self):
if self.param.datatype != dataobjects.TYPE_FILE:
if self.param.datatype == dataobjects.TYPE_RASTER:
options = dataobjects.getRasterLayers(sorting=False)
elif self.param.datatype == dataobjects.TYPE_VECTOR_ANY:
options = dataobjects.getVectorLayers(sorting=False)
elif self.param.datatype == dataobjects.TYPE_TABLE:
options = dataobjects.getTables(sorting=False)
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
elif self.param.datatype in (dataobjects.TYPE_VECTOR_ANY, dataobjects.TYPE_TABLE):
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
else:
options = dataobjects.getVectorLayers([self.param.datatype], sorting=False)
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.datatype], False)
opts = [getExtendedLayerName(opt) for opt in options]
self.widget.updateForOptions(opts)
@ -568,13 +565,11 @@ class MultipleInputWidgetWrapper(WidgetWrapper):
return self.param.setValue(self.widget.selectedoptions)
else:
if self.param.datatype == dataobjects.TYPE_RASTER:
options = dataobjects.getRasterLayers(sorting=False)
elif self.param.datatype == dataobjects.TYPE_VECTOR_ANY:
options = dataobjects.getVectorLayers(sorting=False)
elif self.param.datatype == dataobjects.TYPE_TABLE:
options = dataobjects.getTables(sorting=False)
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
elif self.param.datatype in (dataobjects.TYPE_VECTOR_ANY, dataobjects.TYPE_TABLE):
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
else:
options = dataobjects.getVectorLayers([self.param.datatype], sorting=False)
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.param.datatype], False)
return [options[i] for i in self.widget.selectedoptions]
elif self.dialogType == DIALOG_BATCH:
return self.widget.getText()

View File

@ -37,7 +37,8 @@ from qgis.core import (QgsVectorFileWriter,
QgsVectorLayer,
QgsProject,
QgsCoordinateReferenceSystem,
QgsSettings)
QgsSettings,
QgsProcessingUtils)
from qgis.gui import QgsSublayersDialog
from processing.core.ProcessingConfig import ProcessingConfig
@ -76,60 +77,6 @@ def getSupportedOutputRasterLayerExtensions():
return allexts
def getRasterLayers(sorting=True):
layers = QgsProject.instance().layerTreeRoot().findLayers()
raster = [lay.layer() for lay in layers if lay.layer() is not None and canUseRasterLayer(lay.layer())]
if sorting:
return sorted(raster, key=lambda layer: layer.name().lower())
else:
return raster
def getVectorLayers(shapetype=[-1], sorting=True):
layers = QgsProject.instance().layerTreeRoot().findLayers()
vector = [lay.layer() for lay in layers if canUseVectorLayer(lay.layer(), shapetype)]
if sorting:
return sorted(vector, key=lambda layer: layer.name().lower())
else:
return vector
def canUseVectorLayer(layer, shapetype):
if layer.type() == QgsMapLayer.VectorLayer and layer.dataProvider().name() != "grass":
if (layer.hasGeometryType() and
(shapetype == ALL_TYPES or layer.geometryType() in shapetype)):
return True
return False
def canUseRasterLayer(layer):
if layer.type() == QgsMapLayer.RasterLayer:
if layer.providerType() == 'gdal': # only gdal file-based layers
return True
return False
def getAllLayers():
layers = []
layers += getRasterLayers()
layers += getVectorLayers()
return sorted(layers, key=lambda layer: layer.name().lower())
def getTables(sorting=True):
layers = QgsProject.instance().layerTreeRoot().findLayers()
tables = []
for layer in layers:
mapLayer = layer.layer()
if mapLayer.type() == QgsMapLayer.VectorLayer:
tables.append(mapLayer)
if sorting:
return sorted(tables, key=lambda table: table.name().lower())
else:
return tables
def extent(layers):
first = True
for layer in layers:
@ -206,7 +153,7 @@ def load(fileName, name=None, crs=None, style=None):
def getObjectFromName(name):
layers = getAllLayers()
layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance(), False)
for layer in layers:
if layer.name() == name:
return layer
@ -237,18 +184,10 @@ def getObjectFromUri(uri, forceLoad=True):
return None
if uri in _loadedLayers:
return _loadedLayers[uri]
layers = getRasterLayers()
layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance(), False)
for layer in layers:
if normalizeLayerSource(layer.source()) == normalizeLayerSource(uri):
return layer
layers = getVectorLayers()
for layer in layers:
if normalizeLayerSource(layer.source()) == normalizeLayerSource(uri):
return layer
tables = getTables()
for table in tables:
if normalizeLayerSource(table.source()) == normalizeLayerSource(uri):
return table
if forceLoad and os.path.exists(uri):
settings = QgsSettings()
prjSetting = settings.value('/Projections/defaultBehavior')

View File

@ -87,6 +87,7 @@ SET(QGIS_CORE_SRCS
processing/qgsprocessingalgorithm.cpp
processing/qgsprocessingprovider.cpp
processing/qgsprocessingregistry.cpp
processing/qgsprocessingutils.cpp
qgis.cpp
qgsapplication.cpp
@ -838,6 +839,7 @@ SET(QGIS_CORE_HDRS
processing/qgsprocessingalgorithm.h
processing/qgsprocessingprovider.h
processing/qgsprocessingutils.h
raster/qgsbilinearrasterresampler.h
raster/qgsbrightnesscontrastfilter.h

View File

@ -0,0 +1,97 @@
/***************************************************************************
qgsprocessingutils.cpp
------------------------
begin : April 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsprocessingutils.h"
#include "qgsproject.h"
QList<QgsRasterLayer *> QgsProcessingUtils::compatibleRasterLayers( QgsProject *project, bool sort )
{
if ( !project )
return QList<QgsRasterLayer *>();
QList<QgsRasterLayer *> layers;
Q_FOREACH ( QgsRasterLayer *l, project->layers<QgsRasterLayer *>() )
{
if ( canUseLayer( l ) )
layers << l;
}
if ( sort )
{
std::sort( layers.begin(), layers.end(), []( const QgsRasterLayer * a, const QgsRasterLayer * b ) -> bool
{
return QString::localeAwareCompare( a->name(), b->name() ) < 0;
} );
}
return layers;
}
QList<QgsVectorLayer *> QgsProcessingUtils::compatibleVectorLayers( QgsProject *project, const QList<QgsWkbTypes::GeometryType> &geometryTypes, bool sort )
{
if ( !project )
return QList<QgsVectorLayer *>();
QList<QgsVectorLayer *> layers;
Q_FOREACH ( QgsVectorLayer *l, project->layers<QgsVectorLayer *>() )
{
if ( canUseLayer( l, geometryTypes ) )
layers << l;
}
if ( sort )
{
std::sort( layers.begin(), layers.end(), []( const QgsVectorLayer * a, const QgsVectorLayer * b ) -> bool
{
return QString::localeAwareCompare( a->name(), b->name() ) < 0;
} );
}
return layers;
}
QList<QgsMapLayer *> QgsProcessingUtils::compatibleLayers( QgsProject *project, bool sort )
{
if ( !project )
return QList<QgsMapLayer *>();
QList<QgsMapLayer *> layers;
Q_FOREACH ( QgsRasterLayer *rl, compatibleRasterLayers( project, false ) )
layers << rl;
Q_FOREACH ( QgsVectorLayer *vl, compatibleVectorLayers( project, QList< QgsWkbTypes::GeometryType >(), false ) )
layers << vl;
if ( sort )
{
std::sort( layers.begin(), layers.end(), []( const QgsMapLayer * a, const QgsMapLayer * b ) -> bool
{
return QString::localeAwareCompare( a->name(), b->name() ) < 0;
} );
}
return layers;
}
bool QgsProcessingUtils::canUseLayer( const QgsRasterLayer *layer )
{
// only gdal file-based layers
return layer && layer->providerType() == QStringLiteral( "gdal" );
}
bool QgsProcessingUtils::canUseLayer( const QgsVectorLayer *layer, const QList<QgsWkbTypes::GeometryType> &geometryTypes )
{
return layer &&
( geometryTypes.isEmpty() || geometryTypes.contains( layer->geometryType() ) );
}

View File

@ -0,0 +1,90 @@
/***************************************************************************
qgsprocessingutils.h
------------------------
begin : April 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSPROCESSINGUTILS_H
#define QGSPROCESSINGUTILS_H
#include "qgis_core.h"
#include "qgsrasterlayer.h"
#include "qgsvectorlayer.h"
class QgsProject;
#include <QString>
/**
* \class QgsProcessingUtils
* \ingroup core
* Utility functions for use with processing classes.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProcessingUtils
{
public:
/**
* Returns a list of raster layers from a \a project which are compatible with the processing
* framework.
*
* If the \a sort argument is true then the layers will be sorted by their QgsMapLayer::name()
* value.
* \see compatibleVectorLayers()
* \see compatibleLayers()
*/
static QList< QgsRasterLayer * > compatibleRasterLayers( QgsProject *project, bool sort = true );
/**
* Returns a list of vector layers from a \a project which are compatible with the processing
* framework.
*
* If the \a geometryTypes list is non-empty then the layers will be sorted so that only
* layers with geometry types included in the list will be returned. Leaving the \a geometryTypes
* list empty will cause all vector layers, regardless of their geometry type, to be returned.
*
* If the \a sort argument is true then the layers will be sorted by their QgsMapLayer::name()
* value.
* \see compatibleRasterLayers()
* \see compatibleLayers()
*/
static QList< QgsVectorLayer * > compatibleVectorLayers( QgsProject *project,
const QList< QgsWkbTypes::GeometryType > &geometryTypes = QList< QgsWkbTypes::GeometryType >(),
bool sort = true );
/**
* Returns a list of map layers from a \a project which are compatible with the processing
* framework.
*
* If the \a sort argument is true then the layers will be sorted by their QgsMapLayer::name()
* value.
* \see compatibleRasterLayers()
* \see compatibleVectorLayers()
*/
static QList< QgsMapLayer * > compatibleLayers( QgsProject *project, bool sort = true );
private:
static bool canUseLayer( const QgsRasterLayer *layer );
static bool canUseLayer( const QgsVectorLayer *layer,
const QList< QgsWkbTypes::GeometryType > &geometryTypes );
};
#endif // QGSPROCESSINGUTILS_H

View File

@ -17,8 +17,11 @@
#include "qgsprocessingregistry.h"
#include "qgsprocessingprovider.h"
#include "qgsprocessingutils.h"
#include <QObject>
#include "qgstest.h"
#include "qgsrasterlayer.h"
#include "qgsproject.h"
//dummy provider for testing
class DummyProvider : public QgsProcessingProvider
@ -40,19 +43,31 @@ class TestQgsProcessing: public QObject
Q_OBJECT
private slots:
void initTestCase() {}// will be called before the first testfunction is executed.
void cleanupTestCase() {}// will be called after the last testfunction was executed.
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase(); // will be called after the last testfunction was executed.
void init() {} // will be called before each testfunction is executed.
void cleanup() {} // will be called after every testfunction.
void instance();
void addProvider();
void providerById();
void removeProvider();
void compatibleLayers();
private:
};
void TestQgsProcessing::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
}
void TestQgsProcessing::cleanupTestCase()
{
QgsApplication::exitQgis();
}
void TestQgsProcessing::instance()
{
// test that application has a registry instance
@ -144,5 +159,103 @@ void TestQgsProcessing::removeProvider()
QVERIFY( r.providers().isEmpty() );
}
void TestQgsProcessing::compatibleLayers()
{
QgsProject p;
// add a bunch of layers to a project
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
QString raster1 = testDataDir + "tenbytenraster.asc";
QString raster2 = testDataDir + "landsat.tif";
QString raster3 = testDataDir + "/raster/band1_float32_noct_epsg4326.tif";
QFileInfo fi1( raster1 );
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
QVERIFY( r1->isValid() );
QFileInfo fi2( raster2 );
QgsRasterLayer *r2 = new QgsRasterLayer( fi2.filePath(), "ar2" );
QVERIFY( r2->isValid() );
QFileInfo fi3( raster3 );
QgsRasterLayer *r3 = new QgsRasterLayer( fi3.filePath(), "zz" );
QVERIFY( r3->isValid() );
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon", "V4", "memory" );
QgsVectorLayer *v2 = new QgsVectorLayer( "Point", "v1", "memory" );
QgsVectorLayer *v3 = new QgsVectorLayer( "LineString", "v3", "memory" );
QgsVectorLayer *v4 = new QgsVectorLayer( "none", "vvvv4", "memory" );
p.addMapLayers( QList<QgsMapLayer *>() << r1 << r2 << r3 << v1 << v2 << v3 << v4 );
// compatibleRasterLayers
QVERIFY( QgsProcessingUtils::compatibleRasterLayers( nullptr ).isEmpty() );
// sorted
QStringList lIds;
Q_FOREACH ( QgsRasterLayer *rl, QgsProcessingUtils::compatibleRasterLayers( &p ) )
lIds << rl->name();
QCOMPARE( lIds, QStringList() << "ar2" << "R1" << "zz" );
// unsorted
lIds.clear();
Q_FOREACH ( QgsRasterLayer *rl, QgsProcessingUtils::compatibleRasterLayers( &p, false ) )
lIds << rl->name();
QCOMPARE( lIds, QStringList() << "R1" << "ar2" << "zz" );
// compatibleVectorLayers
QVERIFY( QgsProcessingUtils::compatibleVectorLayers( nullptr ).isEmpty() );
// sorted
lIds.clear();
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p ) )
lIds << vl->name();
QCOMPARE( lIds, QStringList() << "v1" << "v3" << "V4" << "vvvv4" );
// unsorted
lIds.clear();
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<QgsWkbTypes::GeometryType>(), false ) )
lIds << vl->name();
QCOMPARE( lIds, QStringList() << "V4" << "v1" << "v3" << "vvvv4" );
// point only
lIds.clear();
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<QgsWkbTypes::GeometryType>() << QgsWkbTypes::PointGeometry ) )
lIds << vl->name();
QCOMPARE( lIds, QStringList() << "v1" );
// polygon only
lIds.clear();
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<QgsWkbTypes::GeometryType>() << QgsWkbTypes::PolygonGeometry ) )
lIds << vl->name();
QCOMPARE( lIds, QStringList() << "V4" );
// line only
lIds.clear();
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<QgsWkbTypes::GeometryType>() << QgsWkbTypes::LineGeometry ) )
lIds << vl->name();
QCOMPARE( lIds, QStringList() << "v3" );
// point and line only
lIds.clear();
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<QgsWkbTypes::GeometryType>() << QgsWkbTypes::PointGeometry << QgsWkbTypes::LineGeometry ) )
lIds << vl->name();
QCOMPARE( lIds, QStringList() << "v1" << "v3" );
// all layers
QVERIFY( QgsProcessingUtils::compatibleLayers( nullptr ).isEmpty() );
// sorted
lIds.clear();
Q_FOREACH ( QgsMapLayer *l, QgsProcessingUtils::compatibleLayers( &p ) )
lIds << l->name();
QCOMPARE( lIds, QStringList() << "ar2" << "R1" << "v1" << "v3" << "V4" << "vvvv4" << "zz" );
// unsorted
lIds.clear();
Q_FOREACH ( QgsMapLayer *l, QgsProcessingUtils::compatibleLayers( &p, false ) )
lIds << l->name();
QCOMPARE( lIds, QStringList() << "R1" << "ar2" << "zz" << "V4" << "v1" << "v3" << "vvvv4" );
}
QGSTEST_MAIN( TestQgsProcessing )
#include "testqgsprocessing.moc"