34#include <QDragEnterEvent>
44 , mParameter( parameter->clone() )
46 QHBoxLayout *layout =
new QHBoxLayout();
47 layout->setContentsMargins( 0, 0, 0, 0 );
48 layout->setSpacing( 6 );
51 layout->addWidget( mCombo );
52 layout->setAlignment( mCombo, Qt::AlignTop );
57 mIterateButton =
new QToolButton();
59 mIterateButton->setToolTip( tr(
"Iterate over this layer, creating a separate output for every feature in the layer" ) );
60 mIterateButton->setCheckable(
true );
61 mIterateButton->setAutoRaise(
true );
64 mIterateButton->setFixedSize( 2 *
static_cast< int >( 1.25 * iconSize / 2.0 ), 2 *
static_cast< int >( iconSize * 1.1 / 2.0 ) );
65 mIterateButton->setIconSize( QSize( iconSize, iconSize ) );
67 layout->addWidget( mIterateButton );
68 layout->setAlignment( mIterateButton, Qt::AlignTop );
73 mSettingsButton =
new QToolButton();
75 mSettingsButton->setToolTip( tr(
"Advanced options" ) );
78 mSettingsButton->setFixedSize( 2 *
static_cast< int >( 1.25 * iconSize / 2.0 ), 2 *
static_cast< int >( iconSize * 1.1 / 2.0 ) );
79 mSettingsButton->setIconSize( QSize( iconSize, iconSize ) );
80 mSettingsButton->setAutoRaise(
true );
82 connect( mSettingsButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::showSourceOptions );
83 layout->addWidget( mSettingsButton );
84 layout->setAlignment( mSettingsButton, Qt::AlignTop );
87 mSelectButton =
new QToolButton();
88 mSelectButton->setText( QString( QChar( 0x2026 ) ) );
89 mSelectButton->setToolTip( tr(
"Select input" ) );
90 layout->addWidget( mSelectButton );
91 layout->setAlignment( mSelectButton, Qt::AlignTop );
94 mFeatureSourceMenu =
new QMenu(
this );
95 QAction *selectFromFileAction =
new QAction( tr(
"Select File…" ), mFeatureSourceMenu );
96 connect( selectFromFileAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
97 mFeatureSourceMenu->addAction( selectFromFileAction );
98 QAction *browseForLayerAction =
new QAction( tr(
"Browse for Layer…" ), mFeatureSourceMenu );
99 connect( browseForLayerAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::browseForLayer );
100 mFeatureSourceMenu->addAction( browseForLayerAction );
101 mSelectButton->setMenu( mFeatureSourceMenu );
102 mSelectButton->setPopupMode( QToolButton::InstantPopup );
106 connect( mSelectButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
109 QVBoxLayout *vl =
new QVBoxLayout();
110 vl->setContentsMargins( 0, 0, 0, 0 );
112 vl->addLayout( layout );
118 mUseSelectionCheckBox =
new QCheckBox( tr(
"Selected features only" ) );
119 mUseSelectionCheckBox->setChecked(
false );
120 mUseSelectionCheckBox->setEnabled(
false );
121 vl->addWidget( mUseSelectionCheckBox );
124 bool mayBeRaster {
false };
128 QList<int> dataTypes;
160 QList<int> dataTypes;
185 if ( settings.
value( QStringLiteral(
"Processing/Configuration/SHOW_CRS_DEF" ), true ).toBool() )
186 mCombo->setShowCrs(
true );
189 mCombo->setFilters( filters );
196 mCombo->setExcludedProviders( mCombo->excludedProviders() << QStringLiteral(
"virtualraster" ) );
201 mCombo->setAllowEmptyLayer(
true );
202 mCombo->setLayer(
nullptr );
206 if ( mUseSelectionCheckBox )
207 connect( mUseSelectionCheckBox, &QCheckBox::toggled,
this, [ = ]
209 if ( !mBlockChangedSignal )
215 setAcceptDrops(
true );
217 onLayerChanged( mCombo->currentLayer() );
220QgsProcessingMapLayerComboBox::~QgsProcessingMapLayerComboBox() =
default;
222void QgsProcessingMapLayerComboBox::setLayer(
QgsMapLayer *layer )
225 mCombo->setLayer( layer );
228QgsMapLayer *QgsProcessingMapLayerComboBox::currentLayer()
230 return mCombo->currentLayer();
233QString QgsProcessingMapLayerComboBox::currentText()
235 return mCombo->currentText();
238void QgsProcessingMapLayerComboBox::setValue(
const QVariant &value,
QgsProcessingContext &context )
246 QVariant val = value;
248 bool selectedOnly =
false;
249 bool iterate =
false;
250 if ( val.userType() == qMetaTypeId<QgsProcessingFeatureSourceDefinition>() )
264 mFilterExpression.clear();
265 mIsOverridingDefaultGeometryCheck =
false;
269 if ( val.userType() == qMetaTypeId<QgsProperty>() )
281 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( val.value< QObject * >() );
282 if ( !layer && val.userType() == QMetaType::Type::QString )
289 mBlockChangedSignal++;
292 found =
static_cast< bool >( currentLayer() );
293 bool changed = found && ( currentLayer() != prevLayer );
294 if ( found && mUseSelectionCheckBox )
296 const bool hasSelection = qobject_cast< QgsVectorLayer * >( layer ) && qobject_cast< QgsVectorLayer * >( layer )->selectedFeatureCount() > 0;
297 changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
300 mUseSelectionCheckBox->setEnabled(
true );
301 mUseSelectionCheckBox->setChecked( selectedOnly );
305 mUseSelectionCheckBox->setChecked(
false );
306 mUseSelectionCheckBox->setEnabled(
false );
309 if ( mIterateButton )
311 mIterateButton->setChecked( iterate );
314 mBlockChangedSignal--;
321 const QString
string = val.toString();
322 if ( mIterateButton )
323 mIterateButton->setChecked( iterate );
325 if ( !
string.isEmpty() )
327 mBlockChangedSignal++;
328 if ( mCombo->findText(
string ) < 0 )
330 QStringList additional = mCombo->additionalItems();
331 additional.append(
string );
332 mCombo->setAdditionalItems( additional );
334 mCombo->setCurrentIndex( mCombo->findText(
string ) );
335 if ( mUseSelectionCheckBox )
337 mUseSelectionCheckBox->setChecked(
false );
338 mUseSelectionCheckBox->setEnabled(
false );
340 mBlockChangedSignal--;
341 if ( !mBlockChangedSignal )
346 mCombo->setLayer(
nullptr );
347 if ( mUseSelectionCheckBox )
349 mUseSelectionCheckBox->setChecked(
false );
350 mUseSelectionCheckBox->setEnabled(
false );
356QVariant QgsProcessingMapLayerComboBox::value()
const
358 if ( isEditable() && mCombo->currentText() != mCombo->itemText( mCombo->currentIndex() ) )
359 return mCombo->currentText();
361 const bool iterate = mIterateButton && mIterateButton->isChecked();
362 const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
365 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
368 | ( mIsOverridingDefaultGeometryCheck ?
Qgis::ProcessingFeatureSourceDefinitionFlag::OverrideDefaultGeometryCheck :
Qgis::ProcessingFeatureSourceDefinitionFlags() ),
369 mGeometryCheck, mFilterExpression );
375 if ( !mCombo->currentText().isEmpty() )
377 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
380 | ( mIsOverridingDefaultGeometryCheck ?
Qgis::ProcessingFeatureSourceDefinitionFlag::OverrideDefaultGeometryCheck :
Qgis::ProcessingFeatureSourceDefinitionFlags() ),
381 mGeometryCheck, mFilterExpression );
383 return mCombo->currentText();
392 mCombo->setProject( context.
project() );
395void QgsProcessingMapLayerComboBox::setEditable(
bool editable )
397 mCombo->setEditable( editable );
400bool QgsProcessingMapLayerComboBox::isEditable()
const
402 return mCombo->isEditable();
405QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData(
const QMimeData *data,
bool &incompatibleLayerSelected )
const
407 incompatibleLayerSelected =
false;
414 if ( mCombo->mProxyModel->acceptsLayer( layer ) )
418 incompatibleLayerSelected =
true;
427QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData(
const QMimeData *data )
const
434 && u.layerType == QLatin1String(
"vector" ) )
439 bool acceptable =
false;
470 && u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" ) )
473 && u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" ) )
483 if ( u.layerType == QLatin1String(
"vector" ) && u.providerKey == QLatin1String(
"ogr" ) )
509 else if ( u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" )
512 else if ( u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" )
517 if ( !uriList.isEmpty() )
521 QStringList rawPaths;
522 if ( data->hasUrls() )
524 const QList< QUrl > urls = data->urls();
525 rawPaths.reserve( urls.count() );
526 for (
const QUrl &url : urls )
528 const QString local = url.toLocalFile();
529 if ( !rawPaths.contains( local ) )
530 rawPaths.append( local );
533 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
534 rawPaths.append( data->text() );
536 for (
const QString &path : std::as_const( rawPaths ) )
538 QFileInfo file( path );
549void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
551 if ( !( event->possibleActions() & Qt::CopyAction ) )
554 bool incompatibleLayerSelected =
false;
555 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
556 const QString uri = compatibleUriFromMimeData( event->mimeData() );
557 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
560 event->setDropAction( Qt::CopyAction );
563 mCombo->mHighlight =
true;
568void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
570 QWidget::dragLeaveEvent( event );
575 mCombo->mHighlight =
false;
580void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
582 if ( !( event->possibleActions() & Qt::CopyAction ) )
585 bool incompatibleLayerSelected =
false;
586 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
587 const QString uri = compatibleUriFromMimeData( event->mimeData() );
588 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
591 setFocus( Qt::MouseFocusReason );
592 event->setDropAction( Qt::CopyAction );
595 setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
598 mCombo->mHighlight =
false;
602void QgsProcessingMapLayerComboBox::onLayerChanged(
QgsMapLayer *layer )
606 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
608 if (
QgsVectorLayer *prevLayer = qobject_cast< QgsVectorLayer * >( mPrevLayer ) )
612 if ( vl->selectedFeatureCount() == 0 )
613 mUseSelectionCheckBox->setChecked(
false );
614 mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
620 if ( !mBlockChangedSignal )
626 if ( selected.isEmpty() )
627 mUseSelectionCheckBox->setChecked(
false );
628 mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
631void QgsProcessingMapLayerComboBox::showSourceOptions()
635 QgsProcessingFeatureSourceOptionsWidget *widget =
new QgsProcessingFeatureSourceOptionsWidget();
636 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
637 widget->setLayer( qobject_cast< QgsVectorLayer * >( mCombo->currentLayer() ) );
639 widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
640 widget->setFeatureLimit( mFeatureLimit );
641 widget->setFilterExpression( mFilterExpression );
643 panel->openPanel( widget );
647 bool changed =
false;
648 changed = changed | ( widget->featureLimit() != mFeatureLimit );
649 changed = changed | ( widget->filterExpression() != mFilterExpression );
650 changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
651 changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
653 mFeatureLimit = widget->featureLimit();
654 mFilterExpression = widget->filterExpression();
655 mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
656 mGeometryCheck = widget->geometryCheckMethod();
664void QgsProcessingMapLayerComboBox::selectFromFile()
667 const QString initialValue = currentText();
670 if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
672 else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() !=
'.' )
673 path = QFileInfo( initialValue ).path();
674 else if ( settings.
contains( QStringLiteral(
"/Processing/LastInputPath" ) ) )
675 path = settings.
value( QStringLiteral(
"/Processing/LastInputPath" ) ).toString();
679 filter = generator->createFileFilter();
681 filter = QObject::tr(
"All files (*.*)" );
683 const QString filename = QFileDialog::getOpenFileName(
this, tr(
"Select File" ), path, filter );
684 if ( filename.isEmpty() )
687 settings.
setValue( QStringLiteral(
"/Processing/LastInputPath" ), QFileInfo( filename ).path() );
689 setValue( filename, context );
692void QgsProcessingMapLayerComboBox::browseForLayer()
697 widget->
setPanelTitle( tr(
"Browse for \"%1\"" ).arg( mParameter->description() ) );
699 panel->openPanel( widget );
708 if ( widget->
uri().
uri.isEmpty() )
709 setValue( QVariant(), context );
711 setValue( widget->
uri().
uri, context );
The Qgis class provides global constants for use throughout the application.
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
@ 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.
@ CompatibleWithVirtualRaster
The processing provider's algorithms can work with QGIS virtualraster data provider.
@ PointCloudLayer
QgsPointCloudLayer.
@ AbortOnInvalid
Close iterator on encountering any features with invalid geometry. This requires a slow geometry vali...
@ 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.
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.
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.
WidgetType
Types of dialogs which Processing widgets can be created for.
@ Standard
Standard algorithm dialog.
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.
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.
A store for object properties.
Qgis::PropertyType 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.