From 482aadc495daae625c69b0b632ec3e67b038cc24 Mon Sep 17 00:00:00 2001 From: "arnaud.morvan@camptocamp.com" Date: Thu, 9 Feb 2017 16:05:54 +0100 Subject: [PATCH 1/5] [processing] Add possibility to pass additionnal parameters to widget wrapper --- python/plugins/processing/core/parameters.py | 7 ++++++- python/plugins/processing/gui/wrappers.py | 10 ++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/python/plugins/processing/core/parameters.py b/python/plugins/processing/core/parameters.py index 089bca31312..884d12c5862 100644 --- a/python/plugins/processing/core/parameters.py +++ b/python/plugins/processing/core/parameters.py @@ -178,6 +178,11 @@ class Parameter(object): def wrapper(self, dialog, row=0, col=0): wrapper = self.metadata.get('widget_wrapper', None) + params = {} + # wrapper metadata should be a dict with class key + if isinstance(wrapper, dict): + params = deepcopy(wrapper) + wrapper = params.pop('class') # wrapper metadata should be a class path if isinstance(wrapper, str): tokens = wrapper.split('.') @@ -185,7 +190,7 @@ class Parameter(object): wrapper = getattr(mod, tokens[-1]) # or directly a class object if isclass(wrapper): - wrapper = wrapper(self, dialog, row, col) + wrapper = wrapper(self, dialog, row, col, **params) # or a wrapper instance return wrapper diff --git a/python/plugins/processing/gui/wrappers.py b/python/plugins/processing/gui/wrappers.py index 04d3d828800..83bab557c6c 100644 --- a/python/plugins/processing/gui/wrappers.py +++ b/python/plugins/processing/gui/wrappers.py @@ -2,7 +2,7 @@ """ *************************************************************************** - wrappers.py + wrappers.py - Standard parameters widget wrappers --------------------- Date : May 2016 Copyright : (C) 2016 by Arnaud Morvan, Victor Olaya @@ -17,8 +17,6 @@ * * *************************************************************************** """ -from builtins import str -from builtins import range __author__ = 'Arnaud Morvan' @@ -101,14 +99,14 @@ class WidgetWrapper(QObject): widgetValueHasChanged = pyqtSignal(object) - def __init__(self, param, dialog, row=0, col=0): + def __init__(self, param, dialog, row=0, col=0, **kwargs): QObject.__init__(self) self.param = param self.dialog = dialog self.row = row self.col = col self.dialogType = dialogTypes.get(dialog.__class__.__name__, DIALOG_STANDARD) - self.widget = self.createWidget() + self.widget = self.createWidget(**kwargs) if param.default is not None: self.setValue(param.default) @@ -123,7 +121,7 @@ class WidgetWrapper(QObject): return v return combobox.currentData() - def createWidget(self): + def createWidget(self, **kwargs): pass def setValue(self, value): From dda667023a6cdedb813b1926f0c3d79276255ba3 Mon Sep 17 00:00:00 2001 From: "arnaud.morvan@camptocamp.com" Date: Thu, 9 Feb 2017 16:06:34 +0100 Subject: [PATCH 2/5] [processing] Add class ExpressionEnabledWidgetWrapper --- python/plugins/processing/gui/wrappers.py | 68 +++++++++++++++++++---- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/python/plugins/processing/gui/wrappers.py b/python/plugins/processing/gui/wrappers.py index 83bab557c6c..8b318721b74 100644 --- a/python/plugins/processing/gui/wrappers.py +++ b/python/plugins/processing/gui/wrappers.py @@ -32,16 +32,34 @@ import locale import os from functools import cmp_to_key -from qgis.core import QgsCoordinateReferenceSystem, QgsApplication, QgsWkbTypes, QgsMapLayerProxyModel -from qgis.PyQt.QtWidgets import QCheckBox, QComboBox, QLineEdit, QPlainTextEdit, QWidget, QHBoxLayout, QToolButton, QFileDialog -from qgis.gui import (QgsFieldExpressionWidget, - QgsExpressionLineEdit, - QgsProjectionSelectionWidget, - QgsGenericProjectionSelector, - QgsFieldComboBox, - QgsFieldProxyModel, - QgsMapLayerComboBox - ) +from qgis.core import ( + QgsApplication, + QgsCoordinateReferenceSystem, + QgsExpression, + QgsMapLayerProxyModel, + QgsWkbTypes, +) +from qgis.PyQt.QtWidgets import ( + QCheckBox, + QComboBox, + QDialog, + QFileDialog, + QHBoxLayout, + QLineEdit, + QPlainTextEdit, + QToolButton, + QWidget, +) +from qgis.gui import ( + QgsExpressionLineEdit, + QgsExpressionBuilderDialog, + QgsFieldComboBox, + QgsFieldExpressionWidget, + QgsFieldProxyModel, + QgsGenericProjectionSelector, + QgsMapLayerComboBox, + QgsProjectionSelectionWidget, +) from qgis.PyQt.QtCore import pyqtSignal, QObject, QVariant, QSettings from processing.gui.NumberInputPanel import NumberInputPanel, ModellerNumberInputPanel @@ -175,6 +193,36 @@ class WidgetWrapper(QObject): return filename, selected_filter +class ExpressionEnabledWidgetWrapper(WidgetWrapper): + + def createWidget(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 = self.param.expressionContext() + 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): From c768edf9d1ca27b4c6dfb7f3fcd3995b6c9afb59 Mon Sep 17 00:00:00 2001 From: "arnaud.morvan@camptocamp.com" Date: Thu, 9 Feb 2017 16:07:24 +0100 Subject: [PATCH 3/5] [processing] Add postgis widget wrappers --- .../algs/gdal/ogr2ogrtopostgislist.py | 41 ++-- .../processing/algs/qgis/ImportIntoPostGIS.py | 35 ++- .../processing/algs/qgis/PostGISExecuteSQL.py | 9 +- python/plugins/processing/gui/wrappers.py | 4 +- .../processing/gui/wrappers_postgis.py | 207 ++++++++++++++++++ 5 files changed, 265 insertions(+), 31 deletions(-) create mode 100644 python/plugins/processing/gui/wrappers_postgis.py diff --git a/python/plugins/processing/algs/gdal/ogr2ogrtopostgislist.py b/python/plugins/processing/algs/gdal/ogr2ogrtopostgislist.py index 30640b48fc5..3a361c59d3c 100644 --- a/python/plugins/processing/algs/gdal/ogr2ogrtopostgislist.py +++ b/python/plugins/processing/algs/gdal/ogr2ogrtopostgislist.py @@ -27,8 +27,6 @@ __copyright__ = '(C) 2012, Victor Olaya' __revision__ = '$Format:%H$' -from qgis.PyQt.QtCore import QSettings - from processing.core.parameters import ParameterVector from processing.core.parameters import ParameterString from processing.core.parameters import ParameterCrs @@ -87,17 +85,15 @@ class Ogr2OgrToPostGisList(GdalAlgorithm): GdalAlgorithm.__init__(self) self.processing = False - def dbConnectionNames(self): - settings = QSettings() - settings.beginGroup('/PostgreSQL/connections/') - return settings.childGroups() - def defineCharacteristics(self): self.name, self.i18n_name = self.trAlgorithm('Import Vector into PostGIS database (available connections)') self.group, self.i18n_group = self.trAlgorithm('[OGR] Miscellaneous') - self.DB_CONNECTIONS = self.dbConnectionNames() - self.addParameter(ParameterSelection(self.DATABASE, - self.tr('Database (connection name)'), self.DB_CONNECTIONS)) + self.addParameter(ParameterString( + self.DATABASE, + self.tr('Database (connection name)'), + metadata={ + 'widget_wrapper': { + 'class': 'processing.gui.wrappers_postgis.ConnectionWidgetWrapper'}})) self.addParameter(ParameterVector(self.INPUT_LAYER, self.tr('Input layer'))) self.addParameter(ParameterString(self.SHAPE_ENCODING, @@ -110,11 +106,24 @@ class Ogr2OgrToPostGisList(GdalAlgorithm): self.tr('Reproject to this CRS on output '), '', optional=True)) self.addParameter(ParameterCrs(self.S_SRS, self.tr('Override source CRS'), '', optional=True)) - self.addParameter(ParameterString(self.SCHEMA, - self.tr('Schema name'), 'public', optional=True)) - self.addParameter(ParameterString(self.TABLE, - self.tr('Table name, leave blank to use input name'), - '', optional=True)) + self.addParameter(ParameterString( + self.SCHEMA, + self.tr('Schema name'), + 'public', + optional=True, + metadata={ + 'widget_wrapper': { + 'class': 'processing.gui.wrappers_postgis.SchemaWidgetWrapper', + 'connection_param': self.DATABASE}})) + self.addParameter(ParameterString( + self.TABLE, + self.tr('Table name, leave blank to use input name'), + '', + optional=True, + metadata={ + 'widget_wrapper': { + 'class': 'processing.gui.wrappers_postgis.TableWidgetWrapper', + 'schema_param': self.SCHEMA}})) self.addParameter(ParameterString(self.PK, self.tr('Primary key (new field)'), 'id', optional=True)) self.addParameter(ParameterTableField(self.PRIMARY_KEY, @@ -168,7 +177,7 @@ class Ogr2OgrToPostGisList(GdalAlgorithm): self.processing = False def getConsoleCommands(self): - connection = self.DB_CONNECTIONS[self.getParameterValue(self.DATABASE)] + connection = self.getParameterValue(self.DATABASE) uri = uri_from_name(connection) if self.processing: # to get credentials input when needed diff --git a/python/plugins/processing/algs/qgis/ImportIntoPostGIS.py b/python/plugins/processing/algs/qgis/ImportIntoPostGIS.py index bbb58b96f0d..ffbed0acaac 100644 --- a/python/plugins/processing/algs/qgis/ImportIntoPostGIS.py +++ b/python/plugins/processing/algs/qgis/ImportIntoPostGIS.py @@ -33,7 +33,6 @@ from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecution from processing.core.parameters import ParameterBoolean from processing.core.parameters import ParameterVector from processing.core.parameters import ParameterString -from processing.core.parameters import ParameterSelection from processing.core.parameters import ParameterTableField from processing.tools import dataobjects, postgis @@ -58,14 +57,30 @@ class ImportIntoPostGIS(GeoAlgorithm): self.group, self.i18n_group = self.trAlgorithm('Database') self.addParameter(ParameterVector(self.INPUT, self.tr('Layer to import'))) - - self.DB_CONNECTIONS = self.dbConnectionNames() - self.addParameter(ParameterSelection(self.DATABASE, - self.tr('Database (connection name)'), self.DB_CONNECTIONS)) - self.addParameter(ParameterString(self.SCHEMA, - self.tr('Schema (schema name)'), 'public')) - self.addParameter(ParameterString(self.TABLENAME, - self.tr('Table to import to (leave blank to use layer name)'), optional=True)) + self.addParameter(ParameterString( + self.DATABASE, + self.tr('Database (connection name)'), + metadata={ + 'widget_wrapper': { + 'class': 'processing.gui.wrappers_postgis.ConnectionWidgetWrapper'}})) + self.addParameter(ParameterString( + self.SCHEMA, + self.tr('Schema (schema name)'), + 'public', + optional=True, + metadata={ + 'widget_wrapper': { + 'class': 'processing.gui.wrappers_postgis.SchemaWidgetWrapper', + 'connection_param': self.DATABASE}})) + self.addParameter(ParameterString( + self.TABLENAME, + self.tr('Table to import to (leave blank to use layer name)'), + '', + optional=True, + metadata={ + 'widget_wrapper': { + 'class': 'processing.gui.wrappers_postgis.TableWidgetWrapper', + 'schema_param': self.SCHEMA}})) self.addParameter(ParameterTableField(self.PRIMARY_KEY, self.tr('Primary key field'), self.INPUT, optional=True)) self.addParameter(ParameterString(self.GEOMETRY_COLUMN, @@ -85,7 +100,7 @@ class ImportIntoPostGIS(GeoAlgorithm): self.tr('Create single-part geometries instead of multi-part'), False)) def processAlgorithm(self, feedback): - connection = self.DB_CONNECTIONS[self.getParameterValue(self.DATABASE)] + connection = self.getParameterValue(self.DATABASE) db = postgis.GeoDB.from_name(connection) schema = self.getParameterValue(self.SCHEMA) diff --git a/python/plugins/processing/algs/qgis/PostGISExecuteSQL.py b/python/plugins/processing/algs/qgis/PostGISExecuteSQL.py index 07401d86c69..1d34180873d 100644 --- a/python/plugins/processing/algs/qgis/PostGISExecuteSQL.py +++ b/python/plugins/processing/algs/qgis/PostGISExecuteSQL.py @@ -26,8 +26,6 @@ __copyright__ = '(C) 2012, Victor Olaya, Carterix Geomatics' __revision__ = '$Format:%H$' -from qgis.PyQt.QtCore import QSettings - from processing.core.GeoAlgorithm import GeoAlgorithm from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException from processing.core.parameters import ParameterString @@ -42,7 +40,12 @@ class PostGISExecuteSQL(GeoAlgorithm): def defineCharacteristics(self): self.name, self.i18n_name = self.trAlgorithm('PostGIS execute SQL') self.group, self.i18n_group = self.trAlgorithm('Database') - self.addParameter(ParameterString(self.DATABASE, self.tr('Database'))) + self.addParameter(ParameterString( + self.DATABASE, + self.tr('Database'), + metadata={ + 'widget_wrapper': { + 'class': 'processing.gui.wrappers_postgis.ConnectionWidgetWrapper'}})) self.addParameter(ParameterString(self.SQL, self.tr('SQL query'), '', True)) def processAlgorithm(self, feedback): diff --git a/python/plugins/processing/gui/wrappers.py b/python/plugins/processing/gui/wrappers.py index 8b318721b74..eb2d2317d04 100644 --- a/python/plugins/processing/gui/wrappers.py +++ b/python/plugins/processing/gui/wrappers.py @@ -193,9 +193,9 @@ class WidgetWrapper(QObject): return filename, selected_filter -class ExpressionEnabledWidgetWrapper(WidgetWrapper): +class ExpressionWidgetWrapperMixin(): - def createWidget(self, basewidget): + def wrapWithExpressionButton(self, basewidget): expr_button = QToolButton() expr_button.clicked.connect(self.showExpressionsBuilder) expr_button.setText('...') diff --git a/python/plugins/processing/gui/wrappers_postgis.py b/python/plugins/processing/gui/wrappers_postgis.py new file mode 100644 index 00000000000..d8362ebd32c --- /dev/null +++ b/python/plugins/processing/gui/wrappers_postgis.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + postgis.py - Postgis widget wrappers + --------------------- + Date : December 2016 + Copyright : (C) 2016 by Arnaud Morvan + Email : arnaud dot morvan at camptocamp 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. * +* * +*************************************************************************** +""" + + +from qgis.PyQt.QtCore import QSettings +from qgis.PyQt.QtWidgets import QComboBox + +from processing.core.parameters import ( + ParameterString, + ParameterNumber, + ParameterFile, + ParameterTableField, + ParameterExpression +) +from processing.core.outputs import OutputString +from processing.gui.wrappers import ( + WidgetWrapper, + ExpressionWidgetWrapperMixin, + DIALOG_MODELER, +) +from processing.tools.postgis import GeoDB + + +class ConnectionWidgetWrapper(WidgetWrapper, ExpressionWidgetWrapperMixin): + """ + WidgetWrapper for ParameterString that create and manage a combobox widget + with existing postgis connections. + """ + + def createWidget(self): + self._combo = QComboBox() + for group in self.items(): + self._combo.addItem(*group) + self._combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self)) + return self.wrapWithExpressionButton(self._combo) + + def items(self): + settings = QSettings() + settings.beginGroup('/PostgreSQL/connections/') + items = [(group, group) for group in settings.childGroups()] + + if self.dialogType == DIALOG_MODELER: + strings = self.dialog.getAvailableValuesOfType( + [ParameterString, ParameterNumber, ParameterFile, + ParameterTableField, ParameterExpression], OutputString) + items = items + [(self.dialog.resolveValueDescription(s), s) for s in strings] + + return items + + def setValue(self, value): + self.setComboValue(value, self._combo) + + def value(self): + return self.comboValue(combobox=self._combo) + + +class SchemaWidgetWrapper(WidgetWrapper, ExpressionWidgetWrapperMixin): + """ + WidgetWrapper for ParameterString that create and manage a combobox widget + with existing schemas from a parent connection parameter. + """ + + def createWidget(self, connection_param=None): + self._connection_param = connection_param + self._connection = None + self._database = None + + self._combo = QComboBox() + self._combo.setEditable(True) + self.refreshItems() + self._combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self)) + self._combo.lineEdit().editingFinished.connect(lambda: self.widgetValueHasChanged.emit(self)) + + return self.wrapWithExpressionButton(self._combo) + + def postInitialize(self, wrappers): + for wrapper in wrappers: + if wrapper.param.name == self._connection_param: + self.connection_wrapper = wrapper + self.setConnection(wrapper.value()) + wrapper.widgetValueHasChanged.connect(self.connectionChanged) + break + + def connectionChanged(self, wrapper): + connection = wrapper.value() + if connection == self._connection: + return + self.setConnection(connection) + + def setConnection(self, connection): + self._connection = connection + if isinstance(connection, str): + self._database = GeoDB.from_name(connection) + else: + self._database = None + self.refreshItems() + self.widgetValueHasChanged.emit(self) + + def refreshItems(self): + value = self.comboValue(combobox=self._combo) + + self._combo.clear() + + if self._database is not None: + for schema in self._database.list_schemas(): + self._combo.addItem(schema[1], schema[1]) + + if self.dialogType == DIALOG_MODELER: + strings = self.dialog.getAvailableValuesOfType( + [ParameterString, ParameterNumber, ParameterFile, + ParameterTableField, ParameterExpression], OutputString) + for text, data in [(self.dialog.resolveValueDescription(s), s) for s in strings]: + self._combo.addItem(text, data) + + self.setComboValue(value, self._combo) + + def setValue(self, value): + self.setComboValue(value, self._combo) + self.widgetValueHasChanged.emit(self) + + def value(self): + return self.comboValue(combobox=self._combo) + + def database(self): + return self._database + + +class TableWidgetWrapper(WidgetWrapper, ExpressionWidgetWrapperMixin): + """ + WidgetWrapper for ParameterString that create and manage a combobox widget + with existing tables from a parent schema parameter. + """ + + def createWidget(self, schema_param=None): + self._schema_param = schema_param + self._database = None + self._schema = None + + self._combo = QComboBox() + self._combo.setEditable(True) + self.refreshItems() + self._combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self)) + self._combo.lineEdit().editingFinished.connect(lambda: self.widgetValueHasChanged.emit(self)) + + return self.wrapWithExpressionButton(self._combo) + + def postInitialize(self, wrappers): + for wrapper in wrappers: + if wrapper.param.name == self._schema_param: + self.schema_wrapper = wrapper + self.setSchema(wrapper.database(), wrapper.value()) + wrapper.widgetValueHasChanged.connect(self.schemaChanged) + break + + def schemaChanged(self, wrapper): + database = wrapper.database() + schema = wrapper.value() + if database == self._database and schema == self._schema: + return + self.setSchema(database, schema) + + def setSchema(self, database, schema): + self._database = database + self._schema = schema + self.refreshItems() + self.widgetValueHasChanged.emit(self) + + def refreshItems(self): + value = self.comboValue(combobox=self._combo) + + self._combo.clear() + + if (self._database is not None and isinstance(self._schema, str)): + for table in self._database.list_geotables(self._schema): + self._combo.addItem(table[0], table[0]) + + if self.dialogType == DIALOG_MODELER: + strings = self.dialog.getAvailableValuesOfType( + [ParameterString, ParameterNumber, ParameterFile, + ParameterTableField, ParameterExpression], OutputString) + for text, data in [(self.dialog.resolveValueDescription(s), s) for s in strings]: + self._combo.addItem(text, data) + + self.setComboValue(value, self._combo) + + def setValue(self, value): + self.setComboValue(value, self._combo) + self.widgetValueHasChanged.emit(self) + + def value(self): + return self.comboValue(combobox=self._combo) From 7bffef7044549c2ff96ab54b1066aab6588d731b Mon Sep 17 00:00:00 2001 From: "arnaud.morvan@camptocamp.com" Date: Thu, 9 Feb 2017 16:08:45 +0100 Subject: [PATCH 4/5] [processing] Fix ModelerParametersDialog when len(widget) == 0 --- python/plugins/processing/modeler/ModelerParametersDialog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/plugins/processing/modeler/ModelerParametersDialog.py b/python/plugins/processing/modeler/ModelerParametersDialog.py index c5b0fa8c815..16112060c4a 100644 --- a/python/plugins/processing/modeler/ModelerParametersDialog.py +++ b/python/plugins/processing/modeler/ModelerParametersDialog.py @@ -146,7 +146,7 @@ class ModelerParametersDialog(QDialog): self.wrappers[param.name] = wrapper widget = wrapper.widget - if widget: + if widget is not None: self.valueItems[param.name] = widget if param.name in list(tooltips.keys()): tooltip = tooltips[param.name] From 337d1889b8032bfbbdb077e57cec93b88f3cc135 Mon Sep 17 00:00:00 2001 From: "arnaud.morvan@camptocamp.com" Date: Fri, 10 Feb 2017 10:10:32 +0100 Subject: [PATCH 5/5] [processing] Use ExpressionWidgetWrapperMixin in StringWidgetWrapper --- .../processing/gui/StringInputPanel.py | 74 ------------------- python/plugins/processing/gui/wrappers.py | 27 +++---- 2 files changed, 14 insertions(+), 87 deletions(-) delete mode 100644 python/plugins/processing/gui/StringInputPanel.py diff --git a/python/plugins/processing/gui/StringInputPanel.py b/python/plugins/processing/gui/StringInputPanel.py deleted file mode 100644 index fdcce13cfae..00000000000 --- a/python/plugins/processing/gui/StringInputPanel.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -*************************************************************************** - NumberInputPanel.py - --------------------- - Date : August 2016 - Copyright : (C) 2016 by Victor Olaya - Email : volayaf 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. * -* * -*************************************************************************** -""" -from builtins import str - -__author__ = 'Victor Olaya' -__date__ = 'August 2016' -__copyright__ = '(C) 2016, Victor Olaya' - -# This will get replaced with a git SHA1 when you do a git archive - -__revision__ = '$Format:%H$' - -import os - -from qgis.PyQt import uic -from qgis.PyQt.QtCore import pyqtSignal -from qgis.PyQt.QtWidgets import QDialog - -from qgis.core import (QgsDataSourceUri, - QgsCredentials, - QgsExpression, - QgsRasterLayer) -from qgis.gui import QgsEncodingFileDialog, QgsExpressionBuilderDialog -from qgis.utils import iface - -pluginPath = os.path.split(os.path.dirname(__file__))[0] -WIDGET, BASE = uic.loadUiType( - os.path.join(pluginPath, 'ui', 'widgetBaseSelector.ui')) - - -class StringInputPanel(BASE, WIDGET): - - hasChanged = pyqtSignal() - - def __init__(self, param): - super(StringInputPanel, self).__init__(None) - self.setupUi(self) - - self.param = param - self.text = param.default - - self.btnSelect.clicked.connect(self.showExpressionsBuilder) - self.leText.textChanged.connect(lambda: self.hasChanged.emit()) - - def showExpressionsBuilder(self): - context = self.param.expressionContext() - dlg = QgsExpressionBuilderDialog(None, self.leText.text(), self, '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()) - - def getValue(self): - return self.leText.text() - - def setValue(self, value): - self.leText.setText(str(value)) diff --git a/python/plugins/processing/gui/wrappers.py b/python/plugins/processing/gui/wrappers.py index eb2d2317d04..5c11588c164 100644 --- a/python/plugins/processing/gui/wrappers.py +++ b/python/plugins/processing/gui/wrappers.py @@ -88,7 +88,6 @@ from processing.gui.MultipleInputPanel import MultipleInputPanel from processing.gui.BatchInputSelectionPanel import BatchInputSelectionPanel from processing.gui.FixedTablePanel import FixedTablePanel from processing.gui.ExtentSelectionPanel import ExtentSelectionPanel -from processing.gui.StringInputPanel import StringInputPanel DIALOG_STANDARD = 'standard' @@ -837,22 +836,19 @@ class VectorWidgetWrapper(WidgetWrapper): return self.comboValue(validator, combobox=self.combo) -class StringWidgetWrapper(WidgetWrapper): +class StringWidgetWrapper(WidgetWrapper, ExpressionWidgetWrapperMixin): def createWidget(self): if self.dialogType == DIALOG_STANDARD: if self.param.multiline: widget = QPlainTextEdit() - if self.param.default: - widget.setPlainText(self.param.default) else: - widget = StringInputPanel(self.param) - if self.param.default: - widget.setValue(self.param.default) + self._lineedit = QLineEdit() + return self.wrapWithExpressionButton(self._lineedit) + elif self.dialogType == DIALOG_BATCH: widget = QLineEdit() - if self.param.default: - widget.setText(self.param.default) + else: # strings, numbers, files and table fields are all allowed input types strings = self.dialog.getAvailableValuesOfType([ParameterString, ParameterNumber, ParameterFile, @@ -860,20 +856,23 @@ class StringWidgetWrapper(WidgetWrapper): options = [(self.dialog.resolveValueDescription(s), s) for s in strings] if self.param.multiline: widget = MultilineTextPanel(options) - widget.setText(self.param.default or "") else: widget = QComboBox() widget.setEditable(True) for desc, val in options: widget.addItem(desc, val) - widget.setEditText(self.param.default or "") return widget def setValue(self, value): if self.dialogType == DIALOG_STANDARD: - pass # TODO + if self.param.multiline: + self.widget.setPlainText(value) + else: + self._lineedit.setText(value) + elif self.dialogType == DIALOG_BATCH: self.widget.setText(value) + else: if self.param.multiline: self.widget.setValue(value) @@ -885,10 +884,12 @@ class StringWidgetWrapper(WidgetWrapper): if self.param.multiline: text = self.widget.toPlainText() else: - text = self.widget.getValue() + text = self._lineedit.text() return text + elif self.dialogType == DIALOG_BATCH: return self.widget.text() + else: if self.param.multiline: value = self.widget.getValue()