37#include <QDragEnterEvent>
46#include "moc_qgsprocessingmaplayercombobox.cpp"
48using namespace Qt::StringLiterals;
54 , mParameter( parameter->clone() )
56 QHBoxLayout *layout =
new QHBoxLayout();
57 layout->setContentsMargins( 0, 0, 0, 0 );
58 layout->setSpacing( 6 );
61 layout->addWidget( mCombo );
62 layout->setAlignment( mCombo, Qt::AlignTop );
67 mIterateButton =
new QToolButton();
69 mIterateButton->setToolTip( tr(
"Iterate over this layer, creating a separate output for every feature in the layer" ) );
70 mIterateButton->setCheckable(
true );
71 mIterateButton->setAutoRaise(
true );
74 mIterateButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
75 mIterateButton->setIconSize( QSize( iconSize, iconSize ) );
77 layout->addWidget( mIterateButton );
78 layout->setAlignment( mIterateButton, Qt::AlignTop );
83 mSettingsButton =
new QToolButton();
85 mSettingsButton->setToolTip( tr(
"Advanced options" ) );
88 mSettingsButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
89 mSettingsButton->setIconSize( QSize( iconSize, iconSize ) );
90 mSettingsButton->setAutoRaise(
true );
92 connect( mSettingsButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::showSourceOptions );
93 layout->addWidget( mSettingsButton );
94 layout->setAlignment( mSettingsButton, Qt::AlignTop );
98 mSettingsButton =
new QToolButton();
100 mSettingsButton->setToolTip( tr(
"Advanced options" ) );
101 mSettingsButton->setEnabled(
false );
104 mSettingsButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
105 mSettingsButton->setIconSize( QSize( iconSize, iconSize ) );
106 mSettingsButton->setAutoRaise(
true );
108 connect( mSettingsButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::showRasterSourceOptions );
109 layout->addWidget( mSettingsButton );
110 layout->setAlignment( mSettingsButton, Qt::AlignTop );
113 mSelectButton =
new QToolButton();
114 mSelectButton->setText( QString( QChar( 0x2026 ) ) );
115 mSelectButton->setToolTip( tr(
"Select input" ) );
116 layout->addWidget( mSelectButton );
117 layout->setAlignment( mSelectButton, Qt::AlignTop );
120 mFeatureSourceMenu =
new QMenu(
this );
121 QAction *selectFromFileAction =
new QAction( tr(
"Select File…" ), mFeatureSourceMenu );
122 connect( selectFromFileAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
123 mFeatureSourceMenu->addAction( selectFromFileAction );
124 QAction *browseForLayerAction =
new QAction( tr(
"Browse for Layer…" ), mFeatureSourceMenu );
125 connect( browseForLayerAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::browseForLayer );
126 mFeatureSourceMenu->addAction( browseForLayerAction );
127 mSelectButton->setMenu( mFeatureSourceMenu );
128 mSelectButton->setPopupMode( QToolButton::InstantPopup );
132 connect( mSelectButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
135 QVBoxLayout *vl =
new QVBoxLayout();
136 vl->setContentsMargins( 0, 0, 0, 0 );
138 vl->addLayout( layout );
144 mUseSelectionCheckBox =
new QCheckBox( tr(
"Selected features only" ) );
145 mUseSelectionCheckBox->setChecked(
false );
146 mUseSelectionCheckBox->setEnabled(
false );
147 vl->addWidget( mUseSelectionCheckBox );
150 bool mayBeRaster {
false };
154 QList<int> dataTypes;
186 QList<int> dataTypes;
219 if ( settings.
value( u
"Processing/Configuration/SHOW_CRS_DEF"_s,
true ).toBool() )
220 mCombo->setShowCrs(
true );
223 mCombo->setFilters( filters );
229 mCombo->setExcludedProviders( mCombo->excludedProviders() << u
"virtualraster"_s );
234 mCombo->setAllowEmptyLayer(
true );
235 mCombo->setLayer(
nullptr );
239 if ( mUseSelectionCheckBox )
240 connect( mUseSelectionCheckBox, &QCheckBox::toggled,
this, [
this] {
241 if ( !mBlockChangedSignal )
247 setAcceptDrops(
true );
249 onLayerChanged( mCombo->currentLayer() );
252QgsProcessingMapLayerComboBox::~QgsProcessingMapLayerComboBox() =
default;
254void QgsProcessingMapLayerComboBox::setLayer(
QgsMapLayer *layer )
258 mCombo->setLayer( layer );
262QgsMapLayer *QgsProcessingMapLayerComboBox::currentLayer()
264 return mCombo->currentLayer();
267QString QgsProcessingMapLayerComboBox::currentText()
269 return mCombo->currentText();
272void QgsProcessingMapLayerComboBox::setValue(
const QVariant &value,
QgsProcessingContext &context )
280 QVariant val = value;
282 bool selectedOnly =
false;
283 bool iterate =
false;
284 if ( val.userType() == qMetaTypeId<QgsProcessingFeatureSourceDefinition>() )
298 mFilterExpression.clear();
299 mIsOverridingDefaultGeometryCheck =
false;
303 if ( val.userType() == qMetaTypeId<QgsProcessingRasterLayerDefinition>() )
308 mRasterDpi = fromVar.
dpi;
312 mRasterReferenceScale = 0;
316 if ( val.userType() == qMetaTypeId<QgsProperty>() )
328 QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( val.value<QObject *>() );
329 if ( !layer && val.userType() == QMetaType::Type::QString )
336 mBlockChangedSignal++;
339 found =
static_cast<bool>( currentLayer() );
340 bool changed = found && ( currentLayer() != prevLayer );
341 if ( found && mUseSelectionCheckBox )
343 const bool hasSelection = qobject_cast<QgsVectorLayer *>( layer ) && qobject_cast<QgsVectorLayer *>( layer )->selectedFeatureCount() > 0;
344 changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
347 mUseSelectionCheckBox->setEnabled(
true );
348 mUseSelectionCheckBox->setChecked( selectedOnly );
352 mUseSelectionCheckBox->setChecked(
false );
353 mUseSelectionCheckBox->setEnabled(
false );
356 if ( mIterateButton )
358 mIterateButton->setChecked( iterate );
361 mBlockChangedSignal--;
368 const QString
string = val.toString();
369 if ( mIterateButton )
370 mIterateButton->setChecked( iterate );
372 if ( !
string.isEmpty() )
374 mBlockChangedSignal++;
375 if ( mCombo->findText(
string ) < 0 )
377 QStringList additional = mCombo->additionalItems();
378 additional.append(
string );
379 mCombo->setAdditionalItems( additional );
381 mCombo->setCurrentIndex( mCombo->findText(
string ) );
382 if ( mUseSelectionCheckBox )
384 mUseSelectionCheckBox->setChecked(
false );
385 mUseSelectionCheckBox->setEnabled(
false );
387 mBlockChangedSignal--;
388 if ( !mBlockChangedSignal )
393 mCombo->setLayer(
nullptr );
394 if ( mUseSelectionCheckBox )
396 mUseSelectionCheckBox->setChecked(
false );
397 mUseSelectionCheckBox->setEnabled(
false );
403QVariant QgsProcessingMapLayerComboBox::value()
const
405 if ( isEditable() && mCombo->currentText() != mCombo->itemText( mCombo->currentIndex() ) )
406 return mCombo->currentText();
408 const bool iterate = mIterateButton && mIterateButton->isChecked();
409 const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
412 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
414 else if ( mRasterReferenceScale != 0 )
421 if ( !mCombo->currentText().isEmpty() )
423 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
425 else if ( mRasterReferenceScale != 0 )
428 return mCombo->currentText();
437 mCombo->setProject( context.
project() );
440void QgsProcessingMapLayerComboBox::setEditable(
bool editable )
442 mCombo->setEditable( editable );
445bool QgsProcessingMapLayerComboBox::isEditable()
const
447 return mCombo->isEditable();
450QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData(
const QMimeData *data,
bool &incompatibleLayerSelected )
const
452 incompatibleLayerSelected =
false;
459 if ( mCombo->mProxyModel->acceptsLayer( layer ) )
463 incompatibleLayerSelected =
true;
472QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData(
const QMimeData *data )
const
479 && u.layerType ==
"vector"_L1 )
484 bool acceptable =
false;
515 && u.layerType ==
"raster"_L1 && u.providerKey ==
"gdal"_L1 )
518 && u.layerType ==
"mesh"_L1 && u.providerKey ==
"mdal"_L1 )
528 if ( u.layerType ==
"vector"_L1 && u.providerKey ==
"ogr"_L1 )
554 else if ( u.layerType ==
"raster"_L1 && u.providerKey ==
"gdal"_L1
557 else if ( u.layerType ==
"mesh"_L1 && u.providerKey ==
"mdal"_L1
562 if ( !uriList.isEmpty() )
566 QStringList rawPaths;
567 if ( data->hasUrls() )
569 const QList<QUrl> urls = data->urls();
570 rawPaths.reserve( urls.count() );
571 for (
const QUrl &url : urls )
573 const QString local = url.toLocalFile();
574 if ( !rawPaths.contains( local ) )
575 rawPaths.append( local );
578 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
579 rawPaths.append( data->text() );
581 for (
const QString &path : std::as_const( rawPaths ) )
583 QFileInfo file( path );
594void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
596 if ( !( event->possibleActions() & Qt::CopyAction ) )
599 bool incompatibleLayerSelected =
false;
600 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
601 const QString uri = compatibleUriFromMimeData( event->mimeData() );
602 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
605 event->setDropAction( Qt::CopyAction );
608 mCombo->mHighlight =
true;
613void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
615 QWidget::dragLeaveEvent( event );
620 mCombo->mHighlight =
false;
625void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
627 if ( !( event->possibleActions() & Qt::CopyAction ) )
630 bool incompatibleLayerSelected =
false;
631 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
632 const QString uri = compatibleUriFromMimeData( event->mimeData() );
633 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
636 setFocus( Qt::MouseFocusReason );
637 event->setDropAction( Qt::CopyAction );
640 setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
643 mCombo->mHighlight =
false;
647void QgsProcessingMapLayerComboBox::onLayerChanged(
QgsMapLayer *layer )
651 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
653 if (
QgsVectorLayer *prevLayer = qobject_cast<QgsVectorLayer *>( mPrevLayer ) )
657 if ( vl->selectedFeatureCount() == 0 )
658 mUseSelectionCheckBox->setChecked(
false );
659 mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
673 if ( !mBlockChangedSignal )
679 if ( selected.isEmpty() )
680 mUseSelectionCheckBox->setChecked(
false );
681 mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
684void QgsProcessingMapLayerComboBox::showSourceOptions()
688 QgsProcessingFeatureSourceOptionsWidget *widget =
new QgsProcessingFeatureSourceOptionsWidget();
689 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
690 widget->setLayer( qobject_cast<QgsVectorLayer *>( mCombo->currentLayer() ) );
692 widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
693 widget->setFeatureLimit( mFeatureLimit );
694 widget->setFilterExpression( mFilterExpression );
696 panel->openPanel( widget );
699 bool changed =
false;
700 changed = changed | ( widget->featureLimit() != mFeatureLimit );
701 changed = changed | ( widget->filterExpression() != mFilterExpression );
702 changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
703 changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
705 mFeatureLimit = widget->featureLimit();
706 mFilterExpression = widget->filterExpression();
707 mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
708 mGeometryCheck = widget->geometryCheckMethod();
716void QgsProcessingMapLayerComboBox::showRasterSourceOptions()
720 QgsProcessingRasterSourceOptionsWidget *widget =
new QgsProcessingRasterSourceOptionsWidget();
721 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
722 widget->setReferenceScale( mRasterReferenceScale );
723 widget->setDpi( mRasterDpi );
728 panel->openPanel( widget );
731 bool changed =
false;
732 changed = changed | ( widget->referenceScale() != mRasterReferenceScale );
733 changed = changed | ( widget->dpi() != mRasterDpi );
735 mRasterReferenceScale = widget->referenceScale();
736 mRasterDpi = widget->dpi();
744void QgsProcessingMapLayerComboBox::selectFromFile()
747 const QString initialValue = currentText();
750 if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
752 else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() !=
'.' )
753 path = QFileInfo( initialValue ).path();
754 else if ( settings.
contains( u
"/Processing/LastInputPath"_s ) )
755 path = settings.
value( u
"/Processing/LastInputPath"_s ).toString();
759 filter = generator->createFileFilter();
761 filter = QObject::tr(
"All files (*.*)" );
763 const QString filename = QFileDialog::getOpenFileName(
this, tr(
"Select File" ), path, filter );
764 if ( filename.isEmpty() )
767 settings.
setValue( u
"/Processing/LastInputPath"_s, QFileInfo( filename ).path() );
769 setValue( filename, context );
772void QgsProcessingMapLayerComboBox::browseForLayer()
777 widget->
setPanelTitle( tr(
"Browse for \"%1\"" ).arg( mParameter->description() ) );
779 panel->openPanel( widget );
786 if ( widget->
uri().
uri.isEmpty() )
787 setValue( QVariant(), context );
789 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.
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.
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
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.