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() )
422 else if ( mRasterReferenceScale != 0 )
429 if ( !mCombo->currentText().isEmpty() )
431 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
433 mCombo->currentText(),
441 else if ( mRasterReferenceScale != 0 )
444 return mCombo->currentText();
453 mCombo->setProject( context.
project() );
456void QgsProcessingMapLayerComboBox::setEditable(
bool editable )
458 mCombo->setEditable( editable );
461bool QgsProcessingMapLayerComboBox::isEditable()
const
463 return mCombo->isEditable();
466QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData(
const QMimeData *data,
bool &incompatibleLayerSelected )
const
468 incompatibleLayerSelected =
false;
475 if ( mCombo->mProxyModel->acceptsLayer( layer ) )
479 incompatibleLayerSelected =
true;
488QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData(
const QMimeData *data )
const
499 bool acceptable =
false;
507 if ( dataTypes.isEmpty()
515 if ( dataTypes.isEmpty()
523 if ( dataTypes.isEmpty()
550 if ( u.layerType ==
"vector"_L1 && u.providerKey ==
"ogr"_L1 )
582 if ( !uriList.isEmpty() )
586 QStringList rawPaths;
587 if ( data->hasUrls() )
589 const QList<QUrl> urls = data->urls();
590 rawPaths.reserve( urls.count() );
591 for (
const QUrl &url : urls )
593 const QString local = url.toLocalFile();
594 if ( !rawPaths.contains( local ) )
595 rawPaths.append( local );
598 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
599 rawPaths.append( data->text() );
601 for (
const QString &path : std::as_const( rawPaths ) )
603 QFileInfo file( path );
614void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
616 if ( !( event->possibleActions() & Qt::CopyAction ) )
619 bool incompatibleLayerSelected =
false;
620 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
621 const QString uri = compatibleUriFromMimeData( event->mimeData() );
622 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
625 event->setDropAction( Qt::CopyAction );
628 mCombo->mHighlight =
true;
633void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
635 QWidget::dragLeaveEvent( event );
640 mCombo->mHighlight =
false;
645void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
647 if ( !( event->possibleActions() & Qt::CopyAction ) )
650 bool incompatibleLayerSelected =
false;
651 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
652 const QString uri = compatibleUriFromMimeData( event->mimeData() );
653 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
656 setFocus( Qt::MouseFocusReason );
657 event->setDropAction( Qt::CopyAction );
660 setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
663 mCombo->mHighlight =
false;
667void QgsProcessingMapLayerComboBox::onLayerChanged(
QgsMapLayer *layer )
671 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
673 if (
QgsVectorLayer *prevLayer = qobject_cast<QgsVectorLayer *>( mPrevLayer ) )
677 if ( vl->selectedFeatureCount() == 0 )
678 mUseSelectionCheckBox->setChecked(
false );
679 mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
694 if ( !mBlockChangedSignal )
700 if ( selected.isEmpty() )
701 mUseSelectionCheckBox->setChecked(
false );
702 mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
705void QgsProcessingMapLayerComboBox::showSourceOptions()
709 QgsProcessingFeatureSourceOptionsWidget *widget =
new QgsProcessingFeatureSourceOptionsWidget();
710 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
711 widget->setLayer( qobject_cast<QgsVectorLayer *>( mCombo->currentLayer() ) );
713 widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
714 widget->setFeatureLimit( mFeatureLimit );
715 widget->setFilterExpression( mFilterExpression );
717 panel->openPanel( widget );
720 bool changed =
false;
721 changed = changed | ( widget->featureLimit() != mFeatureLimit );
722 changed = changed | ( widget->filterExpression() != mFilterExpression );
723 changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
724 changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
726 mFeatureLimit = widget->featureLimit();
727 mFilterExpression = widget->filterExpression();
728 mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
729 mGeometryCheck = widget->geometryCheckMethod();
737void QgsProcessingMapLayerComboBox::showRasterSourceOptions()
741 QgsProcessingRasterSourceOptionsWidget *widget =
new QgsProcessingRasterSourceOptionsWidget();
742 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
743 widget->setReferenceScale( mRasterReferenceScale );
744 widget->setDpi( mRasterDpi );
749 panel->openPanel( widget );
752 bool changed =
false;
753 changed = changed | ( widget->referenceScale() != mRasterReferenceScale );
754 changed = changed | ( widget->dpi() != mRasterDpi );
756 mRasterReferenceScale = widget->referenceScale();
757 mRasterDpi = widget->dpi();
765void QgsProcessingMapLayerComboBox::selectFromFile()
768 const QString initialValue = currentText();
771 if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
773 else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() !=
'.' )
774 path = QFileInfo( initialValue ).path();
775 else if ( settings.
contains( u
"/Processing/LastInputPath"_s ) )
776 path = settings.
value( u
"/Processing/LastInputPath"_s ).toString();
780 filter = generator->createFileFilter();
782 filter = QObject::tr(
"All files (*.*)" );
784 const QString filename = QFileDialog::getOpenFileName(
this, tr(
"Select File" ), path, filter );
785 if ( filename.isEmpty() )
788 settings.
setValue( u
"/Processing/LastInputPath"_s, QFileInfo( filename ).path() );
790 setValue( filename, context );
793void QgsProcessingMapLayerComboBox::browseForLayer()
798 widget->
setPanelTitle( tr(
"Browse for \"%1\"" ).arg( mParameter->description() ) );
800 panel->openPanel( widget );
805 if ( widget->
uri().
uri.isEmpty() )
806 setValue( QVariant(), context );
808 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.