33#include <QDragEnterEvent>
43 , mParameter( parameter->clone() )
45 QHBoxLayout *layout =
new QHBoxLayout();
46 layout->setContentsMargins( 0, 0, 0, 0 );
47 layout->setSpacing( 6 );
50 layout->addWidget( mCombo );
51 layout->setAlignment( mCombo, Qt::AlignTop );
56 mIterateButton =
new QToolButton();
58 mIterateButton->setToolTip( tr(
"Iterate over this layer, creating a separate output for every feature in the layer" ) );
59 mIterateButton->setCheckable(
true );
60 mIterateButton->setAutoRaise(
true );
63 mIterateButton->setFixedSize( 2 *
static_cast< int >( 1.25 * iconSize / 2.0 ), 2 *
static_cast< int >( iconSize * 1.1 / 2.0 ) );
64 mIterateButton->setIconSize( QSize( iconSize, iconSize ) );
66 layout->addWidget( mIterateButton );
67 layout->setAlignment( mIterateButton, Qt::AlignTop );
72 mSettingsButton =
new QToolButton();
74 mSettingsButton->setToolTip( tr(
"Advanced options" ) );
77 mSettingsButton->setFixedSize( 2 *
static_cast< int >( 1.25 * iconSize / 2.0 ), 2 *
static_cast< int >( iconSize * 1.1 / 2.0 ) );
78 mSettingsButton->setIconSize( QSize( iconSize, iconSize ) );
79 mSettingsButton->setAutoRaise(
true );
81 connect( mSettingsButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::showSourceOptions );
82 layout->addWidget( mSettingsButton );
83 layout->setAlignment( mSettingsButton, Qt::AlignTop );
86 mSelectButton =
new QToolButton();
87 mSelectButton->setText( QString( QChar( 0x2026 ) ) );
88 mSelectButton->setToolTip( tr(
"Select input" ) );
89 layout->addWidget( mSelectButton );
90 layout->setAlignment( mSelectButton, Qt::AlignTop );
93 mFeatureSourceMenu =
new QMenu(
this );
94 QAction *selectFromFileAction =
new QAction( tr(
"Select File…" ), mFeatureSourceMenu );
95 connect( selectFromFileAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
96 mFeatureSourceMenu->addAction( selectFromFileAction );
97 QAction *browseForLayerAction =
new QAction( tr(
"Browse for Layer…" ), mFeatureSourceMenu );
98 connect( browseForLayerAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::browseForLayer );
99 mFeatureSourceMenu->addAction( browseForLayerAction );
100 mSelectButton->setMenu( mFeatureSourceMenu );
101 mSelectButton->setPopupMode( QToolButton::InstantPopup );
105 connect( mSelectButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
108 QVBoxLayout *vl =
new QVBoxLayout();
109 vl->setContentsMargins( 0, 0, 0, 0 );
111 vl->addLayout( layout );
113 Qgis::LayerFilters filters = Qgis::LayerFilters();
117 mUseSelectionCheckBox =
new QCheckBox( tr(
"Selected features only" ) );
118 mUseSelectionCheckBox->setChecked(
false );
119 mUseSelectionCheckBox->setEnabled(
false );
120 vl->addWidget( mUseSelectionCheckBox );
125 QList<int> dataTypes;
156 QList<int> dataTypes;
178 if ( settings.
value( QStringLiteral(
"Processing/Configuration/SHOW_CRS_DEF" ), true ).toBool() )
179 mCombo->setShowCrs(
true );
182 mCombo->setFilters( filters );
183 mCombo->setExcludedProviders( QStringList() << QStringLiteral(
"grass" ) );
187 mCombo->setAllowEmptyLayer(
true );
188 mCombo->setLayer(
nullptr );
192 if ( mUseSelectionCheckBox )
193 connect( mUseSelectionCheckBox, &QCheckBox::toggled,
this, [ = ]
195 if ( !mBlockChangedSignal )
201 setAcceptDrops(
true );
203 onLayerChanged( mCombo->currentLayer() );
206QgsProcessingMapLayerComboBox::~QgsProcessingMapLayerComboBox() =
default;
208void QgsProcessingMapLayerComboBox::setLayer(
QgsMapLayer *layer )
211 mCombo->setLayer( layer );
214QgsMapLayer *QgsProcessingMapLayerComboBox::currentLayer()
216 return mCombo->currentLayer();
219QString QgsProcessingMapLayerComboBox::currentText()
221 return mCombo->currentText();
224void QgsProcessingMapLayerComboBox::setValue(
const QVariant &value,
QgsProcessingContext &context )
232 QVariant val = value;
234 bool selectedOnly =
false;
235 bool iterate =
false;
236 if ( val.userType() == QMetaType::type(
"QgsProcessingFeatureSourceDefinition" ) )
250 mFilterExpression.clear();
251 mIsOverridingDefaultGeometryCheck =
false;
255 if ( val.userType() == QMetaType::type(
"QgsProperty" ) )
267 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( val.value< QObject * >() );
268 if ( !layer && val.type() == QVariant::String )
275 mBlockChangedSignal++;
278 found =
static_cast< bool >( currentLayer() );
279 bool changed = found && ( currentLayer() != prevLayer );
280 if ( found && mUseSelectionCheckBox )
282 const bool hasSelection = qobject_cast< QgsVectorLayer * >( layer ) && qobject_cast< QgsVectorLayer * >( layer )->selectedFeatureCount() > 0;
283 changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
286 mUseSelectionCheckBox->setEnabled(
true );
287 mUseSelectionCheckBox->setChecked( selectedOnly );
291 mUseSelectionCheckBox->setChecked(
false );
292 mUseSelectionCheckBox->setEnabled(
false );
295 if ( mIterateButton )
297 mIterateButton->setChecked( iterate );
300 mBlockChangedSignal--;
307 const QString
string = val.toString();
308 if ( mIterateButton )
309 mIterateButton->setChecked( iterate );
311 if ( !
string.isEmpty() )
313 mBlockChangedSignal++;
314 if ( mCombo->findText(
string ) < 0 )
316 QStringList additional = mCombo->additionalItems();
317 additional.append(
string );
318 mCombo->setAdditionalItems( additional );
320 mCombo->setCurrentIndex( mCombo->findText(
string ) );
321 if ( mUseSelectionCheckBox )
323 mUseSelectionCheckBox->setChecked(
false );
324 mUseSelectionCheckBox->setEnabled(
false );
326 mBlockChangedSignal--;
327 if ( !mBlockChangedSignal )
332 mCombo->setLayer(
nullptr );
333 if ( mUseSelectionCheckBox )
335 mUseSelectionCheckBox->setChecked(
false );
336 mUseSelectionCheckBox->setEnabled(
false );
342QVariant QgsProcessingMapLayerComboBox::value()
const
344 if ( isEditable() && mCombo->currentText() != mCombo->itemText( mCombo->currentIndex() ) )
345 return mCombo->currentText();
347 const bool iterate = mIterateButton && mIterateButton->isChecked();
348 const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
351 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
355 mGeometryCheck, mFilterExpression );
361 if ( !mCombo->currentText().isEmpty() )
363 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
367 mGeometryCheck, mFilterExpression );
369 return mCombo->currentText();
378 mCombo->setProject( context.
project() );
381void QgsProcessingMapLayerComboBox::setEditable(
bool editable )
383 mCombo->setEditable( editable );
386bool QgsProcessingMapLayerComboBox::isEditable()
const
388 return mCombo->isEditable();
391QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData(
const QMimeData *data,
bool &incompatibleLayerSelected )
const
393 incompatibleLayerSelected =
false;
400 if ( mCombo->mProxyModel->acceptsLayer( layer ) )
404 incompatibleLayerSelected =
true;
413QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData(
const QMimeData *data )
const
420 && u.layerType == QLatin1String(
"vector" ) )
425 bool acceptable =
false;
456 && u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" ) )
459 && u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" ) )
469 if ( u.layerType == QLatin1String(
"vector" ) && u.providerKey == QLatin1String(
"ogr" ) )
495 else if ( u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" )
498 else if ( u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" )
503 if ( !uriList.isEmpty() )
507 QStringList rawPaths;
508 if ( data->hasUrls() )
510 const QList< QUrl > urls = data->urls();
511 rawPaths.reserve( urls.count() );
512 for (
const QUrl &url : urls )
514 const QString local = url.toLocalFile();
515 if ( !rawPaths.contains( local ) )
516 rawPaths.append( local );
519 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
520 rawPaths.append( data->text() );
522 for (
const QString &path : std::as_const( rawPaths ) )
524 QFileInfo file( path );
535void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
537 if ( !( event->possibleActions() & Qt::CopyAction ) )
540 bool incompatibleLayerSelected =
false;
541 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
542 const QString uri = compatibleUriFromMimeData( event->mimeData() );
543 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
546 event->setDropAction( Qt::CopyAction );
549 mCombo->mHighlight =
true;
554void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
556 QWidget::dragLeaveEvent( event );
561 mCombo->mHighlight =
false;
566void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
568 if ( !( event->possibleActions() & Qt::CopyAction ) )
571 bool incompatibleLayerSelected =
false;
572 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
573 const QString uri = compatibleUriFromMimeData( event->mimeData() );
574 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
577 setFocus( Qt::MouseFocusReason );
578 event->setDropAction( Qt::CopyAction );
581 setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
584 mCombo->mHighlight =
false;
588void QgsProcessingMapLayerComboBox::onLayerChanged(
QgsMapLayer *layer )
592 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
594 if (
QgsVectorLayer *prevLayer = qobject_cast< QgsVectorLayer * >( mPrevLayer ) )
598 if ( vl->selectedFeatureCount() == 0 )
599 mUseSelectionCheckBox->setChecked(
false );
600 mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
606 if ( !mBlockChangedSignal )
612 if ( selected.isEmpty() )
613 mUseSelectionCheckBox->setChecked(
false );
614 mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
617void QgsProcessingMapLayerComboBox::showSourceOptions()
621 QgsProcessingFeatureSourceOptionsWidget *widget =
new QgsProcessingFeatureSourceOptionsWidget();
622 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
623 widget->setLayer( qobject_cast< QgsVectorLayer * >( mCombo->currentLayer() ) );
625 widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
626 widget->setFeatureLimit( mFeatureLimit );
627 widget->setFilterExpression( mFilterExpression );
629 panel->openPanel( widget );
633 bool changed =
false;
634 changed = changed | ( widget->featureLimit() != mFeatureLimit );
635 changed = changed | ( widget->filterExpression() != mFilterExpression );
636 changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
637 changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
639 mFeatureLimit = widget->featureLimit();
640 mFilterExpression = widget->filterExpression();
641 mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
642 mGeometryCheck = widget->geometryCheckMethod();
650void QgsProcessingMapLayerComboBox::selectFromFile()
653 const QString initialValue = currentText();
656 if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
658 else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() !=
'.' )
659 path = QFileInfo( initialValue ).path();
660 else if ( settings.
contains( QStringLiteral(
"/Processing/LastInputPath" ) ) )
661 path = settings.
value( QStringLiteral(
"/Processing/LastInputPath" ) ).toString();
665 filter = generator->createFileFilter();
667 filter = QObject::tr(
"All files (*.*)" );
669 const QString filename = QFileDialog::getOpenFileName(
this, tr(
"Select File" ), path, filter );
670 if ( filename.isEmpty() )
673 settings.
setValue( QStringLiteral(
"/Processing/LastInputPath" ), QFileInfo( filename ).path() );
675 setValue( filename, context );
678void QgsProcessingMapLayerComboBox::browseForLayer()
683 widget->
setPanelTitle( tr(
"Browse for \"%1\"" ).arg( mParameter->description() ) );
685 panel->openPanel( widget );
694 if ( widget->
uri().
uri.isEmpty() )
695 setValue( QVariant(), context );
697 setValue( widget->
uri().
uri, context );
@ PointCloudLayer
QgsPointCloudLayer.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
@ GeometryAbortOnInvalid
Close iterator on encountering any features with invalid geometry. This requires a slow geometry vali...
Abstract interface for classes which generate a file filter string.
The QgsMapLayerComboBox class is a combo box which displays the list of layers.
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
Base class for all map layer types.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
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.
Flags flags
Flags which dictate source behavior.
bool selectedFeaturesOnly
true if only selected features in the source should be used by algorithms.
QgsFeatureRequest::InvalidGeometryCheck geometryCheck
Geometry check method to apply to this source.
QgsProperty source
Source definition.
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...
@ FlagCreateIndividualOutputPerInputFeature
If set, every feature processed from this source will be placed into its own individually created out...
@ FlagOverrideDefaultGeometryCheck
If set, the default geometry check method (as dictated by QgsProcessingContext) will be overridden fo...
QString filterExpression
Optional expression filter to use for filtering features which will be read from the source.
WidgetType
Types of dialogs which Processing widgets can be created for.
@ Standard
Standard algorithm dialog.
Base class for the definition of processing parameters.
@ FlagOptional
Parameter is optional.
An input feature source (such as vector layers) parameter for processing algorithms.
static QString typeName()
Returns the type name for the parameter class.
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.
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.
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.
@ TypeVectorLine
Vector line layers.
@ TypeMapLayer
Any map layer type (raster, vector, mesh, point cloud, annotation or plugin layer)
@ TypeVectorPolygon
Vector polygon layers.
@ TypePointCloud
Point cloud layers.
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
@ TypeRaster
Raster layers.
@ TypeVectorPoint
Vector point layers.
@ TypeVectorAnyGeometry
Any vector layer with geometry.
A store for object properties.
@ StaticProperty
Static property (QgsStaticProperty)
Type propertyType() const
Returns the property type.
This class is a composition of two QSettings instances:
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 data sets.
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...
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.