38#include <QDragEnterEvent>
47#include "moc_qgsprocessingmaplayercombobox.cpp"
49using namespace Qt::StringLiterals;
55 , mParameter( parameter->clone() )
57 QHBoxLayout *layout =
new QHBoxLayout();
58 layout->setContentsMargins( 0, 0, 0, 0 );
59 layout->setSpacing( 6 );
62 layout->addWidget( mCombo );
63 layout->setAlignment( mCombo, Qt::AlignTop );
68 mIterateButton =
new QToolButton();
70 mIterateButton->setToolTip( tr(
"Iterate over this layer, creating a separate output for every feature in the layer" ) );
71 mIterateButton->setCheckable(
true );
72 mIterateButton->setAutoRaise(
true );
75 mIterateButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
76 mIterateButton->setIconSize( QSize( iconSize, iconSize ) );
78 layout->addWidget( mIterateButton );
79 layout->setAlignment( mIterateButton, Qt::AlignTop );
84 mSettingsButton =
new QToolButton();
86 mSettingsButton->setToolTip( tr(
"Advanced options" ) );
89 mSettingsButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
90 mSettingsButton->setIconSize( QSize( iconSize, iconSize ) );
91 mSettingsButton->setAutoRaise(
true );
93 connect( mSettingsButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::showSourceOptions );
94 layout->addWidget( mSettingsButton );
95 layout->setAlignment( mSettingsButton, Qt::AlignTop );
99 mSettingsButton =
new QToolButton();
101 mSettingsButton->setToolTip( tr(
"Advanced options" ) );
102 mSettingsButton->setEnabled(
false );
105 mSettingsButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
106 mSettingsButton->setIconSize( QSize( iconSize, iconSize ) );
107 mSettingsButton->setAutoRaise(
true );
109 connect( mSettingsButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::showRasterSourceOptions );
110 layout->addWidget( mSettingsButton );
111 layout->setAlignment( mSettingsButton, Qt::AlignTop );
114 mSelectButton =
new QToolButton();
115 mSelectButton->setText( QString( QChar( 0x2026 ) ) );
116 mSelectButton->setToolTip( tr(
"Select input" ) );
117 layout->addWidget( mSelectButton );
118 layout->setAlignment( mSelectButton, Qt::AlignTop );
121 mFeatureSourceMenu =
new QMenu(
this );
122 QAction *selectFromFileAction =
new QAction( tr(
"Select File…" ), mFeatureSourceMenu );
123 connect( selectFromFileAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
124 mFeatureSourceMenu->addAction( selectFromFileAction );
125 QAction *browseForLayerAction =
new QAction( tr(
"Browse for Layer…" ), mFeatureSourceMenu );
126 connect( browseForLayerAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::browseForLayer );
127 mFeatureSourceMenu->addAction( browseForLayerAction );
128 mSelectButton->setMenu( mFeatureSourceMenu );
129 mSelectButton->setPopupMode( QToolButton::InstantPopup );
133 connect( mSelectButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
136 QVBoxLayout *vl =
new QVBoxLayout();
137 vl->setContentsMargins( 0, 0, 0, 0 );
139 vl->addLayout( layout );
145 mUseSelectionCheckBox =
new QCheckBox( tr(
"Selected features only" ) );
146 mUseSelectionCheckBox->setChecked(
false );
147 mUseSelectionCheckBox->setEnabled(
false );
148 vl->addWidget( mUseSelectionCheckBox );
151 bool mayBeRaster {
false };
155 QList<int> dataTypes;
187 QList<int> dataTypes;
220 if ( settings.
value( u
"Processing/Configuration/SHOW_CRS_DEF"_s,
true ).toBool() )
221 mCombo->setShowCrs(
true );
224 mCombo->setFilters( filters );
230 mCombo->setExcludedProviders( mCombo->excludedProviders() << u
"virtualraster"_s );
235 mCombo->setAllowEmptyLayer(
true );
236 mCombo->setLayer(
nullptr );
240 if ( mUseSelectionCheckBox )
241 connect( mUseSelectionCheckBox, &QCheckBox::toggled,
this, [
this] {
242 if ( !mBlockChangedSignal )
248 setAcceptDrops(
true );
250 onLayerChanged( mCombo->currentLayer() );
253QgsProcessingMapLayerComboBox::~QgsProcessingMapLayerComboBox() =
default;
255void QgsProcessingMapLayerComboBox::setLayer(
QgsMapLayer *layer )
259 mCombo->setLayer( layer );
263QgsMapLayer *QgsProcessingMapLayerComboBox::currentLayer()
265 return mCombo->currentLayer();
268QString QgsProcessingMapLayerComboBox::currentText()
270 return mCombo->currentText();
273void QgsProcessingMapLayerComboBox::setValue(
const QVariant &value,
QgsProcessingContext &context )
281 QVariant val = value;
283 bool selectedOnly =
false;
284 bool iterate =
false;
285 if ( val.userType() == qMetaTypeId<QgsProcessingFeatureSourceDefinition>() )
299 mFilterExpression.clear();
300 mIsOverridingDefaultGeometryCheck =
false;
304 if ( val.userType() == qMetaTypeId<QgsProcessingRasterLayerDefinition>() )
309 mRasterDpi = fromVar.
dpi;
313 mRasterReferenceScale = 0;
317 if ( val.userType() == qMetaTypeId<QgsProperty>() )
329 QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( val.value<QObject *>() );
330 if ( !layer && val.userType() == QMetaType::Type::QString )
337 mBlockChangedSignal++;
340 found =
static_cast<bool>( currentLayer() );
341 bool changed = found && ( currentLayer() != prevLayer );
342 if ( found && mUseSelectionCheckBox )
344 const bool hasSelection = qobject_cast<QgsVectorLayer *>( layer ) && qobject_cast<QgsVectorLayer *>( layer )->selectedFeatureCount() > 0;
345 changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
348 mUseSelectionCheckBox->setEnabled(
true );
349 mUseSelectionCheckBox->setChecked( selectedOnly );
353 mUseSelectionCheckBox->setChecked(
false );
354 mUseSelectionCheckBox->setEnabled(
false );
357 if ( mIterateButton )
359 mIterateButton->setChecked( iterate );
362 mBlockChangedSignal--;
369 const QString
string = val.toString();
370 if ( mIterateButton )
371 mIterateButton->setChecked( iterate );
373 if ( !
string.isEmpty() )
375 mBlockChangedSignal++;
376 if ( mCombo->findText(
string ) < 0 )
378 QStringList additional = mCombo->additionalItems();
379 additional.append(
string );
380 mCombo->setAdditionalItems( additional );
382 mCombo->setCurrentIndex( mCombo->findText(
string ) );
383 if ( mUseSelectionCheckBox )
385 mUseSelectionCheckBox->setChecked(
false );
386 mUseSelectionCheckBox->setEnabled(
false );
388 mBlockChangedSignal--;
389 if ( !mBlockChangedSignal )
394 mCombo->setLayer(
nullptr );
395 if ( mUseSelectionCheckBox )
397 mUseSelectionCheckBox->setChecked(
false );
398 mUseSelectionCheckBox->setEnabled(
false );
404QVariant QgsProcessingMapLayerComboBox::value()
const
406 if ( isEditable() && mCombo->currentText() != mCombo->itemText( mCombo->currentIndex() ) )
407 return mCombo->currentText();
409 const bool iterate = mIterateButton && mIterateButton->isChecked();
410 const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
413 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
423 else if ( mRasterReferenceScale != 0 )
430 if ( !mCombo->currentText().isEmpty() )
432 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
434 mCombo->currentText(),
442 else if ( mRasterReferenceScale != 0 )
445 return mCombo->currentText();
454 mCombo->setProject( context.
project() );
457void QgsProcessingMapLayerComboBox::setEditable(
bool editable )
459 mCombo->setEditable( editable );
462bool QgsProcessingMapLayerComboBox::isEditable()
const
464 return mCombo->isEditable();
467QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData(
const QMimeData *data,
bool &incompatibleLayerSelected )
const
469 incompatibleLayerSelected =
false;
476 if ( mCombo->mProxyModel->acceptsLayer( layer ) )
480 incompatibleLayerSelected =
true;
489QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData(
const QMimeData *data )
const
500 bool acceptable =
false;
508 if ( dataTypes.isEmpty()
516 if ( dataTypes.isEmpty()
524 if ( dataTypes.isEmpty()
551 if ( u.layerType ==
"vector"_L1 && u.providerKey ==
"ogr"_L1 )
583 if ( !uriList.isEmpty() )
587 QStringList rawPaths;
588 if ( data->hasUrls() )
590 const QList<QUrl> urls = data->urls();
591 rawPaths.reserve( urls.count() );
592 for (
const QUrl &url : urls )
594 const QString local = url.toLocalFile();
595 if ( !rawPaths.contains( local ) )
596 rawPaths.append( local );
599 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
600 rawPaths.append( data->text() );
602 for (
const QString &path : std::as_const( rawPaths ) )
604 QFileInfo file( path );
615void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
617 if ( !( event->possibleActions() & Qt::CopyAction ) )
620 bool incompatibleLayerSelected =
false;
621 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
622 const QString uri = compatibleUriFromMimeData( event->mimeData() );
623 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
626 event->setDropAction( Qt::CopyAction );
629 mCombo->mHighlight =
true;
634void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
636 QWidget::dragLeaveEvent( event );
641 mCombo->mHighlight =
false;
646void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
648 if ( !( event->possibleActions() & Qt::CopyAction ) )
651 bool incompatibleLayerSelected =
false;
652 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
653 const QString uri = compatibleUriFromMimeData( event->mimeData() );
654 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
657 setFocus( Qt::MouseFocusReason );
658 event->setDropAction( Qt::CopyAction );
661 setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
664 mCombo->mHighlight =
false;
668void QgsProcessingMapLayerComboBox::onLayerChanged(
QgsMapLayer *layer )
672 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
674 if (
QgsVectorLayer *prevLayer = qobject_cast<QgsVectorLayer *>( mPrevLayer ) )
678 if ( vl->selectedFeatureCount() == 0 )
679 mUseSelectionCheckBox->setChecked(
false );
680 mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
695 if ( !mBlockChangedSignal )
701 if ( selected.isEmpty() )
702 mUseSelectionCheckBox->setChecked(
false );
703 mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
706void QgsProcessingMapLayerComboBox::showSourceOptions()
710 QgsProcessingFeatureSourceOptionsWidget *widget =
new QgsProcessingFeatureSourceOptionsWidget();
711 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
712 widget->setLayer( qobject_cast<QgsVectorLayer *>( mCombo->currentLayer() ) );
714 widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
715 widget->setFeatureLimit( mFeatureLimit );
716 widget->setFilterExpression( mFilterExpression );
718 panel->openPanel( widget );
721 bool changed =
false;
722 changed = changed | ( widget->featureLimit() != mFeatureLimit );
723 changed = changed | ( widget->filterExpression() != mFilterExpression );
724 changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
725 changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
727 mFeatureLimit = widget->featureLimit();
728 mFilterExpression = widget->filterExpression();
729 mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
730 mGeometryCheck = widget->geometryCheckMethod();
738void QgsProcessingMapLayerComboBox::showRasterSourceOptions()
742 QgsProcessingRasterSourceOptionsWidget *widget =
new QgsProcessingRasterSourceOptionsWidget();
743 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
744 widget->setReferenceScale( mRasterReferenceScale );
745 widget->setDpi( mRasterDpi );
750 panel->openPanel( widget );
753 bool changed =
false;
754 changed = changed | ( widget->referenceScale() != mRasterReferenceScale );
755 changed = changed | ( widget->dpi() != mRasterDpi );
757 mRasterReferenceScale = widget->referenceScale();
758 mRasterDpi = widget->dpi();
766void QgsProcessingMapLayerComboBox::selectFromFile()
769 const QString initialValue = currentText();
772 if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
774 else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() !=
'.' )
775 path = QFileInfo( initialValue ).path();
776 else if ( settings.
contains( u
"/Processing/LastInputPath"_s ) )
777 path = settings.
value( u
"/Processing/LastInputPath"_s ).toString();
781 filter = generator->createFileFilter();
783 filter = QObject::tr(
"All files (*.*)" );
785 const QString filename = QFileDialog::getOpenFileName(
this, tr(
"Select File" ), path, filter );
786 if ( filename.isEmpty() )
789 settings.
setValue( u
"/Processing/LastInputPath"_s, QFileInfo( filename ).path() );
791 setValue( filename, context );
794void QgsProcessingMapLayerComboBox::browseForLayer()
799 widget->
setPanelTitle( tr(
"Browse for \"%1\"" ).arg( mParameter->description() ) );
801 panel->openPanel( widget );
806 if ( widget->
uri().
uri.isEmpty() )
807 setValue( QVariant(), context );
809 setValue( widget->
uri().
uri, context );
@ TiledScene
Tiled scene layers.
@ Annotation
Annotation layers.
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
@ VectorTile
Vector tile layers.
@ MapLayer
Any map layer type (raster, vector, mesh, point cloud, annotation or plugin layer).
@ VectorAnyGeometry
Any vector layer with geometry.
@ VectorPoint
Vector point layers.
@ VectorPolygon
Vector polygon layers.
@ VectorLine
Vector line layers.
@ PointCloud
Point cloud layers.
@ WmsDpi
The parameter supports a server resolution for WMS source layers.
@ WmsScale
The parameter supports a reference scale for WMS source layers.
ProcessingMode
Types of modes which Processing widgets can be created for.
@ Standard
Standard (single-run) algorithm mode.
@ CompatibleWithVirtualRaster
The processing provider's algorithms can work with QGIS virtualraster data provider.
@ PointCloudLayer
QgsPointCloudLayer.
@ VectorTileLayer
QgsVectorTileLayer.
@ AnnotationLayer
QgsAnnotationLayer.
@ TiledSceneLayer
QgsTiledSceneLayer.
@ AbortOnInvalid
Close iterator on encountering any features with invalid geometry. This requires a slow geometry vali...
QFlags< ProcessingFeatureSourceDefinitionFlag > ProcessingFeatureSourceDefinitionFlags
Flags which control behavior for a Processing feature source.
@ CreateIndividualOutputPerInputFeature
If set, every feature processed from this source will be placed into its own individually created out...
@ OverrideDefaultGeometryCheck
If set, the default geometry check method (as dictated by QgsProcessingContext) will be overridden fo...
@ Optional
Parameter is optional.
QFlags< LayerFilter > LayerFilters
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Abstract interface for classes which generate a file filter string.
A combobox which displays a dynamic list of layers from a QGIS project.
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
Base class for all map layer types.
QList< QgsMimeDataUtils::Uri > UriList
static UriList decodeUriList(const QMimeData *data)
Contains information about the context in which a processing algorithm is executed.
QgsExpressionContext & expressionContext()
Returns the expression context.
Encapsulates settings relating to a feature source input to a processing algorithm.
bool selectedFeaturesOnly
true if only selected features in the source should be used by algorithms.
QgsProperty source
Source definition.
Qgis::InvalidGeometryCheck geometryCheck
Geometry check method to apply to this source.
Qgis::ProcessingFeatureSourceDefinitionFlags flags
Flags which dictate source behavior.
long long featureLimit
If set to a value > 0, places a limit on the maximum number of features which will be read from the s...
QString filterExpression
Optional expression filter to use for filtering features which will be read from the source.
Base class for the definition of processing parameters.
An input feature source (such as vector layers) parameter for processing algorithms.
static QString typeName()
Returns the type name for the parameter class.
QList< int > dataTypes() const
Returns the geometry types for sources acceptable by the parameter.
A map layer parameter for processing algorithms.
static QString typeName()
Returns the type name for the parameter class.
static QString typeName()
Returns the type name for the parameter class.
static QString typeName()
Returns the type name for the parameter class.
A raster layer parameter for processing algorithms.
Qgis::RasterProcessingParameterCapabilities parameterCapabilities() const
Returns flags containing the supported capabilities of the raster layer parameter.
static QString typeName()
Returns the type name for the parameter class.
A vector layer (with or without geometry) parameter for processing algorithms.
static QString typeName()
Returns the type name for the parameter class.
Contains settings which reflect the context in which a Processing parameter widget is shown.
QgsProject * project() const
Returns the project associated with the widget.
QgsBrowserGuiModel * browserModel() const
Returns the browser model associated with the widget.
Encapsulates settings relating to a raster layer input to a processing algorithm.
double referenceScale
If set to a value > 0, sets a scale at which a raster (e.g., a WMS) should be requested or rendered.
int dpi
Indicates the resolution of the raster source (e.g., a WMS server).
QgsProperty source
Source definition.
static QString encodeProviderKeyAndUri(const QString &providerKey, const QString &uri)
Encodes a provider key and layer uri to a single string, for use with decodeProviderKeyAndUri().
static QgsMapLayer * mapLayerFromString(const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers=true, QgsProcessingUtils::LayerHint typeHint=QgsProcessingUtils::LayerHint::UnknownType, QgsProcessing::LayerOptionsFlags flags=QgsProcessing::LayerOptionsFlags())
Interprets a string as a map layer within the supplied context.
static QgsProject * instance()
Returns the QgsProject singleton instance.
A store for object properties.
Qgis::PropertyType propertyType() const
Returns the property type.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Represents a vector layer which manages a vector based dataset.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static bool isWmsLayer(QgsMapLayer *layer)
Returns whether a map layer is an OGC WMS layer or not.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
QSet< QgsFeatureId > QgsFeatureIds
QString uri
Identifier of the data source recognized by its providerKey.
QString providerKey
For "vector" / "raster" type: provider id.