Skip to content

Commit

Permalink
[processing] Remove expression buttons from parameters outside modeler
Browse files Browse the repository at this point in the history
Since these expressions were only evaluated immediately, it led to
confusing behavior for users who were expecting that the expression
would be applied per-feature.

Given that expressions can be directly entered into spin boxes, we already
have a way of users evaluating simple calculations for numeric
parameters at least.

I don't think there's a strong enough use case for needing to
calculate string results to leave the confusing expression builder
option in place.

This should be re-evaluated when we add UI support for dynamic
parameters (which are already supported in the backend), where
expressions are evaluated per-feature.

Fixes #17267
  • Loading branch information
nyalldawson committed Nov 10, 2017
1 parent abe5756 commit 612f516
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 68 deletions.
14 changes: 0 additions & 14 deletions python/plugins/processing/gui/DestinationSelectionPanel.py
Expand Up @@ -122,11 +122,6 @@ def selectOutput(self):
actionSaveToFile.triggered.connect(self.selectFile)
popupMenu.addAction(actionSaveToFile)

actionShowExpressionsBuilder = QAction(
self.tr('Use expression...'), self.btnSelect)
actionShowExpressionsBuilder.triggered.connect(self.showExpressionsBuilder)
popupMenu.addAction(actionShowExpressionsBuilder)

if isinstance(self.parameter, QgsProcessingParameterFeatureSink) \
and self.alg.provider().supportsNonFileBasedOutput():
actionSaveToSpatialite = QAction(
Expand All @@ -145,15 +140,6 @@ def selectOutput(self):

popupMenu.exec_(QCursor.pos())

def showExpressionsBuilder(self):
context = self.alg.createExpressionContext({}, createContext())
dlg = QgsExpressionBuilderDialog(None, self.leText.text(), self, 'generic',
context)
dlg.setWindowTitle(self.tr('Expression based output'))
if dlg.exec_() == QDialog.Accepted:
expression = QgsExpression(dlg.expressionText())
self.leText.setText(expression.evaluate(context))

def saveToTemporary(self):
if isinstance(self.parameter, QgsProcessingParameterFeatureSink) and self.alg.provider().supportsNonFileBasedOutput():
self.leText.setPlaceholderText(self.SAVE_TO_TEMP_LAYER)
Expand Down
26 changes: 7 additions & 19 deletions python/plugins/processing/gui/NumberInputPanel.py
Expand Up @@ -28,6 +28,7 @@

import os
import math
import sip

from qgis.PyQt import uic
from qgis.PyQt.QtCore import pyqtSignal
Expand Down Expand Up @@ -123,9 +124,7 @@ class NumberInputPanel(NUMBER_BASE, NUMBER_WIDGET):

"""
Number input panel for use outside the modeller - this input panel
contains a user friendly spin box for entering values. It also
allows expressions to be evaluated, but these expressions are evaluated
immediately after entry and are not stored anywhere.
contains a user friendly spin box for entering values.
"""

hasChanged = pyqtSignal()
Expand Down Expand Up @@ -172,24 +171,13 @@ def __init__(self, param):
else:
self.setValue(0)
self.spnValue.setClearValue(0)
self.btnSelect.setFixedHeight(self.spnValue.height())

self.btnSelect.clicked.connect(self.showExpressionsBuilder)
self.spnValue.valueChanged.connect(lambda: self.hasChanged.emit())

def showExpressionsBuilder(self):
context = createExpressionContext()
dlg = QgsExpressionBuilderDialog(None, str(self.spnValue.value()), self, 'generic', context)
# we don't show the expression button outside of modeler
self.layout().removeWidget(self.btnSelect)
sip.delete(self.btnSelect)
self.btnSelect = None

dlg.setWindowTitle(self.tr('Expression based input'))
if dlg.exec_() == QDialog.Accepted:
exp = QgsExpression(dlg.expressionText())
if not exp.hasParserError():
try:
val = float(exp.evaluate(context))
self.setValue(val)
except:
return
self.spnValue.valueChanged.connect(lambda: self.hasChanged.emit())

def getValue(self):
return self.spnValue.value()
Expand Down
34 changes: 2 additions & 32 deletions python/plugins/processing/gui/wrappers.py
Expand Up @@ -229,36 +229,6 @@ def getFileName(self, initial_value=''):
return filename, selected_filter


class ExpressionWidgetWrapperMixin():

def wrapWithExpressionButton(self, basewidget):
expr_button = QToolButton()
expr_button.clicked.connect(self.showExpressionsBuilder)
expr_button.setText('…')

layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(basewidget)
layout.addWidget(expr_button)

widget = QWidget()
widget.setLayout(layout)

return widget

def showExpressionsBuilder(self):
context = dataobjects.createExpressionContext()
value = self.value()
if not isinstance(value, str):
value = ''
dlg = QgsExpressionBuilderDialog(None, value, self.widget, 'generic', context)
dlg.setWindowTitle(self.tr('Expression based input'))
if dlg.exec_() == QDialog.Accepted:
exp = QgsExpression(dlg.expressionText())
if not exp.hasParserError():
self.setValue(dlg.expressionText())


class BasicWidgetWrapper(WidgetWrapper):

def createWidget(self):
Expand Down Expand Up @@ -1032,15 +1002,15 @@ def validator(v):
return self.comboValue(validator, combobox=self.combo)


class StringWidgetWrapper(WidgetWrapper, ExpressionWidgetWrapperMixin):
class StringWidgetWrapper(WidgetWrapper):

def createWidget(self):
if self.dialogType == DIALOG_STANDARD:
if self.param.multiLine():
widget = QPlainTextEdit()
else:
self._lineedit = QLineEdit()
return self.wrapWithExpressionButton(self._lineedit)
widget = self._lineedit

elif self.dialogType == DIALOG_BATCH:
widget = QLineEdit()
Expand Down
6 changes: 3 additions & 3 deletions python/plugins/processing/gui/wrappers_postgis.py
Expand Up @@ -47,7 +47,7 @@ def createWidget(self):
for group in self.items():
self._combo.addItem(*group)
self._combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
return self.wrapWithExpressionButton(self._combo)
return self._combo

def items(self):
settings = QgsSettings()
Expand Down Expand Up @@ -86,7 +86,7 @@ def createWidget(self, connection_param=None):
self._combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
self._combo.lineEdit().editingFinished.connect(lambda: self.widgetValueHasChanged.emit(self))

return self.wrapWithExpressionButton(self._combo)
return self._combo

def postInitialize(self, wrappers):
for wrapper in wrappers:
Expand Down Expand Up @@ -158,7 +158,7 @@ def createWidget(self, schema_param=None):
self._combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
self._combo.lineEdit().editingFinished.connect(lambda: self.widgetValueHasChanged.emit(self))

return self.wrapWithExpressionButton(self._combo)
return self._combo

def postInitialize(self, wrappers):
for wrapper in wrappers:
Expand Down

0 comments on commit 612f516

Please sign in to comment.