37#include <QDragEnterEvent>
45#include "moc_qgsprocessingmaplayercombobox.cpp"
51 , mParameter( parameter->clone() )
53 QHBoxLayout *layout =
new QHBoxLayout();
54 layout->setContentsMargins( 0, 0, 0, 0 );
55 layout->setSpacing( 6 );
58 layout->addWidget( mCombo );
59 layout->setAlignment( mCombo, Qt::AlignTop );
64 mIterateButton =
new QToolButton();
66 mIterateButton->setToolTip( tr(
"Iterate over this layer, creating a separate output for every feature in the layer" ) );
67 mIterateButton->setCheckable(
true );
68 mIterateButton->setAutoRaise(
true );
71 mIterateButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
72 mIterateButton->setIconSize( QSize( iconSize, iconSize ) );
74 layout->addWidget( mIterateButton );
75 layout->setAlignment( mIterateButton, Qt::AlignTop );
80 mSettingsButton =
new QToolButton();
82 mSettingsButton->setToolTip( tr(
"Advanced options" ) );
85 mSettingsButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
86 mSettingsButton->setIconSize( QSize( iconSize, iconSize ) );
87 mSettingsButton->setAutoRaise(
true );
89 connect( mSettingsButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::showSourceOptions );
90 layout->addWidget( mSettingsButton );
91 layout->setAlignment( mSettingsButton, Qt::AlignTop );
95 mSettingsButton =
new QToolButton();
97 mSettingsButton->setToolTip( tr(
"Advanced options" ) );
98 mSettingsButton->setEnabled(
false );
101 mSettingsButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
102 mSettingsButton->setIconSize( QSize( iconSize, iconSize ) );
103 mSettingsButton->setAutoRaise(
true );
105 connect( mSettingsButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::showRasterSourceOptions );
106 layout->addWidget( mSettingsButton );
107 layout->setAlignment( mSettingsButton, Qt::AlignTop );
110 mSelectButton =
new QToolButton();
111 mSelectButton->setText( QString( QChar( 0x2026 ) ) );
112 mSelectButton->setToolTip( tr(
"Select input" ) );
113 layout->addWidget( mSelectButton );
114 layout->setAlignment( mSelectButton, Qt::AlignTop );
117 mFeatureSourceMenu =
new QMenu(
this );
118 QAction *selectFromFileAction =
new QAction( tr(
"Select File…" ), mFeatureSourceMenu );
119 connect( selectFromFileAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
120 mFeatureSourceMenu->addAction( selectFromFileAction );
121 QAction *browseForLayerAction =
new QAction( tr(
"Browse for Layer…" ), mFeatureSourceMenu );
122 connect( browseForLayerAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::browseForLayer );
123 mFeatureSourceMenu->addAction( browseForLayerAction );
124 mSelectButton->setMenu( mFeatureSourceMenu );
125 mSelectButton->setPopupMode( QToolButton::InstantPopup );
129 connect( mSelectButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
132 QVBoxLayout *vl =
new QVBoxLayout();
133 vl->setContentsMargins( 0, 0, 0, 0 );
135 vl->addLayout( layout );
141 mUseSelectionCheckBox =
new QCheckBox( tr(
"Selected features only" ) );
142 mUseSelectionCheckBox->setChecked(
false );
143 mUseSelectionCheckBox->setEnabled(
false );
144 vl->addWidget( mUseSelectionCheckBox );
147 bool mayBeRaster {
false };
151 QList<int> dataTypes;
183 QList<int> dataTypes;
216 if ( settings.
value( QStringLiteral(
"Processing/Configuration/SHOW_CRS_DEF" ),
true ).toBool() )
217 mCombo->setShowCrs(
true );
220 mCombo->setFilters( filters );
226 mCombo->setExcludedProviders( mCombo->excludedProviders() << QStringLiteral(
"virtualraster" ) );
231 mCombo->setAllowEmptyLayer(
true );
232 mCombo->setLayer(
nullptr );
236 if ( mUseSelectionCheckBox )
237 connect( mUseSelectionCheckBox, &QCheckBox::toggled,
this, [
this] {
238 if ( !mBlockChangedSignal )
244 setAcceptDrops(
true );
246 onLayerChanged( mCombo->currentLayer() );
249QgsProcessingMapLayerComboBox::~QgsProcessingMapLayerComboBox() =
default;
251void QgsProcessingMapLayerComboBox::setLayer(
QgsMapLayer *layer )
255 mCombo->setLayer( layer );
259QgsMapLayer *QgsProcessingMapLayerComboBox::currentLayer()
261 return mCombo->currentLayer();
264QString QgsProcessingMapLayerComboBox::currentText()
266 return mCombo->currentText();
269void QgsProcessingMapLayerComboBox::setValue(
const QVariant &value,
QgsProcessingContext &context )
277 QVariant val = value;
279 bool selectedOnly =
false;
280 bool iterate =
false;
281 if ( val.userType() == qMetaTypeId<QgsProcessingFeatureSourceDefinition>() )
295 mFilterExpression.clear();
296 mIsOverridingDefaultGeometryCheck =
false;
300 if ( val.userType() == qMetaTypeId<QgsProcessingRasterLayerDefinition>() )
305 mRasterDpi = fromVar.
dpi;
309 mRasterReferenceScale = 0;
313 if ( val.userType() == qMetaTypeId<QgsProperty>() )
325 QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( val.value<QObject *>() );
326 if ( !layer && val.userType() == QMetaType::Type::QString )
333 mBlockChangedSignal++;
336 found =
static_cast<bool>( currentLayer() );
337 bool changed = found && ( currentLayer() != prevLayer );
338 if ( found && mUseSelectionCheckBox )
340 const bool hasSelection = qobject_cast<QgsVectorLayer *>( layer ) && qobject_cast<QgsVectorLayer *>( layer )->selectedFeatureCount() > 0;
341 changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
344 mUseSelectionCheckBox->setEnabled(
true );
345 mUseSelectionCheckBox->setChecked( selectedOnly );
349 mUseSelectionCheckBox->setChecked(
false );
350 mUseSelectionCheckBox->setEnabled(
false );
353 if ( mIterateButton )
355 mIterateButton->setChecked( iterate );
358 mBlockChangedSignal--;
365 const QString
string = val.toString();
366 if ( mIterateButton )
367 mIterateButton->setChecked( iterate );
369 if ( !
string.isEmpty() )
371 mBlockChangedSignal++;
372 if ( mCombo->findText(
string ) < 0 )
374 QStringList additional = mCombo->additionalItems();
375 additional.append(
string );
376 mCombo->setAdditionalItems( additional );
378 mCombo->setCurrentIndex( mCombo->findText(
string ) );
379 if ( mUseSelectionCheckBox )
381 mUseSelectionCheckBox->setChecked(
false );
382 mUseSelectionCheckBox->setEnabled(
false );
384 mBlockChangedSignal--;
385 if ( !mBlockChangedSignal )
390 mCombo->setLayer(
nullptr );
391 if ( mUseSelectionCheckBox )
393 mUseSelectionCheckBox->setChecked(
false );
394 mUseSelectionCheckBox->setEnabled(
false );
400QVariant QgsProcessingMapLayerComboBox::value()
const
402 if ( isEditable() && mCombo->currentText() != mCombo->itemText( mCombo->currentIndex() ) )
403 return mCombo->currentText();
405 const bool iterate = mIterateButton && mIterateButton->isChecked();
406 const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
409 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
411 else if ( mRasterReferenceScale != 0 )
418 if ( !mCombo->currentText().isEmpty() )
420 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
422 else if ( mRasterReferenceScale != 0 )
425 return mCombo->currentText();
434 mCombo->setProject( context.
project() );
437void QgsProcessingMapLayerComboBox::setEditable(
bool editable )
439 mCombo->setEditable( editable );
442bool QgsProcessingMapLayerComboBox::isEditable()
const
444 return mCombo->isEditable();
447QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData(
const QMimeData *data,
bool &incompatibleLayerSelected )
const
449 incompatibleLayerSelected =
false;
456 if ( mCombo->mProxyModel->acceptsLayer( layer ) )
460 incompatibleLayerSelected =
true;
469QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData(
const QMimeData *data )
const
476 && u.layerType == QLatin1String(
"vector" ) )
481 bool acceptable =
false;
512 && u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" ) )
515 && u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" ) )
525 if ( u.layerType == QLatin1String(
"vector" ) && u.providerKey == QLatin1String(
"ogr" ) )
551 else if ( u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" )
554 else if ( u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" )
559 if ( !uriList.isEmpty() )
563 QStringList rawPaths;
564 if ( data->hasUrls() )
566 const QList<QUrl> urls = data->urls();
567 rawPaths.reserve( urls.count() );
568 for (
const QUrl &url : urls )
570 const QString local = url.toLocalFile();
571 if ( !rawPaths.contains( local ) )
572 rawPaths.append( local );
575 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
576 rawPaths.append( data->text() );
578 for (
const QString &path : std::as_const( rawPaths ) )
580 QFileInfo file( path );
591void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
593 if ( !( event->possibleActions() & Qt::CopyAction ) )
596 bool incompatibleLayerSelected =
false;
597 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
598 const QString uri = compatibleUriFromMimeData( event->mimeData() );
599 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
602 event->setDropAction( Qt::CopyAction );
605 mCombo->mHighlight =
true;
610void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
612 QWidget::dragLeaveEvent( event );
617 mCombo->mHighlight =
false;
622void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
624 if ( !( event->possibleActions() & Qt::CopyAction ) )
627 bool incompatibleLayerSelected =
false;
628 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
629 const QString uri = compatibleUriFromMimeData( event->mimeData() );
630 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
633 setFocus( Qt::MouseFocusReason );
634 event->setDropAction( Qt::CopyAction );
637 setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
640 mCombo->mHighlight =
false;
644void QgsProcessingMapLayerComboBox::onLayerChanged(
QgsMapLayer *layer )
648 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
650 if (
QgsVectorLayer *prevLayer = qobject_cast<QgsVectorLayer *>( mPrevLayer ) )
654 if ( vl->selectedFeatureCount() == 0 )
655 mUseSelectionCheckBox->setChecked(
false );
656 mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
670 if ( !mBlockChangedSignal )
676 if ( selected.isEmpty() )
677 mUseSelectionCheckBox->setChecked(
false );
678 mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
681void QgsProcessingMapLayerComboBox::showSourceOptions()
685 QgsProcessingFeatureSourceOptionsWidget *widget =
new QgsProcessingFeatureSourceOptionsWidget();
686 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
687 widget->setLayer( qobject_cast<QgsVectorLayer *>( mCombo->currentLayer() ) );
689 widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
690 widget->setFeatureLimit( mFeatureLimit );
691 widget->setFilterExpression( mFilterExpression );
693 panel->openPanel( widget );
696 bool changed =
false;
697 changed = changed | ( widget->featureLimit() != mFeatureLimit );
698 changed = changed | ( widget->filterExpression() != mFilterExpression );
699 changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
700 changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
702 mFeatureLimit = widget->featureLimit();
703 mFilterExpression = widget->filterExpression();
704 mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
705 mGeometryCheck = widget->geometryCheckMethod();
713void QgsProcessingMapLayerComboBox::showRasterSourceOptions()
717 QgsProcessingRasterSourceOptionsWidget *widget =
new QgsProcessingRasterSourceOptionsWidget();
718 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
719 widget->setReferenceScale( mRasterReferenceScale );
720 widget->setDpi( mRasterDpi );
725 panel->openPanel( widget );
728 bool changed =
false;
729 changed = changed | ( widget->referenceScale() != mRasterReferenceScale );
730 changed = changed | ( widget->dpi() != mRasterDpi );
732 mRasterReferenceScale = widget->referenceScale();
733 mRasterDpi = widget->dpi();
741void QgsProcessingMapLayerComboBox::selectFromFile()
744 const QString initialValue = currentText();
747 if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
749 else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() !=
'.' )
750 path = QFileInfo( initialValue ).path();
751 else if ( settings.
contains( QStringLiteral(
"/Processing/LastInputPath" ) ) )
752 path = settings.
value( QStringLiteral(
"/Processing/LastInputPath" ) ).toString();
756 filter = generator->createFileFilter();
758 filter = QObject::tr(
"All files (*.*)" );
760 const QString filename = QFileDialog::getOpenFileName(
this, tr(
"Select File" ), path, filter );
761 if ( filename.isEmpty() )
764 settings.
setValue( QStringLiteral(
"/Processing/LastInputPath" ), QFileInfo( filename ).path() );
766 setValue( filename, context );
769void QgsProcessingMapLayerComboBox::browseForLayer()
774 widget->
setPanelTitle( tr(
"Browse for \"%1\"" ).arg( mParameter->description() ) );
776 panel->openPanel( widget );
783 if ( widget->
uri().
uri.isEmpty() )
784 setValue( QVariant(), context );
786 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.