mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-17 00:09:36 -04:00
parent
dbe9aa0902
commit
146094f6b2
@ -92,6 +92,13 @@ corresponding expression.
|
||||
void scrollTo( const QModelIndex &index ) const;
|
||||
%Docstring
|
||||
Scroll the fields view to ``index``
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
||||
void changed();
|
||||
%Docstring
|
||||
Emitted when the fields defined in the widget are changed.
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
@ -54,170 +54,13 @@ from processing.gui.wrappers import WidgetWrapper, DIALOG_STANDARD, DIALOG_MODEL
|
||||
from processing.tools import dataobjects
|
||||
|
||||
|
||||
pluginPath = os.path.dirname(__file__)
|
||||
WIDGET, BASE = uic.loadUiType(
|
||||
os.path.join(pluginPath, 'fieldsmappingpanelbase.ui'))
|
||||
|
||||
|
||||
class FieldsMappingPanel(BASE, WIDGET):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(FieldsMappingPanel, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.addButton.setIcon(QgsApplication.getThemeIcon("/mActionNewAttribute.svg"))
|
||||
self.deleteButton.setIcon(QgsApplication.getThemeIcon('/mActionDeleteAttribute.svg'))
|
||||
self.upButton.setIcon(QgsApplication.getThemeIcon('/mActionArrowUp.svg'))
|
||||
self.downButton.setIcon(QgsApplication.getThemeIcon('/mActionArrowDown.svg'))
|
||||
self.resetButton.setIcon(QgsApplication.getThemeIcon('/mIconClearText.svg'))
|
||||
|
||||
self.configure()
|
||||
|
||||
self.layerCombo.setAllowEmptyLayer(True)
|
||||
self.layerCombo.setFilters(QgsMapLayerProxyModel.VectorLayer)
|
||||
self.dialogType = None
|
||||
self.layer = None
|
||||
|
||||
def configure(self):
|
||||
self.model = self.fieldsView.model()
|
||||
self.fieldsView.setDestinationEditable(True)
|
||||
|
||||
def setLayer(self, layer):
|
||||
if layer is None or self.layer == layer:
|
||||
return
|
||||
self.layer = layer
|
||||
if self.model.rowCount(QModelIndex()) == 0:
|
||||
self.on_resetButton_clicked()
|
||||
return
|
||||
dlg = QMessageBox(self)
|
||||
dlg.setText(self.tr("Do you want to reset the field mapping?"))
|
||||
dlg.setStandardButtons(
|
||||
QMessageBox.StandardButtons(QMessageBox.Yes |
|
||||
QMessageBox.No))
|
||||
dlg.setDefaultButton(QMessageBox.No)
|
||||
if dlg.exec_() == QMessageBox.Yes:
|
||||
self.on_resetButton_clicked()
|
||||
|
||||
def value(self):
|
||||
# Value is a dict with name, type, length, precision and expression
|
||||
mapping = self.fieldsView.mapping()
|
||||
results = []
|
||||
for f in mapping:
|
||||
results.append({
|
||||
'name': f.field.name(),
|
||||
'type': f.field.type(),
|
||||
'length': f.field.length(),
|
||||
'precision': f.field.precision(),
|
||||
'expression': f.expression,
|
||||
})
|
||||
return results
|
||||
|
||||
def setValue(self, value):
|
||||
if type(value) != dict:
|
||||
return
|
||||
destinationFields = QgsFields()
|
||||
expressions = {}
|
||||
for field_def in value:
|
||||
f = QgsField(field_def.get('name'),
|
||||
field_def.get('type', QVariant.Invalid),
|
||||
field_def.get(QVariant.typeToName(field_def.get('type', QVariant.Invalid))),
|
||||
field_def.get('length', 0),
|
||||
field_def.get('precision', 0))
|
||||
try:
|
||||
expressions[f.name()] = field_def['expressions']
|
||||
except AttributeError:
|
||||
pass
|
||||
destinationFields.append(f)
|
||||
|
||||
if len(destinationFields):
|
||||
self.fieldsView.setDestinationFields(destinationFields, expressions)
|
||||
|
||||
@pyqtSlot(bool, name='on_addButton_clicked')
|
||||
def on_addButton_clicked(self, checked=False):
|
||||
rowCount = self.model.rowCount(QModelIndex())
|
||||
self.model.appendField(QgsField('new_field'))
|
||||
index = self.model.index(rowCount, 0)
|
||||
self.fieldsView.selectionModel().select(
|
||||
index,
|
||||
QItemSelectionModel.SelectionFlags(
|
||||
QItemSelectionModel.Clear |
|
||||
QItemSelectionModel.Select |
|
||||
QItemSelectionModel.Current |
|
||||
QItemSelectionModel.Rows))
|
||||
self.fieldsView.scrollTo(index)
|
||||
|
||||
@pyqtSlot(bool, name='on_deleteButton_clicked')
|
||||
def on_deleteButton_clicked(self, checked=False):
|
||||
self.fieldsView.removeSelectedFields()
|
||||
|
||||
@pyqtSlot(bool, name='on_upButton_clicked')
|
||||
def on_upButton_clicked(self, checked=False):
|
||||
self.fieldsView.moveSelectedFieldsUp()
|
||||
|
||||
@pyqtSlot(bool, name='on_downButton_clicked')
|
||||
def on_downButton_clicked(self, checked=False):
|
||||
self.fieldsView.moveSelectedFieldsDown()
|
||||
|
||||
@pyqtSlot(bool, name='on_resetButton_clicked')
|
||||
def on_resetButton_clicked(self, checked=False):
|
||||
"""Load fields from layer"""
|
||||
if self.layer:
|
||||
self.fieldsView.setSourceFields(self.layer.fields())
|
||||
self.fieldsView.setDestinationFields(self.layer.fields())
|
||||
|
||||
@pyqtSlot(bool, name='on_loadLayerFieldsButton_clicked')
|
||||
def on_loadLayerFieldsButton_clicked(self, checked=False):
|
||||
layer = self.layerCombo.currentLayer()
|
||||
if layer is None:
|
||||
return
|
||||
|
||||
self.fieldsView.setSourceFields(layer.fields())
|
||||
self.fieldsView.setDestinationFields(layer.fields())
|
||||
|
||||
|
||||
class FieldsMappingWidgetWrapper(WidgetWrapper):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(FieldsMappingWidgetWrapper, self).__init__(*args, **kwargs)
|
||||
self._layer = None
|
||||
|
||||
def createPanel(self):
|
||||
return FieldsMappingPanel()
|
||||
|
||||
def createWidget(self):
|
||||
self.panel = self.createPanel()
|
||||
self.panel.dialogType = self.dialogType
|
||||
|
||||
if self.dialogType == DIALOG_MODELER:
|
||||
self.combobox = QComboBox()
|
||||
self.combobox.addItem(QCoreApplication.translate('Processing', '[Preconfigure]'), None)
|
||||
#fieldsMappingInputs = self.dialog.getAvailableValuesOfType(FieldsMapper.ParameterFieldsMapping)
|
||||
#for input in fieldsMappingInputs:
|
||||
# self.combobox.addItem(self.dialog.resolveValueDescription(input), input)
|
||||
|
||||
def updatePanelEnabledState():
|
||||
if self.combobox.currentData() is None:
|
||||
self.panel.setEnabled(True)
|
||||
else:
|
||||
self.panel.setEnabled(False)
|
||||
|
||||
self.combobox.currentIndexChanged.connect(updatePanelEnabledState)
|
||||
|
||||
widget = QWidget()
|
||||
widget.setLayout(QVBoxLayout())
|
||||
widget.layout().addWidget(self.combobox)
|
||||
widget.layout().addWidget(self.panel)
|
||||
return widget
|
||||
else:
|
||||
return self.panel
|
||||
|
||||
def postInitialize(self, wrappers):
|
||||
for wrapper in wrappers:
|
||||
if wrapper.parameterDefinition().name() == self.parameterDefinition().parentLayerParameterName():
|
||||
if wrapper.parameterValue():
|
||||
self.setLayer(wrapper.parameterValue())
|
||||
wrapper.widgetValueHasChanged.connect(self.parentLayerChanged)
|
||||
break
|
||||
|
||||
# remove exiting spacers to get FieldsMappingPanel fully expanded
|
||||
if self.dialogType in (DIALOG_STANDARD, DIALOG_MODELER):
|
||||
@ -225,34 +68,3 @@ class FieldsMappingWidgetWrapper(WidgetWrapper):
|
||||
spacer = layout.itemAt(layout.count() - 1)
|
||||
if isinstance(spacer, QSpacerItem):
|
||||
layout.removeItem(spacer)
|
||||
|
||||
def parentLayerChanged(self, layer=None):
|
||||
self.setLayer(self.sender().widgetValue())
|
||||
|
||||
def setLayer(self, layer):
|
||||
context = dataobjects.createContext()
|
||||
if layer == self._layer:
|
||||
return
|
||||
if isinstance(layer, QgsProcessingFeatureSourceDefinition):
|
||||
layer, ok = layer.source.valueAsString(context.expressionContext())
|
||||
if isinstance(layer, str):
|
||||
layer = QgsProcessingUtils.mapLayerFromString(layer, context)
|
||||
if not isinstance(layer, QgsVectorLayer):
|
||||
layer = None
|
||||
self._layer = layer
|
||||
self.panel.setLayer(self._layer)
|
||||
|
||||
def linkedVectorLayer(self):
|
||||
return self._layer
|
||||
|
||||
def setValue(self, value):
|
||||
self.panel.setValue(value)
|
||||
|
||||
def value(self):
|
||||
if self.dialogType == DIALOG_MODELER:
|
||||
if self.combobox.currentData() is None:
|
||||
return self.panel.value()
|
||||
else:
|
||||
return self.comboValue(combobox=self.combobox)
|
||||
else:
|
||||
return self.panel.value()
|
||||
|
@ -79,10 +79,6 @@ QgsRefactorFieldsAlgorithm *QgsRefactorFieldsAlgorithm::createInstance() const
|
||||
void QgsRefactorFieldsAlgorithm::initParameters( const QVariantMap & )
|
||||
{
|
||||
std::unique_ptr< QgsProcessingParameterFieldMapping > param = qgis::make_unique< QgsProcessingParameterFieldMapping> ( QStringLiteral( "FIELDS_MAPPING" ), QObject::tr( "Fields mapping" ), QStringLiteral( "INPUT" ) );
|
||||
|
||||
QVariantMap metadata;
|
||||
metadata.insert( QStringLiteral( "widget_wrapper" ), QStringLiteral( "processing.algs.qgis.ui.FieldsMappingPanel.FieldsMappingWidgetWrapper" ) );
|
||||
param->setMetadata( metadata );
|
||||
addParameter( param.release() );
|
||||
}
|
||||
|
||||
|
@ -270,6 +270,7 @@ SET(QGIS_GUI_SRCS
|
||||
processing/qgsprocessingconfigurationwidgets.cpp
|
||||
processing/qgsprocessingenummodelerwidget.cpp
|
||||
processing/qgsprocessingfeaturesourceoptionswidget.cpp
|
||||
processing/qgsprocessingfieldmapwidgetwrapper.cpp
|
||||
processing/qgsprocessingguiregistry.cpp
|
||||
processing/qgsprocessingmaplayercombobox.cpp
|
||||
processing/qgsprocessingmatrixmodelerwidget.cpp
|
||||
@ -991,6 +992,7 @@ SET(QGIS_GUI_HDRS
|
||||
processing/qgsprocessingconfigurationwidgets.h
|
||||
processing/qgsprocessingenummodelerwidget.h
|
||||
processing/qgsprocessingfeaturesourceoptionswidget.h
|
||||
processing/qgsprocessingfieldmapwidgetwrapper.h
|
||||
processing/qgsprocessinggui.h
|
||||
processing/qgsprocessingguiregistry.h
|
||||
processing/qgsprocessingmaplayercombobox.h
|
||||
|
315
src/gui/processing/qgsprocessingfieldmapwidgetwrapper.cpp
Normal file
315
src/gui/processing/qgsprocessingfieldmapwidgetwrapper.cpp
Normal file
@ -0,0 +1,315 @@
|
||||
/***************************************************************************
|
||||
qgsprocessingfieldmapwidgetwrapper.cpp
|
||||
---------------------
|
||||
Date : June 2020
|
||||
Copyright : (C) 2020 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 "qgsprocessingfieldmapwidgetwrapper.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QStandardItemModel>
|
||||
#include <QToolButton>
|
||||
|
||||
#include "qgspanelwidget.h"
|
||||
|
||||
#include "qgsprocessingcontext.h"
|
||||
#include "qgsvectortilewriter.h"
|
||||
|
||||
#include "qgsprocessingparameterfieldmap.h"
|
||||
|
||||
/// @cond private
|
||||
|
||||
//
|
||||
// QgsProcessingFieldMapPanelWidget
|
||||
//
|
||||
|
||||
|
||||
QgsProcessingFieldMapPanelWidget::QgsProcessingFieldMapPanelWidget( QWidget *parent )
|
||||
: QgsPanelWidget( parent )
|
||||
{
|
||||
setupUi( this );
|
||||
|
||||
mModel = mFieldsView->model();
|
||||
mFieldsView->setDestinationEditable( true );
|
||||
|
||||
mLayerCombo->setAllowEmptyLayer( true );
|
||||
mLayerCombo->setFilters( QgsMapLayerProxyModel::VectorLayer );
|
||||
|
||||
connect( mResetButton, &QPushButton::clicked, this, &QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer );
|
||||
connect( mAddButton, &QPushButton::clicked, this, &QgsProcessingFieldMapPanelWidget::addField );
|
||||
connect( mDeleteButton, &QPushButton::clicked, mFieldsView, &QgsFieldMappingWidget::removeSelectedFields );
|
||||
connect( mUpButton, &QPushButton::clicked, mFieldsView, &QgsFieldMappingWidget::moveSelectedFieldsUp );
|
||||
connect( mDownButton, &QPushButton::clicked, mFieldsView, &QgsFieldMappingWidget::moveSelectedFieldsDown );
|
||||
connect( mLoadLayerFieldsButton, &QPushButton::clicked, this, &QgsProcessingFieldMapPanelWidget::loadLayerFields );
|
||||
|
||||
connect( mFieldsView, &QgsFieldMappingWidget::changed, this, [ = ]
|
||||
{
|
||||
if ( !mBlockChangedSignal )
|
||||
{
|
||||
emit changed();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
void QgsProcessingFieldMapPanelWidget::setLayer( QgsVectorLayer *layer )
|
||||
{
|
||||
if ( layer == mLayer )
|
||||
return;
|
||||
|
||||
mLayer = layer;
|
||||
if ( mModel->rowCount() == 0 )
|
||||
{
|
||||
loadFieldsFromLayer();
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox dlg( this );
|
||||
dlg.setText( tr( "Do you want to reset the field mapping?" ) );
|
||||
dlg.setStandardButtons(
|
||||
QMessageBox::StandardButtons( QMessageBox::Yes |
|
||||
QMessageBox::No ) );
|
||||
dlg.setDefaultButton( QMessageBox::No );
|
||||
if ( dlg.exec() == QMessageBox::Yes )
|
||||
{
|
||||
loadFieldsFromLayer();
|
||||
}
|
||||
}
|
||||
|
||||
QgsVectorLayer *QgsProcessingFieldMapPanelWidget::layer()
|
||||
{
|
||||
return mLayer;
|
||||
}
|
||||
|
||||
QVariant QgsProcessingFieldMapPanelWidget::value() const
|
||||
{
|
||||
const QList<QgsFieldMappingModel::Field> mapping = mFieldsView->mapping();
|
||||
|
||||
QVariantList results;
|
||||
results.reserve( mapping.size() );
|
||||
for ( const QgsFieldMappingModel::Field &field : mapping )
|
||||
{
|
||||
QVariantMap def;
|
||||
def.insert( QStringLiteral( "name" ), field.field.name() );
|
||||
def.insert( QStringLiteral( "type" ), static_cast< int >( field.field.type() ) );
|
||||
def.insert( QStringLiteral( "length" ), field.field.length() );
|
||||
def.insert( QStringLiteral( "precision" ), field.field.precision() );
|
||||
def.insert( QStringLiteral( "expression" ), field.expression );
|
||||
results.append( def );
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
void QgsProcessingFieldMapPanelWidget::setValue( const QVariant &value )
|
||||
{
|
||||
if ( value.type() != QVariant::List )
|
||||
return;
|
||||
|
||||
QgsFields destinationFields;
|
||||
QMap<QString, QString> expressions;
|
||||
|
||||
const QVariantList fields = value.toList();
|
||||
for ( const QVariant &field : fields )
|
||||
{
|
||||
const QVariantMap map = field.toMap();
|
||||
QgsField f( map.value( QStringLiteral( "name" ) ).toString(),
|
||||
static_cast< QVariant::Type >( map.value( QStringLiteral( "type" ), QVariant::Invalid ).toInt() ),
|
||||
QVariant::typeToName( static_cast< QVariant::Type >( map.value( QStringLiteral( "type" ), QVariant::Invalid ).toInt() ) ),
|
||||
map.value( QStringLiteral( "length" ), 0 ).toInt(),
|
||||
map.value( QStringLiteral( "precision" ), 0 ).toInt() );
|
||||
|
||||
if ( !map.value( QStringLiteral( "expression" ) ).toString().isEmpty() )
|
||||
{
|
||||
expressions.insert( f.name(), map.value( QStringLiteral( "expression" ) ).toString() );
|
||||
}
|
||||
|
||||
destinationFields.append( f );
|
||||
}
|
||||
|
||||
mBlockChangedSignal = true;
|
||||
if ( destinationFields.size() > 0 )
|
||||
mFieldsView->setDestinationFields( destinationFields, expressions );
|
||||
mBlockChangedSignal = false;
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void QgsProcessingFieldMapPanelWidget::loadFieldsFromLayer()
|
||||
{
|
||||
if ( mLayer )
|
||||
{
|
||||
mFieldsView->setSourceFields( mLayer->fields() );
|
||||
mFieldsView->setDestinationFields( mLayer->fields() );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsProcessingFieldMapPanelWidget::addField()
|
||||
{
|
||||
const int rowCount = mModel->rowCount();
|
||||
mModel->appendField( QgsField( QStringLiteral( "new_field" ) ) );
|
||||
QModelIndex index = mModel->index( rowCount, 0 );
|
||||
mFieldsView->selectionModel()->select(
|
||||
index,
|
||||
QItemSelectionModel::SelectionFlags(
|
||||
QItemSelectionModel::Clear |
|
||||
QItemSelectionModel::Select |
|
||||
QItemSelectionModel::Current |
|
||||
QItemSelectionModel::Rows ) );
|
||||
mFieldsView->scrollTo( index );
|
||||
}
|
||||
|
||||
void QgsProcessingFieldMapPanelWidget::loadLayerFields()
|
||||
{
|
||||
if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( mLayerCombo->currentLayer() ) )
|
||||
{
|
||||
mFieldsView->setSourceFields( vl->fields() );
|
||||
mFieldsView->setDestinationFields( vl->fields() );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// QgsProcessingFieldMapWidgetWrapper
|
||||
//
|
||||
|
||||
QgsProcessingFieldMapWidgetWrapper::QgsProcessingFieldMapWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
|
||||
: QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
|
||||
{
|
||||
}
|
||||
|
||||
QString QgsProcessingFieldMapWidgetWrapper::parameterType() const
|
||||
{
|
||||
return QgsProcessingParameterFieldMapping::typeName();
|
||||
}
|
||||
|
||||
QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingFieldMapWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
|
||||
{
|
||||
return new QgsProcessingFieldMapWidgetWrapper( parameter, type );
|
||||
}
|
||||
|
||||
QWidget *QgsProcessingFieldMapWidgetWrapper::createWidget()
|
||||
{
|
||||
mPanel = new QgsProcessingFieldMapPanelWidget( nullptr );
|
||||
mPanel->setToolTip( parameterDefinition()->toolTip() );
|
||||
|
||||
connect( mPanel, &QgsProcessingFieldMapPanelWidget::changed, this, [ = ]
|
||||
{
|
||||
emit widgetValueHasChanged( this );
|
||||
} );
|
||||
|
||||
return mPanel;
|
||||
}
|
||||
|
||||
void QgsProcessingFieldMapWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
|
||||
{
|
||||
QgsAbstractProcessingParameterWidgetWrapper::postInitialize( wrappers );
|
||||
switch ( type() )
|
||||
{
|
||||
case QgsProcessingGui::Standard:
|
||||
case QgsProcessingGui::Batch:
|
||||
{
|
||||
for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
|
||||
{
|
||||
if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterFieldMapping * >( parameterDefinition() )->parentLayerParameterName() )
|
||||
{
|
||||
setParentLayerWrapperValue( wrapper );
|
||||
connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
|
||||
{
|
||||
setParentLayerWrapperValue( wrapper );
|
||||
} );
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsProcessingGui::Modeler:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsProcessingFieldMapWidgetWrapper::setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper )
|
||||
{
|
||||
// evaluate value to layer
|
||||
QgsProcessingContext *context = nullptr;
|
||||
std::unique_ptr< QgsProcessingContext > tmpContext;
|
||||
if ( mProcessingContextGenerator )
|
||||
context = mProcessingContextGenerator->processingContext();
|
||||
|
||||
if ( !context )
|
||||
{
|
||||
tmpContext = qgis::make_unique< QgsProcessingContext >();
|
||||
context = tmpContext.get();
|
||||
}
|
||||
|
||||
QgsVectorLayer *layer = QgsProcessingParameters::parameterAsVectorLayer( parentWrapper->parameterDefinition(), parentWrapper->parameterValue(), *context );
|
||||
if ( !layer )
|
||||
{
|
||||
if ( mPanel )
|
||||
mPanel->setLayer( nullptr );
|
||||
return;
|
||||
}
|
||||
|
||||
// need to grab ownership of layer if required - otherwise layer may be deleted when context
|
||||
// goes out of scope
|
||||
std::unique_ptr< QgsMapLayer > ownedLayer( context->takeResultLayer( layer->id() ) );
|
||||
if ( ownedLayer && ownedLayer->type() == QgsMapLayerType::VectorLayer )
|
||||
{
|
||||
mParentLayer.reset( qobject_cast< QgsVectorLayer * >( ownedLayer.release() ) );
|
||||
layer = mParentLayer.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't need ownership of this layer - it wasn't owned by context (so e.g. is owned by the project)
|
||||
}
|
||||
|
||||
if ( mPanel )
|
||||
mPanel->setLayer( layer );
|
||||
}
|
||||
|
||||
void QgsProcessingFieldMapWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext & )
|
||||
{
|
||||
if ( mPanel )
|
||||
mPanel->setValue( value );
|
||||
}
|
||||
|
||||
QVariant QgsProcessingFieldMapWidgetWrapper::widgetValue() const
|
||||
{
|
||||
return mPanel ? mPanel->value() : QVariant();
|
||||
}
|
||||
|
||||
QStringList QgsProcessingFieldMapWidgetWrapper::compatibleParameterTypes() const
|
||||
{
|
||||
return QStringList()
|
||||
<< QgsProcessingParameterFieldMapping::typeName();
|
||||
}
|
||||
|
||||
QStringList QgsProcessingFieldMapWidgetWrapper::compatibleOutputTypes() const
|
||||
{
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QString QgsProcessingFieldMapWidgetWrapper::modelerExpressionFormatString() const
|
||||
{
|
||||
return tr( "an array of map items, each containing a 'name', 'type' and 'expression' values (and optional 'length' and 'precision' values)." );
|
||||
}
|
||||
|
||||
const QgsVectorLayer *QgsProcessingFieldMapWidgetWrapper::linkedVectorLayer() const
|
||||
{
|
||||
if ( mPanel && mPanel->layer() )
|
||||
return mPanel->layer();
|
||||
|
||||
return QgsAbstractProcessingParameterWidgetWrapper::linkedVectorLayer();
|
||||
}
|
||||
|
||||
/// @endcond
|
101
src/gui/processing/qgsprocessingfieldmapwidgetwrapper.h
Normal file
101
src/gui/processing/qgsprocessingfieldmapwidgetwrapper.h
Normal file
@ -0,0 +1,101 @@
|
||||
/***************************************************************************
|
||||
qgsprocessingfieldmapwidgetwrapper.h
|
||||
---------------------
|
||||
Date : June 2020
|
||||
Copyright : (C) 2020 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 QGSPROCESSINGFIELDMAPWIDGETWRAPPER_H
|
||||
#define QGSPROCESSINGFIELDMAPWIDGETWRAPPER_H
|
||||
|
||||
#define SIP_NO_FILE
|
||||
|
||||
#include "qgsprocessingwidgetwrapper.h"
|
||||
#include "qgsprocessingmultipleselectiondialog.h"
|
||||
|
||||
#include "ui_qgsprocessingfieldsmappingpanelbase.h"
|
||||
|
||||
class QLineEdit;
|
||||
class QToolButton;
|
||||
|
||||
/// @cond PRIVATE
|
||||
|
||||
|
||||
class GUI_EXPORT QgsProcessingFieldMapPanelWidget : public QgsPanelWidget, private Ui::QgsProcessingFieldMapPanelBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QgsProcessingFieldMapPanelWidget( QWidget *parent = nullptr );
|
||||
|
||||
void setLayer( QgsVectorLayer *layer );
|
||||
QgsVectorLayer *layer();
|
||||
QVariant value() const;
|
||||
void setValue( const QVariant &value );
|
||||
|
||||
signals:
|
||||
|
||||
void changed();
|
||||
|
||||
private slots:
|
||||
void loadFieldsFromLayer();
|
||||
void addField();
|
||||
void loadLayerFields();
|
||||
|
||||
private:
|
||||
QgsFieldMappingModel *mModel = nullptr;
|
||||
|
||||
QgsVectorLayer *mLayer = nullptr;
|
||||
bool mBlockChangedSignal = false;
|
||||
};
|
||||
|
||||
|
||||
class GUI_EXPORT QgsProcessingFieldMapWidgetWrapper : public QgsAbstractProcessingParameterWidgetWrapper, public QgsProcessingParameterWidgetFactoryInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
QgsProcessingFieldMapWidgetWrapper( const QgsProcessingParameterDefinition *parameter = nullptr,
|
||||
QgsProcessingGui::WidgetType type = QgsProcessingGui::Standard, QWidget *parent = nullptr );
|
||||
|
||||
// QgsProcessingParameterWidgetFactoryInterface
|
||||
QString parameterType() const override;
|
||||
QgsAbstractProcessingParameterWidgetWrapper *createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type ) override SIP_FACTORY;
|
||||
|
||||
// QgsProcessingParameterWidgetWrapper interface
|
||||
QWidget *createWidget() override SIP_FACTORY;
|
||||
|
||||
void postInitialize( const QList< QgsAbstractProcessingParameterWidgetWrapper * > &wrappers ) override;
|
||||
public slots:
|
||||
void setParentLayerWrapperValue( const QgsAbstractProcessingParameterWidgetWrapper *parentWrapper );
|
||||
|
||||
protected:
|
||||
|
||||
void setWidgetValue( const QVariant &value, QgsProcessingContext &context ) override;
|
||||
QVariant widgetValue() const override;
|
||||
|
||||
QStringList compatibleParameterTypes() const override;
|
||||
QStringList compatibleOutputTypes() const override;
|
||||
QString modelerExpressionFormatString() const override;
|
||||
const QgsVectorLayer *linkedVectorLayer() const override;
|
||||
private:
|
||||
|
||||
QgsProcessingFieldMapPanelWidget *mPanel = nullptr;
|
||||
std::unique_ptr< QgsVectorLayer > mParentLayer;
|
||||
|
||||
friend class TestProcessingGui;
|
||||
};
|
||||
|
||||
|
||||
/// @endcond
|
||||
|
||||
#endif // QGSPROCESSINGFIELDMAPWIDGETWRAPPER_H
|
@ -19,6 +19,7 @@
|
||||
#include "qgsprocessingalgorithmconfigurationwidget.h"
|
||||
#include "qgsprocessingconfigurationwidgets.h"
|
||||
#include "qgsprocessingvectortilewriterlayerswidgetwrapper.h"
|
||||
#include "qgsprocessingfieldmapwidgetwrapper.h"
|
||||
#include "qgsprocessingwidgetwrapperimpl.h"
|
||||
#include "qgsprocessingparameters.h"
|
||||
#include "qgis.h"
|
||||
@ -66,6 +67,7 @@ QgsProcessingGuiRegistry::QgsProcessingGuiRegistry()
|
||||
addParameterWidgetFactory( new QgsProcessingRasterDestinationWidgetWrapper() );
|
||||
addParameterWidgetFactory( new QgsProcessingFileDestinationWidgetWrapper() );
|
||||
addParameterWidgetFactory( new QgsProcessingFolderDestinationWidgetWrapper() );
|
||||
addParameterWidgetFactory( new QgsProcessingFieldMapWidgetWrapper() );
|
||||
}
|
||||
|
||||
QgsProcessingGuiRegistry::~QgsProcessingGuiRegistry()
|
||||
|
@ -44,6 +44,10 @@ QgsFieldMappingWidget::QgsFieldMappingWidget( QWidget *parent,
|
||||
// Make sure columns are updated when rows are added
|
||||
connect( mModel, &QgsFieldMappingModel::rowsInserted, this, [ = ] { updateColumns(); } );
|
||||
connect( mModel, &QgsFieldMappingModel::modelReset, this, [ = ] { updateColumns(); } );
|
||||
connect( mModel, &QgsFieldMappingModel::dataChanged, this, &QgsFieldMappingWidget::changed );
|
||||
connect( mModel, &QgsFieldMappingModel::rowsInserted, this, &QgsFieldMappingWidget::changed );
|
||||
connect( mModel, &QgsFieldMappingModel::rowsRemoved, this, &QgsFieldMappingWidget::changed );
|
||||
connect( mModel, &QgsFieldMappingModel::modelReset, this, &QgsFieldMappingWidget::changed );
|
||||
}
|
||||
|
||||
void QgsFieldMappingWidget::setDestinationEditable( bool editable )
|
||||
|
@ -96,6 +96,13 @@ class GUI_EXPORT QgsFieldMappingWidget : public QgsPanelWidget, private Ui::QgsF
|
||||
*/
|
||||
void scrollTo( const QModelIndex &index ) const;
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
*Emitted when the fields defined in the widget are changed.
|
||||
*/
|
||||
void changed();
|
||||
|
||||
public slots:
|
||||
|
||||
//! Appends a new \a field to the model, with an optional \a expression
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<class>QgsProcessingFieldMapPanelBase</class>
|
||||
<widget class="QWidget" name="QgsProcessingFieldMapPanelBase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@ -35,7 +35,7 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QgsFieldMappingWidget" name="fieldsView" native="true">
|
||||
<widget class="QgsFieldMappingWidget" name="mFieldsView" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -47,53 +47,73 @@
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="buttonLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="addButton">
|
||||
<widget class="QToolButton" name="mAddButton">
|
||||
<property name="toolTip">
|
||||
<string>Add new field</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>add</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionNewAttribute.svg</normaloff>:/images/themes/default/mActionNewAttribute.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="deleteButton">
|
||||
<widget class="QToolButton" name="mDeleteButton">
|
||||
<property name="toolTip">
|
||||
<string>Delete selected field</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>delete</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionDeleteAttribute.svg</normaloff>:/images/themes/default/mActionDeleteAttribute.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="upButton">
|
||||
<widget class="QToolButton" name="mUpButton">
|
||||
<property name="toolTip">
|
||||
<string>Move selected field up</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>up</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionArrowUp.svg</normaloff>:/images/themes/default/mActionArrowUp.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="downButton">
|
||||
<widget class="QToolButton" name="mDownButton">
|
||||
<property name="toolTip">
|
||||
<string>Move selected field down</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>down</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionArrowDown.svg</normaloff>:/images/themes/default/mActionArrowDown.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="resetButton">
|
||||
<widget class="QToolButton" name="mResetButton">
|
||||
<property name="toolTip">
|
||||
<string>Reset all fields</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>reset</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mIconClearText.svg</normaloff>:/images/themes/default/mIconClearText.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -123,7 +143,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsMapLayerComboBox" name="layerCombo">
|
||||
<widget class="QgsMapLayerComboBox" name="mLayerCombo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -133,7 +153,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="loadLayerFieldsButton">
|
||||
<widget class="QPushButton" name="mLoadLayerFieldsButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -156,16 +176,18 @@
|
||||
<customwidget>
|
||||
<class>QgsMapLayerComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>qgis.gui</header>
|
||||
<header>qgsmaplayercombobox.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsFieldMappingWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qgis.gui</header>
|
||||
<header>qgsfieldmappingwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../../../images/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -83,6 +83,8 @@
|
||||
#include "qgsmodelgraphicsscene.h"
|
||||
#include "qgsmodelgraphicsview.h"
|
||||
#include "qgsmodelcomponentgraphicitem.h"
|
||||
#include "qgsprocessingfieldmapwidgetwrapper.h"
|
||||
#include "qgsprocessingparameterfieldmap.h"
|
||||
|
||||
class TestParamType : public QgsProcessingParameterDefinition
|
||||
{
|
||||
@ -226,6 +228,8 @@ class TestProcessingGui : public QObject
|
||||
void testProviderConnectionWrapper();
|
||||
void testDatabaseSchemaWrapper();
|
||||
void testDatabaseTableWrapper();
|
||||
void testFieldMapWidget();
|
||||
void testFieldMapWrapper();
|
||||
void testOutputDefinitionWidget();
|
||||
void testOutputDefinitionWidgetVectorOut();
|
||||
void testOutputDefinitionWidgetRasterOut();
|
||||
@ -7184,6 +7188,170 @@ void TestProcessingGui::testDatabaseTableWrapper()
|
||||
#endif
|
||||
}
|
||||
|
||||
void TestProcessingGui::testFieldMapWidget()
|
||||
{
|
||||
QgsProcessingFieldMapPanelWidget widget;
|
||||
|
||||
QVariantMap map;
|
||||
map.insert( QStringLiteral( "name" ), QStringLiteral( "n" ) );
|
||||
map.insert( QStringLiteral( "type" ), static_cast< int >( QVariant::Double ) );
|
||||
map.insert( QStringLiteral( "length" ), 8 );
|
||||
map.insert( QStringLiteral( "precision" ), 5 );
|
||||
QVariantMap map2;
|
||||
map2.insert( QStringLiteral( "name" ), QStringLiteral( "n2" ) );
|
||||
map2.insert( QStringLiteral( "type" ), static_cast< int >( QVariant::String ) );
|
||||
map2.insert( QStringLiteral( "expression" ), QStringLiteral( "'abc' || \"def\"" ) );
|
||||
|
||||
QSignalSpy spy( &widget, &QgsProcessingFieldMapPanelWidget::changed );
|
||||
widget.setValue( QVariantList() << map << map2 );
|
||||
QCOMPARE( spy.size(), 1 );
|
||||
|
||||
QCOMPARE( widget.value().toList().size(), 2 );
|
||||
QCOMPARE( widget.value().toList().at( 0 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n" ) );
|
||||
QCOMPARE( widget.value().toList().at( 0 ).toMap().value( QStringLiteral( "type" ) ).toInt(), static_cast< int >( QVariant::Double ) );
|
||||
QCOMPARE( widget.value().toList().at( 0 ).toMap().value( QStringLiteral( "length" ) ).toInt(), 8 );
|
||||
QCOMPARE( widget.value().toList().at( 0 ).toMap().value( QStringLiteral( "precision" ) ).toInt(), 5 );
|
||||
QCOMPARE( widget.value().toList().at( 0 ).toMap().value( QStringLiteral( "expression" ) ).toString(), QString() );
|
||||
QCOMPARE( widget.value().toList().at( 1 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n2" ) );
|
||||
QCOMPARE( widget.value().toList().at( 1 ).toMap().value( QStringLiteral( "type" ) ).toInt(), static_cast< int >( QVariant::String ) );
|
||||
QCOMPARE( widget.value().toList().at( 1 ).toMap().value( QStringLiteral( "expression" ) ).toString(), QStringLiteral( "'abc' || \"def\"" ) );
|
||||
}
|
||||
|
||||
void TestProcessingGui::testFieldMapWrapper()
|
||||
{
|
||||
const QgsProcessingAlgorithm *centroidAlg = QgsApplication::processingRegistry()->algorithmById( QStringLiteral( "native:centroids" ) );
|
||||
const QgsProcessingParameterDefinition *layerDef = centroidAlg->parameterDefinition( QStringLiteral( "INPUT" ) );
|
||||
|
||||
auto testWrapper = [layerDef]( QgsProcessingGui::WidgetType type )
|
||||
{
|
||||
QgsProcessingParameterFieldMapping param( QStringLiteral( "mapping" ), QStringLiteral( "mapping" ) );
|
||||
|
||||
QgsProcessingFieldMapWidgetWrapper wrapper( ¶m, type );
|
||||
|
||||
QgsProcessingContext context;
|
||||
QWidget *w = wrapper.createWrappedWidget( context );
|
||||
|
||||
QVariantMap map;
|
||||
map.insert( QStringLiteral( "name" ), QStringLiteral( "n" ) );
|
||||
map.insert( QStringLiteral( "type" ), static_cast< int >( QVariant::Double ) );
|
||||
map.insert( QStringLiteral( "length" ), 8 );
|
||||
map.insert( QStringLiteral( "precision" ), 5 );
|
||||
QVariantMap map2;
|
||||
map2.insert( QStringLiteral( "name" ), QStringLiteral( "n2" ) );
|
||||
map2.insert( QStringLiteral( "type" ), static_cast< int >( QVariant::String ) );
|
||||
map2.insert( QStringLiteral( "expression" ), QStringLiteral( "'abc' || \"def\"" ) );
|
||||
|
||||
QSignalSpy spy( &wrapper, &QgsProcessingFieldMapWidgetWrapper::widgetValueHasChanged );
|
||||
wrapper.setWidgetValue( QVariantList() << map << map2, context );
|
||||
QCOMPARE( spy.count(), 1 );
|
||||
QCOMPARE( wrapper.widgetValue().toList().at( 0 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n" ) );
|
||||
QCOMPARE( wrapper.widgetValue().toList().at( 0 ).toMap().value( QStringLiteral( "type" ) ).toInt(), static_cast< int >( QVariant::Double ) );
|
||||
QCOMPARE( wrapper.widgetValue().toList().at( 0 ).toMap().value( QStringLiteral( "length" ) ).toInt(), 8 );
|
||||
QCOMPARE( wrapper.widgetValue().toList().at( 0 ).toMap().value( QStringLiteral( "precision" ) ).toInt(), 5 );
|
||||
QCOMPARE( wrapper.widgetValue().toList().at( 0 ).toMap().value( QStringLiteral( "expression" ) ).toString(), QString() );
|
||||
QCOMPARE( wrapper.widgetValue().toList().at( 1 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n2" ) );
|
||||
QCOMPARE( wrapper.widgetValue().toList().at( 1 ).toMap().value( QStringLiteral( "type" ) ).toInt(), static_cast< int >( QVariant::String ) );
|
||||
QCOMPARE( wrapper.widgetValue().toList().at( 1 ).toMap().value( QStringLiteral( "expression" ) ).toString(), QStringLiteral( "'abc' || \"def\"" ) );
|
||||
|
||||
QCOMPARE( static_cast< QgsProcessingFieldMapPanelWidget * >( wrapper.wrappedWidget() )->value().toList().count(), 2 );
|
||||
QCOMPARE( static_cast< QgsProcessingFieldMapPanelWidget * >( wrapper.wrappedWidget() )->value().toList().at( 0 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n" ) );
|
||||
QCOMPARE( static_cast< QgsProcessingFieldMapPanelWidget * >( wrapper.wrappedWidget() )->value().toList().at( 1 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n2" ) );
|
||||
wrapper.setWidgetValue( QVariantList() << map, context );
|
||||
QCOMPARE( spy.count(), 2 );
|
||||
QCOMPARE( wrapper.widgetValue().toList().size(), 1 );
|
||||
QCOMPARE( static_cast< QgsProcessingFieldMapPanelWidget * >( wrapper.wrappedWidget() )->value().toList().size(), 1 );
|
||||
|
||||
QLabel *l = wrapper.createWrappedLabel();
|
||||
if ( wrapper.type() != QgsProcessingGui::Batch )
|
||||
{
|
||||
QVERIFY( l );
|
||||
QCOMPARE( l->text(), QStringLiteral( "mapping" ) );
|
||||
QCOMPARE( l->toolTip(), param.toolTip() );
|
||||
delete l;
|
||||
}
|
||||
else
|
||||
{
|
||||
QVERIFY( !l );
|
||||
}
|
||||
|
||||
// check signal
|
||||
static_cast< QgsProcessingFieldMapPanelWidget * >( wrapper.wrappedWidget() )->setValue( QVariantList() << map << map2 );
|
||||
QCOMPARE( spy.count(), 3 );
|
||||
|
||||
delete w;
|
||||
|
||||
// with layer
|
||||
param.setParentLayerParameterName( QStringLiteral( "other" ) );
|
||||
QgsProcessingFieldMapWidgetWrapper wrapper2( ¶m, type );
|
||||
w = wrapper2.createWrappedWidget( context );
|
||||
|
||||
QSignalSpy spy2( &wrapper2, &QgsProcessingFieldMapWidgetWrapper::widgetValueHasChanged );
|
||||
wrapper2.setWidgetValue( QVariantList() << map, context );
|
||||
QCOMPARE( spy2.count(), 1 );
|
||||
QCOMPARE( wrapper2.widgetValue().toList().size(), 1 );
|
||||
QCOMPARE( wrapper2.widgetValue().toList().at( 0 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n" ) );
|
||||
QCOMPARE( static_cast< QgsProcessingFieldMapPanelWidget * >( wrapper2.wrappedWidget() )->value().toList().at( 0 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n" ) );
|
||||
|
||||
wrapper2.setWidgetValue( QVariantList() << map2, context );
|
||||
QCOMPARE( spy2.count(), 2 );
|
||||
QCOMPARE( wrapper2.widgetValue().toList().size(), 1 );
|
||||
QCOMPARE( wrapper2.widgetValue().toList().at( 0 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n2" ) );
|
||||
QCOMPARE( static_cast< QgsProcessingFieldMapPanelWidget * >( wrapper2.wrappedWidget() )->value().toList().at( 0 ).toMap().value( QStringLiteral( "name" ) ).toString(), QStringLiteral( "n2" ) );
|
||||
|
||||
static_cast< QgsProcessingFieldMapPanelWidget * >( wrapper2.wrappedWidget() )->setValue( QVariantList() << map );
|
||||
QCOMPARE( spy2.count(), 3 );
|
||||
|
||||
TestLayerWrapper layerWrapper( layerDef );
|
||||
QgsProject p;
|
||||
QgsVectorLayer *vl = new QgsVectorLayer( QStringLiteral( "LineString" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
|
||||
p.addMapLayer( vl );
|
||||
|
||||
QVERIFY( !wrapper2.mPanel->layer() );
|
||||
layerWrapper.setWidgetValue( QVariant::fromValue( vl ), context );
|
||||
wrapper2.setParentLayerWrapperValue( &layerWrapper );
|
||||
QCOMPARE( wrapper2.mPanel->layer(), vl );
|
||||
|
||||
// should not be owned by wrapper
|
||||
QVERIFY( !wrapper2.mParentLayer.get() );
|
||||
layerWrapper.setWidgetValue( QVariant(), context );
|
||||
wrapper2.setParentLayerWrapperValue( &layerWrapper );
|
||||
QVERIFY( !wrapper2.mPanel->layer() );
|
||||
|
||||
layerWrapper.setWidgetValue( vl->id(), context );
|
||||
wrapper2.setParentLayerWrapperValue( &layerWrapper );
|
||||
QVERIFY( !wrapper2.mPanel->layer() );
|
||||
QVERIFY( !wrapper2.mParentLayer.get() );
|
||||
|
||||
// with project layer
|
||||
context.setProject( &p );
|
||||
TestProcessingContextGenerator generator( context );
|
||||
wrapper2.registerProcessingContextGenerator( &generator );
|
||||
|
||||
layerWrapper.setWidgetValue( vl->id(), context );
|
||||
wrapper2.setParentLayerWrapperValue( &layerWrapper );
|
||||
QCOMPARE( wrapper2.mPanel->layer(), vl );
|
||||
QVERIFY( !wrapper2.mParentLayer.get() );
|
||||
|
||||
// non-project layer
|
||||
QString pointFileName = TEST_DATA_DIR + QStringLiteral( "/points.shp" );
|
||||
layerWrapper.setWidgetValue( pointFileName, context );
|
||||
wrapper2.setParentLayerWrapperValue( &layerWrapper );
|
||||
QCOMPARE( wrapper2.mPanel->layer()->publicSource(), pointFileName );
|
||||
// must be owned by wrapper, or layer may be deleted while still required by wrapper
|
||||
QCOMPARE( wrapper2.mParentLayer->publicSource(), pointFileName );
|
||||
|
||||
};
|
||||
|
||||
// standard wrapper
|
||||
testWrapper( QgsProcessingGui::Standard );
|
||||
|
||||
// batch wrapper
|
||||
testWrapper( QgsProcessingGui::Batch );
|
||||
|
||||
// modeler wrapper
|
||||
testWrapper( QgsProcessingGui::Modeler );
|
||||
}
|
||||
|
||||
void TestProcessingGui::testOutputDefinitionWidget()
|
||||
{
|
||||
QgsProcessingParameterFeatureSink sink( QStringLiteral( "test" ) );
|
||||
|
Loading…
x
Reference in New Issue
Block a user