mirror of
https://github.com/qgis/QGIS.git
synced 2025-06-01 00:02:16 -04:00
[processing] Port map layer selection combobox widget to c++
And: - fix enable state of selected features only after changing between map layers with/without selections - fix state of selected features only when running an algorithm from the history list, e.g. respect original setting for selected features only (or not) - ensure no duplicate changed signals are sent, and correctly emit changed signals in all applicable circumstances - handle drag and dropped layers from browser panel (UX fix) - soak with unit tests
This commit is contained in:
parent
9d82273208
commit
fbd243be65
@ -0,0 +1,111 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/processing/qgsprocessingmaplayercombobox.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsProcessingMapLayerComboBox : QWidget
|
||||
{
|
||||
%Docstring
|
||||
Processing map layer combo box.
|
||||
|
||||
.. warning::
|
||||
|
||||
Not part of stable API and may change in future QGIS releases.
|
||||
|
||||
.. versionadded:: 3.8
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsprocessingmaplayercombobox.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsProcessingMapLayerComboBox( QgsProcessingParameterDefinition *parameter, QWidget *parent = 0 );
|
||||
%Docstring
|
||||
Constructor for QgsProcessingMapLayerComboBox, with the specified ``parameter`` definition.
|
||||
%End
|
||||
|
||||
void setLayer( QgsMapLayer *layer );
|
||||
%Docstring
|
||||
Sets the combo box to the specified ``layer``, if ``layer`` is compatible with the
|
||||
widget's parameter definition.
|
||||
%End
|
||||
|
||||
QgsMapLayer *currentLayer();
|
||||
%Docstring
|
||||
Returns the current layer selected in the combobox, or ``None`` if the selection cannot
|
||||
be represented as a map layer.
|
||||
|
||||
.. warning::
|
||||
|
||||
Prefer calling value() instead, as it correctly encapsulates all valid
|
||||
values which can be represented by the widget.
|
||||
|
||||
.. seealso:: :py:func:`currentText`
|
||||
%End
|
||||
|
||||
QString currentText();
|
||||
%Docstring
|
||||
Returns the current text of the selected item in the combobox.
|
||||
|
||||
.. warning::
|
||||
|
||||
Prefer calling value() instead, as it correctly encapsulates all valid
|
||||
values which can be represented by the widget.
|
||||
|
||||
.. seealso:: :py:func:`currentLayer`
|
||||
%End
|
||||
|
||||
void setValue( const QVariant &value, QgsProcessingContext &context );
|
||||
%Docstring
|
||||
Sets the ``value`` shown in the widget.
|
||||
|
||||
.. seealso:: :py:func:`value`
|
||||
%End
|
||||
|
||||
QVariant value() const;
|
||||
%Docstring
|
||||
Returns the current value of the widget.
|
||||
|
||||
.. seealso:: :py:func:`setValue`
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
||||
void valueChanged();
|
||||
%Docstring
|
||||
Emitted whenever the value is changed in the widget.
|
||||
%End
|
||||
|
||||
void triggerFileSelection();
|
||||
%Docstring
|
||||
Emitted when the widget has triggered a file selection operation (to be
|
||||
handled in Python for now).
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
virtual void dragEnterEvent( QDragEnterEvent *event );
|
||||
|
||||
virtual void dragLeaveEvent( QDragLeaveEvent *event );
|
||||
|
||||
virtual void dropEvent( QDropEvent *event );
|
||||
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/processing/qgsprocessingmaplayercombobox.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -330,6 +330,7 @@
|
||||
%Include auto_generated/locator/qgslocatorwidget.sip
|
||||
%Include auto_generated/processing/qgsprocessingalgorithmconfigurationwidget.sip
|
||||
%Include auto_generated/processing/qgsprocessingalgorithmdialogbase.sip
|
||||
%Include auto_generated/processing/qgsprocessingmaplayercombobox.sip
|
||||
%Include auto_generated/processing/qgsprocessingmodelerparameterwidget.sip
|
||||
%Include auto_generated/processing/qgsprocessingmultipleselectiondialog.sip
|
||||
%Include auto_generated/processing/qgsprocessingrecentalgorithmlog.sip
|
||||
|
@ -104,7 +104,8 @@ from qgis.gui import (
|
||||
QgsProjectionSelectionWidget,
|
||||
QgsRasterBandComboBox,
|
||||
QgsProcessingGui,
|
||||
QgsAbstractProcessingParameterWidgetWrapper
|
||||
QgsAbstractProcessingParameterWidgetWrapper,
|
||||
QgsProcessingMapLayerComboBox
|
||||
)
|
||||
from qgis.PyQt.QtCore import pyqtSignal, QObject, QVariant, Qt
|
||||
from qgis.utils import iface
|
||||
@ -931,37 +932,17 @@ class MapLayerWidgetWrapper(WidgetWrapper):
|
||||
|
||||
def createWidget(self):
|
||||
if self.dialogType == DIALOG_STANDARD:
|
||||
widget = QWidget()
|
||||
layout = QHBoxLayout()
|
||||
layout.setMargin(0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(6)
|
||||
self.combo = QgsMapLayerComboBox()
|
||||
layout.addWidget(self.combo)
|
||||
btn = QToolButton()
|
||||
btn.setText('…')
|
||||
btn.setToolTip(self.tr("Select file"))
|
||||
btn.clicked.connect(self.selectFile)
|
||||
layout.addWidget(btn)
|
||||
|
||||
widget.setLayout(layout)
|
||||
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF):
|
||||
self.combo.setShowCrs(True)
|
||||
|
||||
self.setComboBoxFilters(self.combo)
|
||||
self.combo = QgsProcessingMapLayerComboBox(self.parameterDefinition())
|
||||
self.context = dataobjects.createContext()
|
||||
|
||||
try:
|
||||
self.combo.setLayer(iface.activeLayer())
|
||||
except:
|
||||
pass
|
||||
|
||||
if self.parameterDefinition().flags() & QgsProcessingParameterDefinition.FlagOptional:
|
||||
self.combo.setAllowEmptyLayer(True)
|
||||
self.combo.setLayer(None)
|
||||
|
||||
self.combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
self.combo.currentTextChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
return widget
|
||||
self.combo.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
self.combo.triggerFileSelection.connect(self.selectFile)
|
||||
return self.combo
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
widget = BatchInputSelectionPanel(self.parameterDefinition(), self.row, self.col, self.dialog)
|
||||
widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
@ -989,9 +970,6 @@ class MapLayerWidgetWrapper(WidgetWrapper):
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
def setComboBoxFilters(self, combo):
|
||||
pass
|
||||
|
||||
def getAvailableLayers(self):
|
||||
return self.dialog.getAvailableValuesOfType(
|
||||
[QgsProcessingParameterRasterLayer, QgsProcessingParameterMeshLayer, QgsProcessingParameterVectorLayer, QgsProcessingParameterMapLayer, QgsProcessingParameterString],
|
||||
@ -1000,7 +978,9 @@ class MapLayerWidgetWrapper(WidgetWrapper):
|
||||
def selectFile(self):
|
||||
filename, selected_filter = self.getFileName(self.combo.currentText())
|
||||
if filename:
|
||||
if isinstance(self.combo, QgsMapLayerComboBox):
|
||||
if isinstance(self.combo, QgsProcessingMapLayerComboBox):
|
||||
self.combo.setValue(filename, self.context)
|
||||
elif isinstance(self.combo, QgsMapLayerComboBox):
|
||||
items = self.combo.additionalItems()
|
||||
items.append(filename)
|
||||
self.combo.setAdditionalItems(items)
|
||||
@ -1018,20 +998,7 @@ class MapLayerWidgetWrapper(WidgetWrapper):
|
||||
layer = QgsProject.instance().mapLayer(value)
|
||||
if layer is not None:
|
||||
value = layer
|
||||
|
||||
found = False
|
||||
if isinstance(value, QgsMapLayer):
|
||||
self.combo.setLayer(value)
|
||||
found = self.combo.currentIndex() != -1
|
||||
|
||||
if not found:
|
||||
if self.combo.findText(value) >= 0:
|
||||
self.combo.setCurrentIndex(self.combo.findText(value))
|
||||
else:
|
||||
items = self.combo.additionalItems()
|
||||
items.append(value)
|
||||
self.combo.setAdditionalItems(items)
|
||||
self.combo.setCurrentIndex(self.combo.findText(value))
|
||||
self.combo.setValue(value, self.context)
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
self.widget.setValue(value)
|
||||
else:
|
||||
@ -1040,14 +1007,7 @@ class MapLayerWidgetWrapper(WidgetWrapper):
|
||||
|
||||
def value(self):
|
||||
if self.dialogType == DIALOG_STANDARD:
|
||||
try:
|
||||
layer = self.combo.currentLayer()
|
||||
if layer is not None:
|
||||
return layer
|
||||
else:
|
||||
return self.combo.currentText() or None
|
||||
except:
|
||||
return self.combo.currentText()
|
||||
return self.combo.value()
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
return self.widget.value()
|
||||
else:
|
||||
@ -1066,15 +1026,13 @@ class RasterWidgetWrapper(MapLayerWidgetWrapper):
|
||||
return self.dialog.getAvailableValuesOfType((QgsProcessingParameterRasterLayer, QgsProcessingParameterString),
|
||||
(QgsProcessingOutputRasterLayer, QgsProcessingOutputFile, QgsProcessingOutputString))
|
||||
|
||||
def setComboBoxFilters(self, combo):
|
||||
combo.setFilters(QgsMapLayerProxyModel.RasterLayer)
|
||||
combo.setExcludedProviders(['grass'])
|
||||
|
||||
def selectFile(self):
|
||||
filename, selected_filter = self.getFileName(self.combo.currentText())
|
||||
if filename:
|
||||
filename = dataobjects.getRasterSublayer(filename, self.parameterDefinition())
|
||||
if isinstance(self.combo, QgsMapLayerComboBox):
|
||||
if isinstance(self.combo, QgsProcessingMapLayerComboBox):
|
||||
self.combo.setValue(filename, self.context)
|
||||
elif isinstance(self.combo, QgsMapLayerComboBox):
|
||||
items = self.combo.additionalItems()
|
||||
items.append(filename)
|
||||
self.combo.setAdditionalItems(items)
|
||||
@ -1090,13 +1048,12 @@ class MeshWidgetWrapper(MapLayerWidgetWrapper):
|
||||
return self.dialog.getAvailableValuesOfType((QgsProcessingParameterMeshLayer, QgsProcessingParameterString),
|
||||
())
|
||||
|
||||
def setComboBoxFilters(self, combo):
|
||||
combo.setFilters(QgsMapLayerProxyModel.MeshLayer)
|
||||
|
||||
def selectFile(self):
|
||||
filename, selected_filter = self.getFileName(self.combo.currentText())
|
||||
if filename:
|
||||
if isinstance(self.combo, QgsMapLayerComboBox):
|
||||
if isinstance(self.combo, QgsProcessingMapLayerComboBox):
|
||||
self.combo.setValue(filename, self.context)
|
||||
elif isinstance(self.combo, QgsMapLayerComboBox):
|
||||
items = self.combo.additionalItems()
|
||||
items.append(filename)
|
||||
self.combo.setAdditionalItems(items)
|
||||
@ -1177,70 +1134,19 @@ class FeatureSourceWidgetWrapper(WidgetWrapper):
|
||||
NOT_SELECTED = '[Not selected]'
|
||||
|
||||
def createWidget(self):
|
||||
self.fileBasedLayers = {}
|
||||
if self.dialogType == DIALOG_STANDARD:
|
||||
widget = QWidget()
|
||||
layout = QHBoxLayout()
|
||||
layout.setMargin(0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(6)
|
||||
self.combo = QgsMapLayerComboBox()
|
||||
layout.addWidget(self.combo)
|
||||
layout.setAlignment(self.combo, Qt.AlignTop)
|
||||
btn = QToolButton()
|
||||
btn.setText('…')
|
||||
btn.setToolTip(self.tr("Select file"))
|
||||
btn.clicked.connect(self.selectFile)
|
||||
layout.addWidget(btn)
|
||||
layout.setAlignment(btn, Qt.AlignTop)
|
||||
|
||||
vl = QVBoxLayout()
|
||||
vl.setMargin(0)
|
||||
vl.setContentsMargins(0, 0, 0, 0)
|
||||
vl.setSpacing(6)
|
||||
vl.addLayout(layout)
|
||||
|
||||
self.use_selection_checkbox = QCheckBox(self.tr('Selected features only'))
|
||||
self.use_selection_checkbox.setChecked(False)
|
||||
self.use_selection_checkbox.setEnabled(False)
|
||||
vl.addWidget(self.use_selection_checkbox)
|
||||
|
||||
widget.setLayout(vl)
|
||||
|
||||
filters = QgsMapLayerProxyModel.Filters()
|
||||
if QgsProcessing.TypeVectorAnyGeometry in self.parameterDefinition().dataTypes() or len(self.parameterDefinition().dataTypes()) == 0:
|
||||
filters = QgsMapLayerProxyModel.HasGeometry
|
||||
if QgsProcessing.TypeVectorPoint in self.parameterDefinition().dataTypes():
|
||||
filters |= QgsMapLayerProxyModel.PointLayer
|
||||
if QgsProcessing.TypeVectorLine in self.parameterDefinition().dataTypes():
|
||||
filters |= QgsMapLayerProxyModel.LineLayer
|
||||
if QgsProcessing.TypeVectorPolygon in self.parameterDefinition().dataTypes():
|
||||
filters |= QgsMapLayerProxyModel.PolygonLayer
|
||||
if not filters:
|
||||
filters = QgsMapLayerProxyModel.VectorLayer
|
||||
self.combo = QgsProcessingMapLayerComboBox(self.parameterDefinition())
|
||||
self.context = dataobjects.createContext()
|
||||
|
||||
try:
|
||||
if iface.activeLayer().type() == QgsMapLayerType.VectorLayer:
|
||||
self.combo.setLayer(iface.activeLayer())
|
||||
self.use_selection_checkbox.setEnabled(iface.activeLayer().selectedFeatureCount() > 0)
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF):
|
||||
self.combo.setShowCrs(True)
|
||||
|
||||
if filters:
|
||||
self.combo.setFilters(filters)
|
||||
self.combo.setExcludedProviders(['grass'])
|
||||
|
||||
if self.parameterDefinition().flags() & QgsProcessingParameterDefinition.FlagOptional:
|
||||
self.combo.setAllowEmptyLayer(True)
|
||||
self.combo.setLayer(None)
|
||||
|
||||
self.combo.layerChanged.connect(self.layerChanged)
|
||||
return widget
|
||||
|
||||
self.combo.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
self.combo.triggerFileSelection.connect(self.selectFile)
|
||||
return self.combo
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
widget = BatchInputSelectionPanel(self.parameterDefinition(), self.row, self.col, self.dialog)
|
||||
widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
@ -1270,19 +1176,13 @@ class FeatureSourceWidgetWrapper(WidgetWrapper):
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
def layerChanged(self, layer):
|
||||
if layer is None or layer.type() != QgsMapLayerType.VectorLayer or layer.selectedFeatureCount() == 0:
|
||||
self.use_selection_checkbox.setChecked(False)
|
||||
self.use_selection_checkbox.setEnabled(False)
|
||||
else:
|
||||
self.use_selection_checkbox.setEnabled(True)
|
||||
self.widgetValueHasChanged.emit(self)
|
||||
|
||||
def selectFile(self):
|
||||
filename, selected_filter = self.getFileName(self.combo.currentText())
|
||||
if filename:
|
||||
filename = dataobjects.getRasterSublayer(filename, self.parameterDefinition())
|
||||
if isinstance(self.combo, QgsMapLayerComboBox):
|
||||
if isinstance(self.combo, QgsProcessingMapLayerComboBox):
|
||||
self.combo.setValue(filename, self.context)
|
||||
elif isinstance(self.combo, QgsMapLayerComboBox):
|
||||
items = self.combo.additionalItems()
|
||||
items.append(filename)
|
||||
self.combo.setAdditionalItems(items)
|
||||
@ -1300,20 +1200,7 @@ class FeatureSourceWidgetWrapper(WidgetWrapper):
|
||||
layer = QgsProject.instance().mapLayer(value)
|
||||
if layer is not None:
|
||||
value = layer
|
||||
|
||||
found = False
|
||||
if isinstance(value, QgsMapLayer):
|
||||
self.combo.setLayer(value)
|
||||
found = self.combo.currentIndex() != -1
|
||||
|
||||
if not found:
|
||||
if self.combo.findText(value) >= 0:
|
||||
self.combo.setCurrentIndex(self.combo.findText(value))
|
||||
else:
|
||||
items = self.combo.additionalItems()
|
||||
items.append(value)
|
||||
self.combo.setAdditionalItems(items)
|
||||
self.combo.setCurrentIndex(self.combo.findText(value))
|
||||
self.combo.setValue(value, self.context)
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
self.widget.setValue(value)
|
||||
else:
|
||||
@ -1322,24 +1209,7 @@ class FeatureSourceWidgetWrapper(WidgetWrapper):
|
||||
|
||||
def value(self):
|
||||
if self.dialogType == DIALOG_STANDARD:
|
||||
use_selected_features = self.use_selection_checkbox.isChecked()
|
||||
try:
|
||||
layer = self.combo.currentLayer()
|
||||
if layer is not None:
|
||||
if use_selected_features:
|
||||
return QgsProcessingFeatureSourceDefinition(layer.id(), True)
|
||||
else:
|
||||
return layer.id()
|
||||
else:
|
||||
if self.combo.currentText():
|
||||
if use_selected_features:
|
||||
return QgsProcessingFeatureSourceDefinition(self.combo.currentText(), True)
|
||||
else:
|
||||
return self.combo.currentText()
|
||||
else:
|
||||
return None
|
||||
except:
|
||||
return QgsProcessingFeatureSourceDefinition(self.combo.currentText(), use_selected_features)
|
||||
return self.combo.value()
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
return self.widget.getValue()
|
||||
else:
|
||||
@ -1538,56 +1408,19 @@ class VectorLayerWidgetWrapper(WidgetWrapper):
|
||||
NOT_SELECTED = '[Not selected]'
|
||||
|
||||
def createWidget(self):
|
||||
self.fileBasedLayers = {}
|
||||
if self.dialogType == DIALOG_STANDARD:
|
||||
widget = QWidget()
|
||||
layout = QHBoxLayout()
|
||||
layout.setMargin(0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(6)
|
||||
self.combo = QgsMapLayerComboBox()
|
||||
layout.addWidget(self.combo)
|
||||
btn = QToolButton()
|
||||
btn.setText('…')
|
||||
btn.setToolTip(self.tr("Select file"))
|
||||
btn.clicked.connect(self.selectFile)
|
||||
layout.addWidget(btn)
|
||||
self.combo = QgsProcessingMapLayerComboBox(self.parameterDefinition())
|
||||
self.context = dataobjects.createContext()
|
||||
|
||||
widget.setLayout(layout)
|
||||
|
||||
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF):
|
||||
self.combo.setShowCrs(True)
|
||||
|
||||
filters = QgsMapLayerProxyModel.Filters()
|
||||
if QgsProcessing.TypeVectorAnyGeometry in self.parameterDefinition().dataTypes() or len(self.parameterDefinition().dataTypes()) == 0:
|
||||
filters = QgsMapLayerProxyModel.HasGeometry
|
||||
if QgsProcessing.TypeVectorPoint in self.parameterDefinition().dataTypes():
|
||||
filters |= QgsMapLayerProxyModel.PointLayer
|
||||
if QgsProcessing.TypeVectorLine in self.parameterDefinition().dataTypes():
|
||||
filters |= QgsMapLayerProxyModel.LineLayer
|
||||
if QgsProcessing.TypeVectorPolygon in self.parameterDefinition().dataTypes():
|
||||
filters |= QgsMapLayerProxyModel.PolygonLayer
|
||||
if not filters:
|
||||
filters = QgsMapLayerProxyModel.VectorLayer
|
||||
|
||||
if filters:
|
||||
self.combo.setFilters(filters)
|
||||
|
||||
self.combo.setExcludedProviders(['grass'])
|
||||
try:
|
||||
if iface.activeLayer().type() == QgsMapLayerType.VectorLayer:
|
||||
self.combo.setLayer(iface.activeLayer())
|
||||
except:
|
||||
pass
|
||||
|
||||
if self.parameterDefinition().flags() & QgsProcessingParameterDefinition.FlagOptional:
|
||||
self.combo.setAllowEmptyLayer(True)
|
||||
self.combo.setLayer(None)
|
||||
|
||||
self.combo.currentIndexChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
self.combo.currentTextChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
return widget
|
||||
|
||||
self.combo.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
self.combo.triggerFileSelection.connect(self.selectFile)
|
||||
return self.combo
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
widget = BatchInputSelectionPanel(self.parameterDefinition(), self.row, self.col, self.dialog)
|
||||
widget.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
|
||||
@ -1620,7 +1453,9 @@ class VectorLayerWidgetWrapper(WidgetWrapper):
|
||||
filename, selected_filter = self.getFileName(self.combo.currentText())
|
||||
if filename:
|
||||
filename = dataobjects.getRasterSublayer(filename, self.parameterDefinition())
|
||||
if isinstance(self.combo, QgsMapLayerComboBox):
|
||||
if isinstance(self.combo, QgsProcessingMapLayerComboBox):
|
||||
self.combo.setValue(filename, self.context)
|
||||
elif isinstance(self.combo, QgsMapLayerComboBox):
|
||||
items = self.combo.additionalItems()
|
||||
items.append(filename)
|
||||
self.combo.setAdditionalItems(items)
|
||||
@ -1638,20 +1473,7 @@ class VectorLayerWidgetWrapper(WidgetWrapper):
|
||||
layer = QgsProject.instance().mapLayer(value)
|
||||
if layer is not None:
|
||||
value = layer
|
||||
|
||||
found = False
|
||||
if isinstance(value, QgsMapLayer):
|
||||
self.combo.setLayer(value)
|
||||
found = self.combo.currentIndex() != -1
|
||||
|
||||
if not found:
|
||||
if self.combo.findText(value) >= 0:
|
||||
self.combo.setCurrentIndex(self.combo.findText(value))
|
||||
else:
|
||||
items = self.combo.additionalItems()
|
||||
items.append(value)
|
||||
self.combo.setAdditionalItems(items)
|
||||
self.combo.setCurrentIndex(self.combo.findText(value))
|
||||
self.combo.setValue(value, self.context)
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
return self.widget.setValue(value)
|
||||
else:
|
||||
@ -1660,14 +1482,7 @@ class VectorLayerWidgetWrapper(WidgetWrapper):
|
||||
|
||||
def value(self):
|
||||
if self.dialogType == DIALOG_STANDARD:
|
||||
try:
|
||||
layer = self.combo.currentLayer()
|
||||
if layer is not None:
|
||||
return layer
|
||||
else:
|
||||
return self.combo.currentText()
|
||||
except:
|
||||
return self.combo.currentText()
|
||||
return self.combo.value()
|
||||
elif self.dialogType == DIALOG_BATCH:
|
||||
return self.widget.value()
|
||||
else:
|
||||
@ -1686,6 +1501,7 @@ class TableFieldWidgetWrapper(WidgetWrapper):
|
||||
|
||||
def createWidget(self):
|
||||
self._layer = None
|
||||
self.parent_file_based_layers = {}
|
||||
|
||||
if self.dialogType in (DIALOG_STANDARD, DIALOG_BATCH):
|
||||
if self.parameterDefinition().allowMultiple():
|
||||
@ -1725,11 +1541,11 @@ class TableFieldWidgetWrapper(WidgetWrapper):
|
||||
|
||||
def parentValueChanged(self, wrapper):
|
||||
value = wrapper.parameterValue()
|
||||
if value in wrapper.fileBasedLayers:
|
||||
self.setLayer(wrapper.fileBasedLayers[value])
|
||||
if value in self.parent_file_based_layers:
|
||||
self.setLayer(self.parent_file_based_layers[value])
|
||||
else:
|
||||
self.setLayer(value)
|
||||
wrapper.fileBasedLayers[value] = self._layer
|
||||
self.parent_file_based_layers[value] = self._layer
|
||||
|
||||
def setLayer(self, layer):
|
||||
if isinstance(layer, QgsProcessingFeatureSourceDefinition):
|
||||
|
@ -32,6 +32,7 @@ from qgis.core import (QgsApplication,
|
||||
QgsProcessingParameterVectorDestination,
|
||||
QgsProcessingParameterRasterDestination,
|
||||
QgsProcessingParameterRange,
|
||||
QgsFeature,
|
||||
QgsVectorLayer,
|
||||
QgsProject)
|
||||
from qgis.analysis import QgsNativeAlgorithms
|
||||
@ -134,6 +135,10 @@ class WrappersTest(unittest.TestCase):
|
||||
|
||||
# dummy layer
|
||||
layer = QgsVectorLayer('Point', 'test', 'memory')
|
||||
# need at least one feature in order to have a selection
|
||||
layer.dataProvider().addFeature(QgsFeature())
|
||||
layer.selectAll()
|
||||
|
||||
self.assertTrue(layer.isValid())
|
||||
QgsProject.instance().addMapLayer(layer)
|
||||
|
||||
@ -148,20 +153,15 @@ class WrappersTest(unittest.TestCase):
|
||||
wrapper.setValue(layer.id())
|
||||
self.assertEqual(wrapper.value(), layer.id())
|
||||
|
||||
# check not set
|
||||
wrapper.setValue('')
|
||||
self.assertFalse(wrapper.value())
|
||||
|
||||
# check selected only - expect a QgsProcessingFeatureSourceDefinition
|
||||
wrapper.setValue(layer.id())
|
||||
wrapper.use_selection_checkbox.setChecked(True)
|
||||
wrapper.setValue(QgsProcessingFeatureSourceDefinition(layer.id(), True))
|
||||
value = wrapper.value()
|
||||
self.assertIsInstance(value, QgsProcessingFeatureSourceDefinition)
|
||||
self.assertTrue(value.selectedFeaturesOnly)
|
||||
self.assertEqual(value.source.staticValue(), layer.id())
|
||||
|
||||
# NOT selected only, expect a direct layer id or source value
|
||||
wrapper.use_selection_checkbox.setChecked(False)
|
||||
wrapper.setValue(QgsProcessingFeatureSourceDefinition(layer.id(), False))
|
||||
value = wrapper.value()
|
||||
self.assertEqual(value, layer.id())
|
||||
|
||||
|
@ -201,6 +201,7 @@ SET(QGIS_GUI_SRCS
|
||||
processing/qgsprocessingalgorithmdialogbase.cpp
|
||||
processing/qgsprocessingconfigurationwidgets.cpp
|
||||
processing/qgsprocessingguiregistry.cpp
|
||||
processing/qgsprocessingmaplayercombobox.cpp
|
||||
processing/qgsprocessingmatrixparameterdialog.cpp
|
||||
processing/qgsprocessingmodelerparameterwidget.cpp
|
||||
processing/qgsprocessingmultipleselectiondialog.cpp
|
||||
@ -752,6 +753,7 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
processing/qgsprocessingalgorithmconfigurationwidget.h
|
||||
processing/qgsprocessingalgorithmdialogbase.h
|
||||
processing/qgsprocessingconfigurationwidgets.h
|
||||
processing/qgsprocessingmaplayercombobox.h
|
||||
processing/qgsprocessingmatrixparameterdialog.h
|
||||
processing/qgsprocessingmodelerparameterwidget.h
|
||||
processing/qgsprocessingmultipleselectiondialog.h
|
||||
|
399
src/gui/processing/qgsprocessingmaplayercombobox.cpp
Normal file
399
src/gui/processing/qgsprocessingmaplayercombobox.cpp
Normal file
@ -0,0 +1,399 @@
|
||||
/***************************************************************************
|
||||
qgsprocessingmaplayercombobox.cpp
|
||||
-------------------------------
|
||||
begin : June 2019
|
||||
copyright : (C) 2019 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 "qgsprocessingmaplayercombobox.h"
|
||||
#include "qgsmaplayercombobox.h"
|
||||
#include "qgsmimedatautils.h"
|
||||
#include "qgsprocessingparameters.h"
|
||||
#include "qgssettings.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsfeatureid.h"
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QToolButton>
|
||||
#include <QCheckBox>
|
||||
#include <QDragEnterEvent>
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
QgsProcessingMapLayerComboBox::QgsProcessingMapLayerComboBox( QgsProcessingParameterDefinition *parameter, QWidget *parent )
|
||||
: QWidget( parent )
|
||||
, mParameter( parameter )
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout();
|
||||
layout->setMargin( 0 );
|
||||
layout->setContentsMargins( 0, 0, 0, 0 );
|
||||
layout->setSpacing( 6 );
|
||||
|
||||
mCombo = new QgsMapLayerComboBox();
|
||||
layout->addWidget( mCombo );
|
||||
layout->setAlignment( mCombo, Qt::AlignTop );
|
||||
|
||||
mSelectButton = new QToolButton();
|
||||
mSelectButton->setText( QStringLiteral( "…" ) );
|
||||
mSelectButton->setToolTip( tr( "Select file" ) );
|
||||
connect( mSelectButton, &QToolButton::clicked, this, &QgsProcessingMapLayerComboBox::triggerFileSelection );
|
||||
layout->addWidget( mSelectButton );
|
||||
layout->setAlignment( mSelectButton, Qt::AlignTop );
|
||||
|
||||
QVBoxLayout *vl = new QVBoxLayout();
|
||||
vl->setMargin( 0 );
|
||||
vl->setContentsMargins( 0, 0, 0, 0 );
|
||||
vl->setSpacing( 6 );
|
||||
vl->addLayout( layout );
|
||||
|
||||
QgsMapLayerProxyModel::Filters filters = nullptr;
|
||||
|
||||
if ( mParameter->type() == QgsProcessingParameterFeatureSource::typeName() )
|
||||
{
|
||||
mUseSelectionCheckBox = new QCheckBox( tr( "Selected features only" ) );
|
||||
mUseSelectionCheckBox->setChecked( false );
|
||||
mUseSelectionCheckBox->setEnabled( false );
|
||||
vl->addWidget( mUseSelectionCheckBox );
|
||||
}
|
||||
|
||||
if ( mParameter->type() == QgsProcessingParameterFeatureSource::typeName() || mParameter->type() == QgsProcessingParameterVectorLayer::typeName() )
|
||||
{
|
||||
QList<int> dataTypes;
|
||||
if ( mParameter->type() == QgsProcessingParameterFeatureSource::typeName() )
|
||||
dataTypes = static_cast< QgsProcessingParameterFeatureSource *>( mParameter )->dataTypes();
|
||||
else if ( mParameter->type() == QgsProcessingParameterVectorLayer::typeName() )
|
||||
dataTypes = static_cast< QgsProcessingParameterVectorLayer *>( mParameter )->dataTypes();
|
||||
|
||||
if ( dataTypes.contains( QgsProcessing::TypeVectorAnyGeometry ) || dataTypes.isEmpty() )
|
||||
filters = QgsMapLayerProxyModel::HasGeometry;
|
||||
if ( dataTypes.contains( QgsProcessing::TypeVectorPoint ) )
|
||||
filters |= QgsMapLayerProxyModel::PointLayer;
|
||||
if ( dataTypes.contains( QgsProcessing::TypeVectorLine ) )
|
||||
filters |= QgsMapLayerProxyModel::LineLayer;
|
||||
if ( dataTypes.contains( QgsProcessing::TypeVectorPolygon ) )
|
||||
filters |= QgsMapLayerProxyModel::PolygonLayer;
|
||||
if ( !filters )
|
||||
filters = QgsMapLayerProxyModel::VectorLayer;
|
||||
}
|
||||
else if ( mParameter->type() == QgsProcessingParameterRasterLayer::typeName() )
|
||||
{
|
||||
filters = QgsMapLayerProxyModel::RasterLayer;
|
||||
}
|
||||
else if ( mParameter->type() == QgsProcessingParameterMeshLayer::typeName() )
|
||||
{
|
||||
filters = QgsMapLayerProxyModel::MeshLayer;
|
||||
}
|
||||
|
||||
QgsSettings settings;
|
||||
if ( settings.value( QStringLiteral( "Processing/Configuration/SHOW_CRS_DEF" ), true ).toBool() )
|
||||
mCombo->setShowCrs( true );
|
||||
|
||||
if ( filters )
|
||||
mCombo->setFilters( filters );
|
||||
mCombo->setExcludedProviders( QStringList() << QStringLiteral( "grass" ) ); // not sure if this is still required...
|
||||
|
||||
if ( mParameter->flags() & QgsProcessingParameterDefinition::FlagOptional )
|
||||
{
|
||||
mCombo->setAllowEmptyLayer( true );
|
||||
mCombo->setLayer( nullptr );
|
||||
}
|
||||
|
||||
connect( mCombo, &QgsMapLayerComboBox::layerChanged, this, &QgsProcessingMapLayerComboBox::onLayerChanged );
|
||||
if ( mUseSelectionCheckBox )
|
||||
connect( mUseSelectionCheckBox, &QCheckBox::toggled, this, [ = ]
|
||||
{
|
||||
if ( !mBlockChangedSignal )
|
||||
emit valueChanged();
|
||||
} );
|
||||
|
||||
setLayout( vl );
|
||||
|
||||
setAcceptDrops( true );
|
||||
}
|
||||
|
||||
void QgsProcessingMapLayerComboBox::setLayer( QgsMapLayer *layer )
|
||||
{
|
||||
if ( layer || mParameter->flags() & QgsProcessingParameterDefinition::FlagOptional )
|
||||
mCombo->setLayer( layer );
|
||||
}
|
||||
|
||||
QgsMapLayer *QgsProcessingMapLayerComboBox::currentLayer()
|
||||
{
|
||||
return mCombo->currentLayer();
|
||||
}
|
||||
|
||||
QString QgsProcessingMapLayerComboBox::currentText()
|
||||
{
|
||||
return mCombo->currentText();
|
||||
}
|
||||
|
||||
void QgsProcessingMapLayerComboBox::setValue( const QVariant &value, QgsProcessingContext &context )
|
||||
{
|
||||
QVariant val = value;
|
||||
bool found = false;
|
||||
bool selectedOnly = false;
|
||||
if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
|
||||
{
|
||||
QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( val );
|
||||
val = fromVar.source;
|
||||
selectedOnly = fromVar.selectedFeaturesOnly;
|
||||
}
|
||||
|
||||
if ( val.canConvert<QgsProperty>() )
|
||||
{
|
||||
if ( val.value< QgsProperty >().propertyType() == QgsProperty::StaticProperty )
|
||||
{
|
||||
val = val.value< QgsProperty >().staticValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
val = val.value< QgsProperty >().valueAsString( context.expressionContext(), mParameter->defaultValue().toString() );
|
||||
}
|
||||
}
|
||||
|
||||
QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( val.value< QObject * >() );
|
||||
if ( !layer && val.type() == QVariant::String )
|
||||
{
|
||||
layer = QgsProcessingUtils::mapLayerFromString( val.toString(), context, false );
|
||||
}
|
||||
|
||||
if ( layer )
|
||||
{
|
||||
mBlockChangedSignal++;
|
||||
QgsMapLayer *prevLayer = currentLayer();
|
||||
setLayer( layer );
|
||||
found = static_cast< bool >( currentLayer() );
|
||||
bool changed = found && ( currentLayer() != prevLayer );
|
||||
if ( found && mUseSelectionCheckBox )
|
||||
{
|
||||
const bool hasSelection = qobject_cast< QgsVectorLayer * >( layer ) && qobject_cast< QgsVectorLayer * >( layer )->selectedFeatureCount() > 0;
|
||||
changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
|
||||
if ( hasSelection )
|
||||
{
|
||||
mUseSelectionCheckBox->setEnabled( true );
|
||||
mUseSelectionCheckBox->setChecked( selectedOnly );
|
||||
}
|
||||
else
|
||||
{
|
||||
mUseSelectionCheckBox->setChecked( false );
|
||||
mUseSelectionCheckBox->setEnabled( false );
|
||||
}
|
||||
}
|
||||
mBlockChangedSignal--;
|
||||
if ( changed )
|
||||
emit valueChanged(); // and ensure we only ever raise one
|
||||
}
|
||||
|
||||
if ( !found )
|
||||
{
|
||||
const QString string = val.toString();
|
||||
if ( !string.isEmpty() )
|
||||
{
|
||||
mBlockChangedSignal++;
|
||||
if ( mCombo->findText( string ) < 0 )
|
||||
{
|
||||
QStringList additional = mCombo->additionalItems();
|
||||
additional.append( string );
|
||||
mCombo->setAdditionalItems( additional );
|
||||
}
|
||||
mCombo->setCurrentIndex( mCombo->findText( string ) ); // this may or may not throw a signal, so let's block it..
|
||||
mBlockChangedSignal--;
|
||||
if ( !mBlockChangedSignal )
|
||||
emit valueChanged(); // and ensure we only ever raise one
|
||||
}
|
||||
else if ( mParameter->flags() & QgsProcessingParameterDefinition::FlagOptional )
|
||||
{
|
||||
mCombo->setLayer( nullptr );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariant QgsProcessingMapLayerComboBox::value() const
|
||||
{
|
||||
if ( QgsMapLayer *layer = mCombo->currentLayer() )
|
||||
{
|
||||
if ( mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked() )
|
||||
return QgsProcessingFeatureSourceDefinition( layer->id(), true );
|
||||
else
|
||||
return layer->id();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !mCombo->currentText().isEmpty() )
|
||||
{
|
||||
if ( mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked() )
|
||||
return QgsProcessingFeatureSourceDefinition( mCombo->currentText(), true );
|
||||
else
|
||||
return mCombo->currentText();
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData( const QMimeData *data, bool &incompatibleLayerSelected ) const
|
||||
{
|
||||
incompatibleLayerSelected = false;
|
||||
const QgsMimeDataUtils::UriList uriList = QgsMimeDataUtils::decodeUriList( data );
|
||||
for ( const QgsMimeDataUtils::Uri &u : uriList )
|
||||
{
|
||||
// is this uri from the current project?
|
||||
if ( QgsMapLayer *layer = u.mapLayer() )
|
||||
{
|
||||
if ( mCombo->mProxyModel->acceptsLayer( layer ) )
|
||||
return layer;
|
||||
else
|
||||
{
|
||||
incompatibleLayerSelected = true;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData( const QMimeData *data ) const
|
||||
{
|
||||
const QgsMimeDataUtils::UriList uriList = QgsMimeDataUtils::decodeUriList( data );
|
||||
for ( const QgsMimeDataUtils::Uri &u : uriList )
|
||||
{
|
||||
if ( ( mParameter->type() == QgsProcessingParameterFeatureSource::typeName()
|
||||
|| mParameter->type() == QgsProcessingParameterVectorLayer::typeName()
|
||||
|| mParameter->type() == QgsProcessingParameterMapLayer::typeName() )
|
||||
&& u.layerType == QLatin1String( "vector" ) && u.providerKey == QLatin1String( "ogr" ) )
|
||||
return u.uri;
|
||||
else if ( ( mParameter->type() == QgsProcessingParameterRasterLayer::typeName()
|
||||
|| mParameter->type() == QgsProcessingParameterMapLayer::typeName() )
|
||||
&& u.layerType == QLatin1String( "raster" ) && u.providerKey == QLatin1String( "gdal" ) )
|
||||
return u.uri;
|
||||
else if ( ( mParameter->type() == QgsProcessingParameterMeshLayer::typeName()
|
||||
|| mParameter->type() == QgsProcessingParameterMapLayer::typeName() )
|
||||
&& u.layerType == QLatin1String( "mesh" ) && u.providerKey == QLatin1String( "mdal" ) )
|
||||
return u.uri;
|
||||
}
|
||||
if ( !uriList.isEmpty() )
|
||||
return QString();
|
||||
|
||||
// second chance -- files dragged from file explorer, outside of QGIS
|
||||
QStringList rawPaths;
|
||||
if ( data->hasUrls() )
|
||||
{
|
||||
const QList< QUrl > urls = data->urls();
|
||||
rawPaths.reserve( urls.count() );
|
||||
for ( const QUrl &url : urls )
|
||||
{
|
||||
const QString local = url.toLocalFile();
|
||||
if ( !rawPaths.contains( local ) )
|
||||
rawPaths.append( local );
|
||||
}
|
||||
}
|
||||
if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
|
||||
rawPaths.append( data->text() );
|
||||
|
||||
for ( const QString &path : qgis::as_const( rawPaths ) )
|
||||
{
|
||||
QFileInfo file( path );
|
||||
if ( file.isFile() )
|
||||
{
|
||||
// TODO - we should check to see if it's a valid extension for the parameter, but that's non-trivial
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
|
||||
{
|
||||
if ( !( event->possibleActions() & Qt::CopyAction ) )
|
||||
return;
|
||||
|
||||
bool incompatibleLayerSelected = false;
|
||||
QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
|
||||
const QString uri = compatibleUriFromMimeData( event->mimeData() );
|
||||
if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
|
||||
{
|
||||
// dragged an acceptable layer, phew
|
||||
event->setDropAction( Qt::CopyAction );
|
||||
event->accept();
|
||||
mDragActive = true;
|
||||
mCombo->mHighlight = true;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
|
||||
{
|
||||
QWidget::dragLeaveEvent( event );
|
||||
if ( mDragActive )
|
||||
{
|
||||
event->accept();
|
||||
mDragActive = false;
|
||||
mCombo->mHighlight = false;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
|
||||
{
|
||||
if ( !( event->possibleActions() & Qt::CopyAction ) )
|
||||
return;
|
||||
|
||||
bool incompatibleLayerSelected = false;
|
||||
QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
|
||||
const QString uri = compatibleUriFromMimeData( event->mimeData() );
|
||||
if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
|
||||
{
|
||||
// dropped an acceptable layer, phew
|
||||
setFocus( Qt::MouseFocusReason );
|
||||
event->setDropAction( Qt::CopyAction );
|
||||
event->accept();
|
||||
QgsProcessingContext context;
|
||||
setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
|
||||
}
|
||||
mDragActive = false;
|
||||
mCombo->mHighlight = false;
|
||||
update();
|
||||
}
|
||||
|
||||
void QgsProcessingMapLayerComboBox::onLayerChanged( QgsMapLayer *layer )
|
||||
{
|
||||
if ( mParameter->type() == QgsProcessingParameterFeatureSource::typeName() )
|
||||
{
|
||||
if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
|
||||
{
|
||||
if ( QgsVectorLayer *prevLayer = qobject_cast< QgsVectorLayer * >( mPrevLayer ) )
|
||||
{
|
||||
disconnect( prevLayer, &QgsVectorLayer::selectionChanged, this, &QgsProcessingMapLayerComboBox::selectionChanged );
|
||||
}
|
||||
if ( vl->selectedFeatureCount() == 0 )
|
||||
mUseSelectionCheckBox->setChecked( false );
|
||||
mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
|
||||
connect( vl, &QgsVectorLayer::selectionChanged, this, &QgsProcessingMapLayerComboBox::selectionChanged );
|
||||
}
|
||||
}
|
||||
|
||||
mPrevLayer = layer;
|
||||
if ( !mBlockChangedSignal )
|
||||
emit valueChanged();
|
||||
}
|
||||
|
||||
void QgsProcessingMapLayerComboBox::selectionChanged( const QgsFeatureIds &selected, const QgsFeatureIds &, bool )
|
||||
{
|
||||
if ( selected.isEmpty() )
|
||||
mUseSelectionCheckBox->setChecked( false );
|
||||
mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
///@endcond
|
130
src/gui/processing/qgsprocessingmaplayercombobox.h
Normal file
130
src/gui/processing/qgsprocessingmaplayercombobox.h
Normal file
@ -0,0 +1,130 @@
|
||||
/***************************************************************************
|
||||
qgsprocessingmaplayercombobox.h
|
||||
-----------------------------
|
||||
begin : June 2019
|
||||
copyright : (C) 2019 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 QGSPROCESSINGMAPLAYERCOMBOBOX_H
|
||||
#define QGSPROCESSINGMAPLAYERCOMBOBOX_H
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgis_gui.h"
|
||||
#include <QTreeView>
|
||||
#include "qgsprocessingtoolboxmodel.h"
|
||||
#include "qgsfeatureid.h"
|
||||
#include "qgsmimedatautils.h"
|
||||
#include "qgsprocessingcontext.h"
|
||||
|
||||
|
||||
class QgsMapLayerComboBox;
|
||||
class QToolButton;
|
||||
class QCheckBox;
|
||||
class QgsProcessingParameterDefinition;
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
/**
|
||||
* Processing map layer combo box.
|
||||
* \ingroup gui
|
||||
* \warning Not part of stable API and may change in future QGIS releases.
|
||||
* \since QGIS 3.8
|
||||
*/
|
||||
class GUI_EXPORT QgsProcessingMapLayerComboBox : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for QgsProcessingMapLayerComboBox, with the specified \a parameter definition.
|
||||
*/
|
||||
QgsProcessingMapLayerComboBox( QgsProcessingParameterDefinition *parameter, QWidget *parent = nullptr );
|
||||
|
||||
/**
|
||||
* Sets the combo box to the specified \a layer, if \a layer is compatible with the
|
||||
* widget's parameter definition.
|
||||
*/
|
||||
void setLayer( QgsMapLayer *layer );
|
||||
|
||||
/**
|
||||
* Returns the current layer selected in the combobox, or NULLPTR if the selection cannot
|
||||
* be represented as a map layer.
|
||||
*
|
||||
* \warning Prefer calling value() instead, as it correctly encapsulates all valid
|
||||
* values which can be represented by the widget.
|
||||
*
|
||||
* \see currentText()
|
||||
*/
|
||||
QgsMapLayer *currentLayer();
|
||||
|
||||
/**
|
||||
* Returns the current text of the selected item in the combobox.
|
||||
*
|
||||
* \warning Prefer calling value() instead, as it correctly encapsulates all valid
|
||||
* values which can be represented by the widget.
|
||||
*
|
||||
* \see currentLayer()
|
||||
*/
|
||||
QString currentText();
|
||||
|
||||
/**
|
||||
* Sets the \a value shown in the widget.
|
||||
*
|
||||
* \see value()
|
||||
*/
|
||||
void setValue( const QVariant &value, QgsProcessingContext &context );
|
||||
|
||||
/**
|
||||
* Returns the current value of the widget.
|
||||
*
|
||||
* \see setValue()
|
||||
*/
|
||||
QVariant value() const;
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
* Emitted whenever the value is changed in the widget.
|
||||
*/
|
||||
void valueChanged();
|
||||
|
||||
/**
|
||||
* Emitted when the widget has triggered a file selection operation (to be
|
||||
* handled in Python for now).
|
||||
*/
|
||||
void triggerFileSelection();
|
||||
|
||||
protected:
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent *event ) override;
|
||||
void dragLeaveEvent( QDragLeaveEvent *event ) override;
|
||||
void dropEvent( QDropEvent *event ) override;
|
||||
|
||||
private slots:
|
||||
|
||||
void onLayerChanged( QgsMapLayer *layer );
|
||||
void selectionChanged( const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect );
|
||||
|
||||
private:
|
||||
QgsProcessingParameterDefinition *mParameter = nullptr;
|
||||
QgsMapLayerComboBox *mCombo = nullptr;
|
||||
QToolButton *mSelectButton = nullptr;
|
||||
QCheckBox *mUseSelectionCheckBox = nullptr;
|
||||
bool mDragActive = false;
|
||||
QPointer< QgsMapLayer> mPrevLayer;
|
||||
int mBlockChangedSignal = 0;
|
||||
QgsMapLayer *compatibleMapLayerFromMimeData( const QMimeData *data, bool &incompatibleLayerSelected ) const;
|
||||
QString compatibleUriFromMimeData( const QMimeData *data ) const;
|
||||
};
|
||||
|
||||
///@endcond
|
||||
#endif // QGSPROCESSINGMAPLAYERCOMBOBOX_H
|
@ -208,7 +208,7 @@ void QgsMapLayerComboBox::dropEvent( QDropEvent *event )
|
||||
void QgsMapLayerComboBox::paintEvent( QPaintEvent *e )
|
||||
{
|
||||
QComboBox::paintEvent( e );
|
||||
if ( mDragActive )
|
||||
if ( mDragActive || mHighlight )
|
||||
{
|
||||
QPainter p( this );
|
||||
int width = 2; // width of highlight rectangle inside frame
|
||||
|
@ -153,12 +153,15 @@ class GUI_EXPORT QgsMapLayerComboBox : public QComboBox
|
||||
private:
|
||||
QgsMapLayerProxyModel *mProxyModel = nullptr;
|
||||
bool mDragActive = false;
|
||||
bool mHighlight = false;
|
||||
|
||||
/**
|
||||
* Returns a map layer, compatible with the filters set for the combo box, from
|
||||
* the specified mime \a data (if possible!).
|
||||
*/
|
||||
QgsMapLayer *compatibleMapLayerFromMimeData( const QMimeData *data ) const;
|
||||
|
||||
friend class QgsProcessingMapLayerComboBox;
|
||||
};
|
||||
|
||||
#endif // QGSMAPLAYERCOMBOBOX_H
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "qgsprocessingwidgetwrapperimpl.h"
|
||||
#include "qgsprocessingmodelerparameterwidget.h"
|
||||
#include "qgsprocessingparameters.h"
|
||||
#include "qgsprocessingmaplayercombobox.h"
|
||||
#include "qgsnativealgorithms.h"
|
||||
#include "processing/models/qgsprocessingmodelalgorithm.h"
|
||||
#include "qgsxmlutils.h"
|
||||
@ -58,6 +59,8 @@
|
||||
#include "qgslayoutitemcombobox.h"
|
||||
#include "qgslayoutitemlabel.h"
|
||||
#include "qgsscalewidget.h"
|
||||
#include "mesh/qgsmeshlayer.h"
|
||||
#include "mesh/qgsmeshdataprovider.h"
|
||||
|
||||
class TestParamType : public QgsProcessingParameterDefinition
|
||||
{
|
||||
@ -181,6 +184,7 @@ class TestProcessingGui : public QObject
|
||||
void testLayoutItemWrapper();
|
||||
void testPointPanel();
|
||||
void testPointWrapper();
|
||||
void mapLayerComboBox();
|
||||
|
||||
private:
|
||||
|
||||
@ -3011,6 +3015,416 @@ void TestProcessingGui::testPointWrapper()
|
||||
testWrapper( QgsProcessingGui::Modeler );
|
||||
}
|
||||
|
||||
void TestProcessingGui::mapLayerComboBox()
|
||||
{
|
||||
QgsProject::instance()->removeAllMapLayers();
|
||||
QgsProcessingContext context;
|
||||
context.setProject( QgsProject::instance() );
|
||||
|
||||
// feature source param
|
||||
std::unique_ptr< QgsProcessingParameterDefinition > param( new QgsProcessingParameterFeatureSource( QStringLiteral( "param" ), QString() ) );
|
||||
std::unique_ptr< QgsProcessingMapLayerComboBox> combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
|
||||
QSignalSpy spy( combo.get(), &QgsProcessingMapLayerComboBox::valueChanged );
|
||||
QVERIFY( !combo->value().isValid() );
|
||||
combo->setValue( QStringLiteral( "file path" ), context );
|
||||
QCOMPARE( spy.count(), 1 );
|
||||
QCOMPARE( combo->value().toString(), QStringLiteral( "file path" ) );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
QCOMPARE( spy.count(), 1 );
|
||||
combo->setValue( QVariant(), context ); // not possible, it's not an optional param
|
||||
QCOMPARE( combo->value().toString(), QStringLiteral( "file path" ) );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
QCOMPARE( spy.count(), 1 );
|
||||
combo->setValue( QStringLiteral( "file path 2" ), context );
|
||||
QCOMPARE( combo->value().toString(), QStringLiteral( "file path 2" ) );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
QCOMPARE( spy.count(), 2 );
|
||||
combo->setValue( QStringLiteral( "file path" ), context );
|
||||
QCOMPARE( combo->value().toString(), QStringLiteral( "file path" ) );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
QCOMPARE( spy.count(), 3 );
|
||||
combo->setLayer( nullptr ); // not possible, not optional
|
||||
QCOMPARE( combo->value().toString(), QStringLiteral( "file path" ) );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
QCOMPARE( spy.count(), 3 );
|
||||
|
||||
// project layers
|
||||
QgsVectorLayer *vl = new QgsVectorLayer( QStringLiteral( "LineString" ), QStringLiteral( "l1" ), QStringLiteral( "memory" ) );
|
||||
QgsFeature f;
|
||||
vl->dataProvider()->addFeature( f );
|
||||
QgsProject::instance()->addMapLayer( vl );
|
||||
QVERIFY( vl->isValid() );
|
||||
QgsVectorLayer *vl2 = new QgsVectorLayer( QStringLiteral( "LineString" ), QStringLiteral( "l2" ), QStringLiteral( "memory" ) );
|
||||
vl2->dataProvider()->addFeature( f );
|
||||
QgsProject::instance()->addMapLayer( vl2 );
|
||||
QVERIFY( vl2->isValid() );
|
||||
|
||||
QCOMPARE( combo->value().toString(), QStringLiteral( "file path" ) );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
QCOMPARE( spy.count(), 3 );
|
||||
|
||||
combo->setLayer( vl );
|
||||
QCOMPARE( combo->currentLayer(), vl );
|
||||
QCOMPARE( combo->value().toString(), vl->id() );
|
||||
QVERIFY( combo->currentText().startsWith( vl->name() ) );
|
||||
QCOMPARE( spy.count(), 4 );
|
||||
combo->setLayer( vl );
|
||||
QCOMPARE( spy.count(), 4 );
|
||||
|
||||
combo->setLayer( vl2 );
|
||||
QCOMPARE( combo->value().toString(), vl2->id() );
|
||||
QVERIFY( combo->currentText().startsWith( vl2->name() ) );
|
||||
QCOMPARE( spy.count(), 5 );
|
||||
|
||||
combo->setValue( QStringLiteral( "file path" ), context );
|
||||
QCOMPARE( combo->value().toString(), QStringLiteral( "file path" ) );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
QCOMPARE( spy.count(), 6 );
|
||||
|
||||
// setting feature source def, i.e. with selection
|
||||
QgsProcessingFeatureSourceDefinition sourceDef( vl2->id(), false );
|
||||
combo->setValue( sourceDef, context );
|
||||
QCOMPARE( combo->value().toString(), vl2->id() );
|
||||
QVERIFY( combo->currentText().startsWith( vl2->name() ) );
|
||||
QCOMPARE( spy.count(), 7 );
|
||||
// asking for selected features only, but no selection in layer, won't be allowed
|
||||
sourceDef = QgsProcessingFeatureSourceDefinition( vl2->id(), true );
|
||||
combo->setValue( sourceDef, context );
|
||||
QCOMPARE( combo->value().toString(), vl2->id() );
|
||||
QVERIFY( combo->currentText().startsWith( vl2->name() ) );
|
||||
QCOMPARE( spy.count(), 7 ); // no change
|
||||
|
||||
// now make a selection in the layer, and repeat
|
||||
vl2->selectAll();
|
||||
combo->setValue( sourceDef, context );
|
||||
QVERIFY( combo->value().canConvert< QgsProcessingFeatureSourceDefinition >() );
|
||||
QCOMPARE( combo->value().value< QgsProcessingFeatureSourceDefinition >().source.staticValue().toString(), vl2->id() );
|
||||
QVERIFY( combo->value().value< QgsProcessingFeatureSourceDefinition >().selectedFeaturesOnly );
|
||||
QVERIFY( combo->currentText().startsWith( vl2->name() ) );
|
||||
QCOMPARE( spy.count(), 8 );
|
||||
|
||||
// remove layer selection, and check result...
|
||||
vl2->removeSelection();
|
||||
QCOMPARE( combo->value().toString(), vl2->id() );
|
||||
QVERIFY( combo->currentText().startsWith( vl2->name() ) );
|
||||
QCOMPARE( spy.count(), 9 );
|
||||
|
||||
// phew, nearly there. Let's check another variation
|
||||
vl2->selectAll();
|
||||
combo->setValue( sourceDef, context );
|
||||
QVERIFY( combo->value().canConvert< QgsProcessingFeatureSourceDefinition >() );
|
||||
QCOMPARE( spy.count(), 10 );
|
||||
combo->setValue( QVariant::fromValue( vl ), context );
|
||||
QCOMPARE( combo->value().toString(), vl->id() );
|
||||
QVERIFY( combo->currentText().startsWith( vl->name() ) );
|
||||
QCOMPARE( spy.count(), 11 );
|
||||
|
||||
// one last variation - selection to selection
|
||||
combo->setValue( sourceDef, context );
|
||||
QCOMPARE( spy.count(), 12 );
|
||||
QVERIFY( combo->value().value< QgsProcessingFeatureSourceDefinition >().selectedFeaturesOnly );
|
||||
vl->selectAll();
|
||||
sourceDef = QgsProcessingFeatureSourceDefinition( vl->id(), true );
|
||||
combo->setValue( sourceDef, context );
|
||||
// except "selected only" state to remain
|
||||
QVERIFY( combo->value().canConvert< QgsProcessingFeatureSourceDefinition >() );
|
||||
QCOMPARE( combo->value().value< QgsProcessingFeatureSourceDefinition >().source.staticValue().toString(), vl->id() );
|
||||
QVERIFY( combo->value().value< QgsProcessingFeatureSourceDefinition >().selectedFeaturesOnly );
|
||||
QVERIFY( combo->currentText().startsWith( vl->name() ) );
|
||||
QCOMPARE( spy.count(), 13 );
|
||||
|
||||
// setup a project with a range of layer types
|
||||
QgsProject::instance()->removeAllMapLayers();
|
||||
QgsVectorLayer *point = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "l1" ), QStringLiteral( "memory" ) );
|
||||
QgsProject::instance()->addMapLayer( point );
|
||||
QgsVectorLayer *line = new QgsVectorLayer( QStringLiteral( "LineString" ), QStringLiteral( "l1" ), QStringLiteral( "memory" ) );
|
||||
QgsProject::instance()->addMapLayer( line );
|
||||
QgsVectorLayer *polygon = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "l1" ), QStringLiteral( "memory" ) );
|
||||
QgsProject::instance()->addMapLayer( polygon );
|
||||
QgsVectorLayer *noGeom = new QgsVectorLayer( QStringLiteral( "None" ), QStringLiteral( "l1" ), QStringLiteral( "memory" ) );
|
||||
QgsProject::instance()->addMapLayer( noGeom );
|
||||
QgsMeshLayer *mesh = new QgsMeshLayer( QStringLiteral( TEST_DATA_DIR ) + "/mesh/quad_and_triangle.2dm", QStringLiteral( "Triangle and Quad Mdal" ), QStringLiteral( "mdal" ) );
|
||||
mesh->dataProvider()->addDataset( QStringLiteral( TEST_DATA_DIR ) + "/mesh/quad_and_triangle_vertex_scalar_with_inactive_face.dat" );
|
||||
QVERIFY( mesh->isValid() );
|
||||
QgsProject::instance()->addMapLayer( mesh );
|
||||
QgsRasterLayer *raster = new QgsRasterLayer( QStringLiteral( TEST_DATA_DIR ) + "/raster/band1_byte_ct_epsg4326.tif", QStringLiteral( "band1_byte" ) );
|
||||
QgsProject::instance()->addMapLayer( raster );
|
||||
|
||||
// map layer param, all types are acceptable
|
||||
param = qgis::make_unique< QgsProcessingParameterMapLayer> ( QStringLiteral( "param" ), QString() );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
combo->setLayer( point );
|
||||
QCOMPARE( combo->currentLayer(), point );
|
||||
combo->setLayer( line );
|
||||
QCOMPARE( combo->currentLayer(), line );
|
||||
combo->setLayer( polygon );
|
||||
QCOMPARE( combo->currentLayer(), polygon );
|
||||
combo->setLayer( noGeom );
|
||||
QCOMPARE( combo->currentLayer(), noGeom );
|
||||
combo->setLayer( mesh );
|
||||
QCOMPARE( combo->currentLayer(), mesh );
|
||||
combo->setLayer( raster );
|
||||
QCOMPARE( combo->currentLayer(), raster );
|
||||
|
||||
// raster layer param, only raster types are acceptable
|
||||
param = qgis::make_unique< QgsProcessingParameterRasterLayer> ( QStringLiteral( "param" ), QString() );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
combo->setLayer( point );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo->setLayer( line );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo->setLayer( polygon );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo->setLayer( noGeom );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo->setLayer( mesh );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo->setLayer( raster );
|
||||
QCOMPARE( combo->currentLayer(), raster );
|
||||
|
||||
// mesh layer parm, only mesh types are acceptable
|
||||
param = qgis::make_unique< QgsProcessingParameterMeshLayer> ( QStringLiteral( "param" ), QString() );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
combo->setLayer( point );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo->setLayer( line );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo->setLayer( polygon );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo->setLayer( noGeom );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo->setLayer( mesh );
|
||||
QCOMPARE( combo->currentLayer(), mesh );
|
||||
combo->setLayer( raster );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
|
||||
// feature source and vector layer params
|
||||
// if not specified, the default is any vector layer with geometry
|
||||
param = qgis::make_unique< QgsProcessingParameterVectorLayer> ( QStringLiteral( "param" ) );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
auto param2 = qgis::make_unique< QgsProcessingParameterFeatureSource> ( QStringLiteral( "param" ) );
|
||||
auto combo2 = qgis::make_unique< QgsProcessingMapLayerComboBox >( param2.get() );
|
||||
combo->setLayer( point );
|
||||
QCOMPARE( combo->currentLayer(), point );
|
||||
combo2->setLayer( point );
|
||||
QCOMPARE( combo2->currentLayer(), point );
|
||||
combo->setLayer( line );
|
||||
QCOMPARE( combo->currentLayer(), line );
|
||||
combo2->setLayer( line );
|
||||
QCOMPARE( combo2->currentLayer(), line );
|
||||
combo->setLayer( polygon );
|
||||
QCOMPARE( combo->currentLayer(), polygon );
|
||||
combo2->setLayer( polygon );
|
||||
QCOMPARE( combo2->currentLayer(), polygon );
|
||||
combo->setLayer( noGeom );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( noGeom );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( mesh );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( mesh );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( raster );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( raster );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
|
||||
// point layer
|
||||
param = qgis::make_unique< QgsProcessingParameterVectorLayer> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorPoint );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
param2 = qgis::make_unique< QgsProcessingParameterFeatureSource> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorPoint );
|
||||
combo2 = qgis::make_unique< QgsProcessingMapLayerComboBox >( param2.get() );
|
||||
combo->setLayer( point );
|
||||
QCOMPARE( combo->currentLayer(), point );
|
||||
combo2->setLayer( point );
|
||||
QCOMPARE( combo2->currentLayer(), point );
|
||||
combo->setLayer( line );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( line );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( polygon );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( polygon );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( noGeom );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( noGeom );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( mesh );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( mesh );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( raster );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( raster );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
|
||||
// line layer
|
||||
param = qgis::make_unique< QgsProcessingParameterVectorLayer> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorLine );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
param2 = qgis::make_unique< QgsProcessingParameterFeatureSource> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorLine );
|
||||
combo2 = qgis::make_unique< QgsProcessingMapLayerComboBox >( param2.get() );
|
||||
combo->setLayer( point );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( point );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( line );
|
||||
QCOMPARE( combo->currentLayer(), line );
|
||||
combo2->setLayer( line );
|
||||
QCOMPARE( combo2->currentLayer(), line );
|
||||
combo->setLayer( polygon );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( polygon );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( noGeom );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( noGeom );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( mesh );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( mesh );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( raster );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( raster );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
|
||||
// polygon
|
||||
param = qgis::make_unique< QgsProcessingParameterVectorLayer> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorPolygon );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
param2 = qgis::make_unique< QgsProcessingParameterFeatureSource> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorPolygon );
|
||||
combo2 = qgis::make_unique< QgsProcessingMapLayerComboBox >( param2.get() );
|
||||
combo->setLayer( point );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( point );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( line );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( line );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( polygon );
|
||||
QCOMPARE( combo->currentLayer(), polygon );
|
||||
combo2->setLayer( polygon );
|
||||
QCOMPARE( combo2->currentLayer(), polygon );
|
||||
combo->setLayer( noGeom );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( noGeom );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( mesh );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( mesh );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( raster );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( raster );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
|
||||
// no geom
|
||||
param = qgis::make_unique< QgsProcessingParameterVectorLayer> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVector );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
param2 = qgis::make_unique< QgsProcessingParameterFeatureSource> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVector );
|
||||
combo2 = qgis::make_unique< QgsProcessingMapLayerComboBox >( param2.get() );
|
||||
combo->setLayer( point );
|
||||
QCOMPARE( combo->currentLayer(), point );
|
||||
combo2->setLayer( point );
|
||||
QCOMPARE( combo2->currentLayer(), point );
|
||||
combo->setLayer( line );
|
||||
QCOMPARE( combo->currentLayer(), line );
|
||||
combo2->setLayer( line );
|
||||
QCOMPARE( combo2->currentLayer(), line );
|
||||
combo->setLayer( polygon );
|
||||
QCOMPARE( combo->currentLayer(), polygon );
|
||||
combo2->setLayer( polygon );
|
||||
QCOMPARE( combo2->currentLayer(), polygon );
|
||||
combo->setLayer( noGeom );
|
||||
QCOMPARE( combo->currentLayer(), noGeom );
|
||||
combo2->setLayer( noGeom );
|
||||
QCOMPARE( combo2->currentLayer(), noGeom );
|
||||
combo->setLayer( mesh );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( mesh );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( raster );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( raster );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
|
||||
// any geom
|
||||
param = qgis::make_unique< QgsProcessingParameterVectorLayer> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorAnyGeometry );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
param2 = qgis::make_unique< QgsProcessingParameterFeatureSource> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorAnyGeometry );
|
||||
combo2 = qgis::make_unique< QgsProcessingMapLayerComboBox >( param2.get() );
|
||||
combo->setLayer( point );
|
||||
QCOMPARE( combo->currentLayer(), point );
|
||||
combo2->setLayer( point );
|
||||
QCOMPARE( combo2->currentLayer(), point );
|
||||
combo->setLayer( line );
|
||||
QCOMPARE( combo->currentLayer(), line );
|
||||
combo2->setLayer( line );
|
||||
QCOMPARE( combo2->currentLayer(), line );
|
||||
combo->setLayer( polygon );
|
||||
QCOMPARE( combo->currentLayer(), polygon );
|
||||
combo2->setLayer( polygon );
|
||||
QCOMPARE( combo2->currentLayer(), polygon );
|
||||
combo->setLayer( noGeom );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( noGeom );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( mesh );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( mesh );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( raster );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( raster );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
|
||||
// combination point and line only
|
||||
param = qgis::make_unique< QgsProcessingParameterVectorLayer> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorPoint << QgsProcessing::TypeVectorLine );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
param2 = qgis::make_unique< QgsProcessingParameterFeatureSource> ( QStringLiteral( "param" ), QString(), QList< int>() << QgsProcessing::TypeVectorPoint << QgsProcessing::TypeVectorLine );
|
||||
combo2 = qgis::make_unique< QgsProcessingMapLayerComboBox >( param2.get() );
|
||||
combo->setLayer( point );
|
||||
QCOMPARE( combo->currentLayer(), point );
|
||||
combo2->setLayer( point );
|
||||
QCOMPARE( combo2->currentLayer(), point );
|
||||
combo->setLayer( line );
|
||||
QCOMPARE( combo->currentLayer(), line );
|
||||
combo2->setLayer( line );
|
||||
QCOMPARE( combo2->currentLayer(), line );
|
||||
combo->setLayer( polygon );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( polygon );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( noGeom );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( noGeom );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( mesh );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( mesh );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
combo->setLayer( raster );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
combo2->setLayer( raster );
|
||||
QVERIFY( !combo2->currentLayer() );
|
||||
|
||||
// optional
|
||||
param = qgis::make_unique< QgsProcessingParameterVectorLayer> ( QStringLiteral( "param" ), QString(), QList< int>(), QVariant(), true );
|
||||
combo = qgis::make_unique< QgsProcessingMapLayerComboBox >( param.get() );
|
||||
combo->setLayer( point );
|
||||
QCOMPARE( combo->currentLayer(), point );
|
||||
combo->setLayer( nullptr );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
QVERIFY( !combo->value().isValid() );
|
||||
combo->setLayer( point );
|
||||
QCOMPARE( combo->currentLayer(), point );
|
||||
combo->setValue( QVariant(), context );
|
||||
QVERIFY( !combo->currentLayer() );
|
||||
QVERIFY( !combo->value().isValid() );
|
||||
}
|
||||
|
||||
void TestProcessingGui::cleanupTempDir()
|
||||
{
|
||||
QDir tmpDir = QDir( mTempDir );
|
||||
|
Loading…
x
Reference in New Issue
Block a user