Skip to content

Commit

Permalink
[processing] fix handling of the "selection" type settings
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy committed Jan 12, 2017
1 parent b823874 commit 03eaad5
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 30 deletions.
83 changes: 53 additions & 30 deletions python/plugins/processing/core/ProcessingConfig.py
Expand Up @@ -31,10 +31,9 @@

from qgis.PyQt.QtCore import QCoreApplication, QSettings, QObject, pyqtSignal
from qgis.PyQt.QtGui import QIcon
from qgis.core import (NULL,
QgsApplication)
from qgis.core import NULL, QgsApplication
from processing.tools.system import defaultOutputFolder
import processing.tools.dataobjects
from processing.tools import dataobjects


class SettingsWatcher(QObject):
Expand Down Expand Up @@ -87,14 +86,6 @@ def initialize():
ProcessingConfig.tr('General'),
ProcessingConfig.USE_SELECTED,
ProcessingConfig.tr('Use only selected features'), True))
invalidFeaturesOptions = [ProcessingConfig.tr('Do not filter (better performance'),
ProcessingConfig.tr('Ignore features with invalid geometries'),
ProcessingConfig.tr('Stop algorithm execution when a geometry is invalid')]
ProcessingConfig.addSetting(Setting(
ProcessingConfig.tr('General'),
ProcessingConfig.FILTER_INVALID_GEOMETRIES,
ProcessingConfig.tr('Invalid features filtering'), invalidFeaturesOptions[2],
valuetype=Setting.SELECTION, options=invalidFeaturesOptions))
ProcessingConfig.addSetting(Setting(
ProcessingConfig.tr('General'),
ProcessingConfig.USE_FILENAME_AS_LAYER_NAME,
Expand Down Expand Up @@ -163,18 +154,35 @@ def initialize():
ProcessingConfig.MODELS_SCRIPTS_REPO,
ProcessingConfig.tr('Scripts and models repository'),
'https://raw.githubusercontent.com/qgis/QGIS-Processing/master'))
extensions = processing.tools.dataobjects.getSupportedOutputVectorLayerExtensions()

invalidFeaturesOptions = [ProcessingConfig.tr('Do not filter (better performance'),
ProcessingConfig.tr('Ignore features with invalid geometries'),
ProcessingConfig.tr('Stop algorithm execution when a geometry is invalid')]
ProcessingConfig.addSetting(Setting(
ProcessingConfig.tr('General'),
ProcessingConfig.FILTER_INVALID_GEOMETRIES,
ProcessingConfig.tr('Invalid features filtering'),
invalidFeaturesOptions[2],
valuetype=Setting.SELECTION,
options=invalidFeaturesOptions))

extensions = dataobjects.getSupportedOutputVectorLayerExtensions()
ProcessingConfig.addSetting(Setting(
ProcessingConfig.tr('General'),
ProcessingConfig.DEFAULT_OUTPUT_VECTOR_LAYER_EXT,
ProcessingConfig.tr('Default output vector layer extension'), extensions[0],
valuetype=Setting.SELECTION, options=extensions))
extensions = processing.tools.dataobjects.getSupportedOutputRasterLayerExtensions()
ProcessingConfig.tr('Default output vector layer extension'),
extensions[0],
valuetype=Setting.SELECTION,
options=extensions))

extensions = dataobjects.getSupportedOutputRasterLayerExtensions()
ProcessingConfig.addSetting(Setting(
ProcessingConfig.tr('General'),
ProcessingConfig.DEFAULT_OUTPUT_RASTER_LAYER_EXT,
ProcessingConfig.tr('Default output raster layer extension'), extensions[0],
valuetype=Setting.SELECTION, options=extensions))
ProcessingConfig.tr('Default output raster layer extension'),
extensions[0],
valuetype=Setting.SELECTION,
options=extensions))

@staticmethod
def setGroupIcon(group, icon):
Expand Down Expand Up @@ -224,14 +232,20 @@ def getSetting(name):
v = None
except:
pass
return v
if ProcessingConfig.settings[name].valuetype == Setting.SELECTION:
return ProcessingConfig.settings[name].options.index(v)
else:
return v
else:
return None

@staticmethod
def setSettingValue(name, value):
if name in list(ProcessingConfig.settings.keys()):
ProcessingConfig.settings[name].setValue(value)
if ProcessingConfig.settings[name].valuetype == Setting.SELECTION:
ProcessingConfig.settings[name].setValue(ProcessingConfig.settings[name].options[value])
else:
ProcessingConfig.settings[name].setValue(value)
ProcessingConfig.settings[name].save()

@staticmethod
Expand Down Expand Up @@ -261,34 +275,36 @@ def __init__(self, group, name, description, default, hidden=False, valuetype=No
self.description = description
self.default = default
self.hidden = hidden
if valuetype is None:
if isinstance(default, int):
valuetype = self.INT
elif isinstance(default, float):
valuetype = self.FLOAT
self.valuetype = valuetype
self.options = options

if self.valuetype is None:
if isinstance(default, int):
self.valuetype = self.INT
elif isinstance(default, float):
self.valuetype = self.FLOAT

if validator is None:
if valuetype == self.FLOAT:
if self.valuetype == self.FLOAT:
def checkFloat(v):
try:
float(v)
except ValueError:
raise ValueError(self.tr('Wrong parameter value:\n%s') % str(v))
validator = checkFloat
elif valuetype == self.INT:
elif self.valuetype == self.INT:
def checkInt(v):
try:
int(v)
except ValueError:
raise ValueError(self.tr('Wrong parameter value:\n%s') % str(v))
validator = checkInt
elif valuetype in [self.FILE, self.FOLDER]:
elif self.valuetype in [self.FILE, self.FOLDER]:
def checkFileOrFolder(v):
if v and not os.path.exists(v):
raise ValueError(self.tr('Specified path does not exist:\n%s') % str(v))
validator = checkFileOrFolder
elif valuetype == self.MULTIPLE_FOLDERS:
elif self.valuetype == self.MULTIPLE_FOLDERS:
def checkMultipleFolders(v):
folders = v.split(';')
for f in folders:
Expand All @@ -310,10 +326,17 @@ def read(self, qsettings=QSettings()):
if value is not None:
if isinstance(self.value, bool):
value = str(value).lower() == str(True).lower()
self.value = value

if self.valuetype == self.SELECTION:
self.value = self.options[int(value)]
else:
self.value = value

def save(self, qsettings=QSettings()):
qsettings.setValue(self.qname, self.value)
if self.valuetype == self.SELECTION:
qsettings.setValue(self.qname, self.options.index(self.value))
else:
qsettings.setValue(self.qname, self.value)

def __str__(self):
return self.name + '=' + str(self.value)
Expand Down
23 changes: 23 additions & 0 deletions python/plugins/processing/tests/ToolsTest.py
Expand Up @@ -59,6 +59,10 @@ def testFeatures(self):
test_data = points()
test_layer = QgsVectorLayer(test_data, 'test', 'ogr')

# disable check for geometry validity
prevInvalidGeoms = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, 0)

# test with all features
features = vector.features(test_layer)
self.assertEqual(len(features), 9)
Expand Down Expand Up @@ -101,9 +105,22 @@ def testFeatures(self):

ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)

# test exception is raised when filtering invalid geoms
#ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, 2)
#test_layer_invalid_geoms = QgsVectorLayer(invalid_geometries(), 'test', 'ogr')
#with self.assertRaises(GeoAlgorithmExecutionException):
# features = vector.features(test_layer_invalid_geoms)
# feats = [f for f in features]

ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, prevInvalidGeoms)

def testValues(self):
ProcessingConfig.initialize()

# disable check for geometry validity
prevInvalidGeoms = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, 0)

test_data = points()
test_layer = QgsVectorLayer(test_data, 'test', 'ogr')

Expand Down Expand Up @@ -138,10 +155,15 @@ def testValues(self):
self.assertEqual(set(res[1]), set([5, 7, 3]))

ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, prevInvalidGeoms)

def testUniqueValues(self):
ProcessingConfig.initialize()

# disable check for geometry validity
prevInvalidGeoms = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES)
ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, 0)

test_data = points()
test_layer = QgsVectorLayer(test_data, 'test', 'ogr')

Expand All @@ -164,6 +186,7 @@ def testUniqueValues(self):
self.assertEqual(set(v), set([5, 7, 3]))

ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, prevInvalidGeoms)

def testOgrLayerNameExtraction(self):
outdir = tempfile.mkdtemp()
Expand Down

3 comments on commit 03eaad5

@m-kuhn
Copy link
Member

@m-kuhn m-kuhn commented on 03eaad5 Jan 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails for me with

ValueError: invalid literal for int() with base 10: 'tif'

@alexbruy
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably you have settings file from previous installation. I will add code to handle this.

@nirvn
Copy link
Contributor

@nirvn nirvn commented on 03eaad5 Jan 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexbruy , I'm pretty sure that has broken getDefaultFileExtension() -- try gdal's build virtual raster (and leave the output as temporary file). It'll fail (while it used to work OK >1 week ago).

Please sign in to comment.