Skip to content
Permalink
Browse files

First working pure c++ algorithms

  • Loading branch information
nyalldawson committed Jun 5, 2017
1 parent 4cb7d18 commit c1d9d57dd2a208168893fe9c212763c582c711e4
@@ -193,17 +193,14 @@ class QgsProcessingAlgorithm
:rtype: QgsProcessingOutputDefinition
%End

virtual QVariantMap run( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const;
QVariantMap run( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const;
%Docstring
Runs the algorithm using the specified ``parameters``. Algorithms should implement
their custom processing logic here.
Executes the algorithm using the specified ``parameters``.

The ``context`` argument specifies the context in which the algorithm is being run.

Algorithm progress should be reported using the supplied ``feedback`` object. Additionally,
well-behaved algorithms should periodically check ``feedback`` to determine whether the
algorithm should be canceled and exited early.
Algorithm progress should be reported using the supplied ``feedback`` object.

:return: A map of algorithm outputs. These may be output layer references, or calculated
values such as statistical calculations.
@@ -239,6 +236,23 @@ class QgsProcessingAlgorithm
:rtype: bool
%End

virtual QVariantMap processAlgorithm( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const = 0;
%Docstring
Runs the algorithm using the specified ``parameters``. Algorithms should implement
their custom processing logic here.

The ``context`` argument specifies the context in which the algorithm is being run.

Algorithm progress should be reported using the supplied ``feedback`` object. Additionally,
well-behaved algorithms should periodically check ``feedback`` to determine whether the
algorithm should be canceled and exited early.

:return: A map of algorithm outputs. These may be output layer references, or calculated
values such as statistical calculations.
:rtype: QVariantMap
%End

QString parameterAsString( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a static string value.
@@ -83,6 +83,28 @@ class QgsProcessingContext
:rtype: QgsMapLayerStore
%End

QStringList layersToLoadOnCompletion() const;
%Docstring
Returns a list of layers (by ID or datasource) to load into the canvas upon completion of the algorithm or model.
.. seealso:: setLayersToLoadOnCompletion()
.. seealso:: addLayerToLoadOnCompletion()
:rtype: list of str
%End

void setLayersToLoadOnCompletion( const QStringList &layers );
%Docstring
Sets the list of ``layers`` (by ID or datasource) to load into the canvas upon completion of the algorithm or model.
.. seealso:: addLayerToLoadOnCompletion()
.. seealso:: layersToLoadOnCompletion()
%End

void addLayerToLoadOnCompletion( const QString &layer );
%Docstring
Adds a ``layer`` to load (by ID or datasource) into the canvas upon completion of the algorithm or model.
.. seealso:: setLayersToLoadOnCompletion()
.. seealso:: layersToLoadOnCompletion()
%End


QgsFeatureRequest::InvalidGeometryCheck invalidGeometryCheck() const;
%Docstring
@@ -137,6 +159,10 @@ class QgsProcessingContext
QgsProcessingContext( const QgsProcessingContext &other );
};





QFlags<QgsProcessingContext::Flag> operator|(QgsProcessingContext::Flag f1, QFlags<QgsProcessingContext::Flag> f2);


@@ -178,9 +178,9 @@ def doCheck(self, context, feedback):
del invalid_writer
del error_writer

if valid_count == 0:
valid_output.open = False
if invalid_count == 0:
invalid_output.open = False
if error_count == 0:
error_output.open = False
if valid_count != 0:
context.addLayerToLoadOnCompletion(valid_output.value)
if invalid_count != 0:
context.addLayerToLoadOnCompletion(invalid_output.value)
if error_count != 0:
context.addLayerToLoadOnCompletion(error_output.value)
@@ -75,13 +75,13 @@ def processAlgorithm(self, parameters, context, feedback):
style = self.getParameterValue(self.STYLE)
if layer is None:
dataobjects.load(filename, os.path.basename(filename), style=style)
self.getOutputFromName(self.OUTPUT).open = False
else:
with open(style) as f:
xml = "".join(f.readlines())
d = QDomDocument()
d.setContent(xml)
n = d.firstChild()
layer.readSymbology(n, '')
context.addLayerToLoadOnCompletion(self.getOutputFromName(self.OUTPUT).value)
self.setOutputValue(self.OUTPUT, filename)
iface.mapCanvas().refresh()
layer.triggerRepaint()
@@ -72,8 +72,7 @@ def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(filename, context, False)
if layer is None:
dataobjects.load(filename, os.path.basename(filename), style=style)
self.getOutputFromName(self.OUTPUT).open = False
else:
layer.loadNamedStyle(style)
iface.mapCanvas().refresh()
context.addLayerToLoadOnCompletion(layer.id())
layer.triggerRepaint()
@@ -462,9 +462,10 @@ def executeAlgorithm(alg, parameters, context=None, feedback=None, model=None):
#self.resolveOutputs()
#self.evaluateParameterValues()
#self.runPreExecutionScript(feedback)
alg.run(parameters, context, feedback)
result = alg.run(parameters, context, feedback)
#self.processAlgorithm(parameters, context, feedback)
feedback.setProgress(100)
return result
#self.convertUnsupportedFormats(context, feedback)
#self.runPostExecutionScript(feedback)
#except GeoAlgorithmExecutionException as gaee:
@@ -78,10 +78,6 @@ def __init__(self, name='', description='', hidden=False):
# outputs not representing layers or tables should always be hidden.
self.hidden = str(hidden).lower() == str(True).lower()

# This value indicates whether the output has to be opened
# after being produced by the algorithm or not
self.open = True

def __str__(self):
return u'{} <{}>'.format(self.name, self.__class__.__name__)

@@ -33,7 +33,9 @@
from qgis.core import (QgsProject,
QgsProcessingUtils,
QgsMessageLog,
QgsProcessingParameterDefinition)
QgsProcessingParameterDefinition,
QgsProcessingOutputVectorLayer,
QgsProcessingParameterOutputVectorLayer)
from qgis.gui import QgsMessageBar
from qgis.utils import iface

@@ -114,6 +116,17 @@ def getParamValues(self):

return parameters

def getLayersToOpen(self):
layer_outputs = []
for param in self.alg.destinationParameterDefinitions():
if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
continue
if isinstance(param, (OutputRaster, QgsProcessingParameterOutputVectorLayer, OutputTable)):
if self.mainWidget.checkBoxes[param.name()].isChecked():
layer_outputs.append(param.name())

return layer_outputs

def setParamValue(self, param, wrapper):
if wrapper.widget:
return param.setValue(wrapper.value())
@@ -220,7 +233,7 @@ def accept(self):

if self.iterateParam:
if executeIterating(self.alg, parameters, self.iterateParam, context, self.feedback):
self.finish(context)
self.finish(parameters, context)
else:
QApplication.restoreOverrideCursor()
self.resetGUI()
@@ -229,11 +242,12 @@ def accept(self):
#command = self.alg.getAsCommand()
#if command:
# ProcessingLog.addToLog(command)
if executeAlgorithm(self.alg, parameters, context, self.feedback):
self.finish(context)
else:
QApplication.restoreOverrideCursor()
self.resetGUI()
result = executeAlgorithm(self.alg, parameters, context, self.feedback)
self.finish(result, context)
#TODO
#else:
# QApplication.restoreOverrideCursor()
# self.resetGUI()
except AlgorithmDialogBase.InvalidParameterValue as e:
try:
self.buttonBox.accepted.connect(lambda e=e:
@@ -247,10 +261,14 @@ def accept(self):
self.bar.pushMessage("", self.tr("Wrong or missing parameter value: {0}").format(e.parameter.description),
level=QgsMessageBar.WARNING, duration=5)

def finish(self, context):
def finish(self, result, context):
keepOpen = ProcessingConfig.getSetting(ProcessingConfig.KEEP_DIALOG_OPEN)

if self.iterateParam is None:

for o in self.getLayersToOpen():
context.addLayerToLoadOnCompletion(result[o])

if not handleAlgorithmResults(self.alg, context, self.feedback, not keepOpen):
self.resetGUI()
return
@@ -158,6 +158,9 @@ def fillTreeUsingProviders(self):
emptyItem.setEditable(False)

rootItem.insertRow(0, [groupItem, emptyItem])
if not group in settings:
continue

# add menu item only if it has any search matches
for setting in settings[group]:
if setting.hidden or setting.name.startswith("MENU_"):
@@ -33,7 +33,8 @@
from qgis.PyQt.QtCore import pyqtSignal
from qgis.PyQt.QtWidgets import QDialog

from qgis.core import QgsExpression
from qgis.core import (QgsExpression,
QgsProcessingParameterNumber)
from qgis.gui import QgsExpressionBuilderDialog
from processing.core.parameters import ParameterNumber, ParameterVector, ParameterRaster
from processing.core.outputs import OutputNumber, OutputVector, OutputRaster
@@ -63,8 +64,8 @@ def __init__(self, param, modelParametersDialog):

self.param = param
self.modelParametersDialog = modelParametersDialog
if param.default:
self.setValue(param.default)
if param.defaultValue():
self.setValue(param.defaultValue())
self.btnSelect.clicked.connect(self.showExpressionsBuilder)
self.leText.textChanged.connect(lambda: self.hasChanged.emit())

@@ -153,36 +154,36 @@ def __init__(self, param):
self.spnValue.setExpressionsEnabled(True)

self.param = param
if self.param.isInteger:
if self.param.dataType() == QgsProcessingParameterNumber.Integer:
self.spnValue.setDecimals(0)
else:
# Guess reasonable step value
if self.param.max is not None and self.param.min is not None:
if self.param.maximum() is not None and self.param.minimum() is not None:
try:
self.spnValue.setSingleStep(self.calculateStep(float(self.param.min), float(self.param.max)))
self.spnValue.setSingleStep(self.calculateStep(float(self.param.minimum()), float(self.param.maximum())))
except:
pass

if self.param.max is not None:
self.spnValue.setMaximum(self.param.max)
if self.param.maximum() is not None:
self.spnValue.setMaximum(self.param.maximum())
else:
self.spnValue.setMaximum(999999999)
if self.param.min is not None:
self.spnValue.setMinimum(self.param.min)
if self.param.minimum() is not None:
self.spnValue.setMinimum(self.param.minimum())
else:
self.spnValue.setMinimum(-999999999)

# set default value
if param.default is not None:
self.setValue(param.default)
if param.defaultValue() is not None:
self.setValue(param.defaultValue())
try:
self.spnValue.setClearValue(float(param.default))
self.spnValue.setClearValue(float(param.defaultValue()))
except:
pass
elif self.param.min is not None:
elif self.param.minimum() is not None:
try:
self.setValue(float(self.param.min))
self.spnValue.setClearValue(float(self.param.min))
self.setValue(float(self.param.minimum()))
self.spnValue.setClearValue(float(self.param.minimum()))
except:
pass
else:
@@ -55,6 +55,54 @@ def handleAlgorithmResults(alg, context, feedback=None, showResults=True):
feedback = QgsProcessingFeedback()
feedback.setProgressText(QCoreApplication.translate('Postprocessing', 'Loading resulting layers'))
i = 0
#for out in alg.outputs:
# feedback.setProgress(100 * i / float(len(alg.outputs)))
# if out.hidden or not out.open:
# continue
# if isinstance(out, (OutputRaster, OutputVector, OutputTable)):
# try:
# layer = QgsProcessingUtils.mapLayerFromString(out.value, context)
# if layer:
# layer.setName(out.description)
# QgsProject.instance().addMapLayer(context.temporaryLayerStore().takeMapLayer(layer))
# else:
# if ProcessingConfig.getSetting(
# ProcessingConfig.USE_FILENAME_AS_LAYER_NAME):
# name = os.path.basename(out.value)
# else:
# name = out.description
# dataobjects.load(out.value, name, alg.crs,
# RenderingStyles.getStyle(alg.id(),
# out.name))
# except Exception:
# QgsMessageLog.logMessage("Error loading result layer:\n" + traceback.format_exc(), 'Processing', QgsMessageLog.CRITICAL)
# wrongLayers.append(out.description)
# elif isinstance(out, OutputHTML):
# resultsList.addResult(alg.icon(), out.description, out.value)
# i += 1
i = 0
for l in context.layersToLoadOnCompletion():
feedback.setProgress(100 * i / float(len(context.layersToLoadOnCompletion())))
try:
layer = QgsProcessingUtils.mapLayerFromString(l, context)
if layer:
#TODO
#layer.setName(out.description)
QgsProject.instance().addMapLayer(context.temporaryLayerStore().takeMapLayer(layer))
else:
if ProcessingConfig.getSetting(
ProcessingConfig.USE_FILENAME_AS_LAYER_NAME):
name = os.path.basename(l)
else:
#TODO
name = l # out.description
dataobjects.load(l, name, alg.crs,
RenderingStyles.getStyle(alg.id(), l))
#out.name))
except Exception:
QgsMessageLog.logMessage("Error loading result layer:\n" + traceback.format_exc(), 'Processing', QgsMessageLog.CRITICAL)
#wrongLayers.append(out.description)
wrongLayers.append(l)
for out in alg.outputs:
feedback.setProgress(100 * i / float(len(alg.outputs)))
if out.hidden or not out.open:
@@ -723,8 +723,8 @@ def createWidget(self):
return MultipleInputPanel(options=self.param.options())
else:
widget = QComboBox()
for option in self.param.options():
widget.addItem(option[1], option[0])
for i, option in enumerate(self.param.options()):
widget.addItem(option, i)
if self.param.defaultValue():
widget.setCurrentIndex(widget.findData(self.param.defaultValue()))
return widget
@@ -1377,11 +1377,16 @@ bool QgsGeos::centroid( QgsPoint &pt, QString *errorMsg ) const
return false;
}

double x, y;
GEOSGeomGetX_r( geosinit.ctxt, geos.get(), &x );
GEOSGeomGetY_r( geosinit.ctxt, geos.get(), &y );
pt.setX( x );
pt.setY( y );
try
{
double x, y;
GEOSGeomGetX_r( geosinit.ctxt, geos.get(), &x );
GEOSGeomGetY_r( geosinit.ctxt, geos.get(), &y );
pt.setX( x );
pt.setY( y );
}
CATCH_GEOS_WITH_ERRMSG( false );

return true;
}

0 comments on commit c1d9d57

Please sign in to comment.
You can’t perform that action at this time.