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 ) );
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 ) );
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 QgsMapLayerProxyModel::Filters filters = QgsMapLayerProxyModel::Filters();
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" ) )
241 iterate = fromVar.
flags & QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature;
243 mIsOverridingDefaultGeometryCheck = fromVar.
flags & QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck;
249 mIsOverridingDefaultGeometryCheck =
false;
253 if ( val.userType() == QMetaType::type(
"QgsProperty" ) )
265 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( val.value< QObject * >() );
266 if ( !layer && val.type() == QVariant::String )
273 mBlockChangedSignal++;
276 found =
static_cast< bool >( currentLayer() );
277 bool changed = found && ( currentLayer() != prevLayer );
278 if ( found && mUseSelectionCheckBox )
280 const bool hasSelection = qobject_cast< QgsVectorLayer * >( layer ) && qobject_cast< QgsVectorLayer * >( layer )->selectedFeatureCount() > 0;
281 changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
284 mUseSelectionCheckBox->setEnabled(
true );
285 mUseSelectionCheckBox->setChecked( selectedOnly );
289 mUseSelectionCheckBox->setChecked(
false );
290 mUseSelectionCheckBox->setEnabled(
false );
293 if ( mIterateButton )
295 mIterateButton->setChecked( iterate );
298 mBlockChangedSignal--;
305 const QString
string = val.toString();
306 if ( mIterateButton )
307 mIterateButton->setChecked( iterate );
309 if ( !
string.isEmpty() )
311 mBlockChangedSignal++;
312 if ( mCombo->findText(
string ) < 0 )
314 QStringList additional = mCombo->additionalItems();
315 additional.append(
string );
316 mCombo->setAdditionalItems( additional );
318 mCombo->setCurrentIndex( mCombo->findText(
string ) );
319 if ( mUseSelectionCheckBox )
321 mUseSelectionCheckBox->setChecked(
false );
322 mUseSelectionCheckBox->setEnabled(
false );
324 mBlockChangedSignal--;
325 if ( !mBlockChangedSignal )
330 mCombo->setLayer(
nullptr );
331 if ( mUseSelectionCheckBox )
333 mUseSelectionCheckBox->setChecked(
false );
334 mUseSelectionCheckBox->setEnabled(
false );
340QVariant QgsProcessingMapLayerComboBox::value()
const
342 if ( isEditable() && mCombo->currentText() != mCombo->itemText( mCombo->currentIndex() ) )
343 return mCombo->currentText();
345 const bool iterate = mIterateButton && mIterateButton->isChecked();
346 const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
349 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck )
351 ( iterate ? QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature : QgsProcessingFeatureSourceDefinition::Flags() )
352 | ( mIsOverridingDefaultGeometryCheck ? QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck : QgsProcessingFeatureSourceDefinition::Flags() ),
359 if ( !mCombo->currentText().isEmpty() )
361 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck )
363 ( iterate ? QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature : QgsProcessingFeatureSourceDefinition::Flags() )
364 | ( mIsOverridingDefaultGeometryCheck ? QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck : QgsProcessingFeatureSourceDefinition::Flags() ),
367 return mCombo->currentText();
376 mCombo->setProject( context.
project() );
379void QgsProcessingMapLayerComboBox::setEditable(
bool editable )
381 mCombo->setEditable( editable );
384bool QgsProcessingMapLayerComboBox::isEditable()
const
386 return mCombo->isEditable();
389QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData(
const QMimeData *data,
bool &incompatibleLayerSelected )
const
391 incompatibleLayerSelected =
false;
398 if ( mCombo->mProxyModel->acceptsLayer( layer ) )
402 incompatibleLayerSelected =
true;
411QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData(
const QMimeData *data )
const
418 && u.layerType == QLatin1String(
"vector" ) )
423 bool acceptable =
false;
454 && u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" ) )
457 && u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" ) )
467 if ( u.layerType == QLatin1String(
"vector" ) && u.providerKey == QLatin1String(
"ogr" ) )
493 else if ( u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" )
496 else if ( u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" )
501 if ( !uriList.isEmpty() )
505 QStringList rawPaths;
506 if ( data->hasUrls() )
508 const QList< QUrl > urls = data->urls();
509 rawPaths.reserve( urls.count() );
510 for (
const QUrl &url : urls )
512 const QString local = url.toLocalFile();
513 if ( !rawPaths.contains( local ) )
514 rawPaths.append( local );
517 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
518 rawPaths.append( data->text() );
520 for (
const QString &path : std::as_const( rawPaths ) )
522 QFileInfo file( path );
533void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
535 if ( !( event->possibleActions() & Qt::CopyAction ) )
538 bool incompatibleLayerSelected =
false;
539 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
540 const QString uri = compatibleUriFromMimeData( event->mimeData() );
541 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
544 event->setDropAction( Qt::CopyAction );
547 mCombo->mHighlight =
true;
552void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
554 QWidget::dragLeaveEvent( event );
559 mCombo->mHighlight =
false;
564void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
566 if ( !( event->possibleActions() & Qt::CopyAction ) )
569 bool incompatibleLayerSelected =
false;
570 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
571 const QString uri = compatibleUriFromMimeData( event->mimeData() );
572 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
575 setFocus( Qt::MouseFocusReason );
576 event->setDropAction( Qt::CopyAction );
579 setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
582 mCombo->mHighlight =
false;
586void QgsProcessingMapLayerComboBox::onLayerChanged(
QgsMapLayer *layer )
590 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
592 if (
QgsVectorLayer *prevLayer = qobject_cast< QgsVectorLayer * >( mPrevLayer ) )
596 if ( vl->selectedFeatureCount() == 0 )
597 mUseSelectionCheckBox->setChecked(
false );
598 mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
604 if ( !mBlockChangedSignal )
610 if ( selected.isEmpty() )
611 mUseSelectionCheckBox->setChecked(
false );
612 mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
615void QgsProcessingMapLayerComboBox::showSourceOptions()
619 QgsProcessingFeatureSourceOptionsWidget *widget =
new QgsProcessingFeatureSourceOptionsWidget();
620 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
622 widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
623 widget->setFeatureLimit( mFeatureLimit );
625 panel->openPanel( widget );
629 bool changed =
false;
630 changed = changed | ( widget->featureLimit() != mFeatureLimit );
631 changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
632 changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
634 mFeatureLimit = widget->featureLimit();
635 mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
636 mGeometryCheck = widget->geometryCheckMethod();
644void QgsProcessingMapLayerComboBox::selectFromFile()
647 const QString initialValue = currentText();
650 if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
652 else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() !=
'.' )
653 path = QFileInfo( initialValue ).path();
654 else if ( settings.
contains( QStringLiteral(
"/Processing/LastInputPath" ) ) )
655 path = settings.
value( QStringLiteral(
"/Processing/LastInputPath" ) ).toString();
659 filter = generator->createFileFilter();
661 filter = QObject::tr(
"All files (*.*)" );
663 const QString filename = QFileDialog::getOpenFileName(
this, tr(
"Select File" ), path, filter );
664 if ( filename.isEmpty() )
667 settings.
setValue( QStringLiteral(
"/Processing/LastInputPath" ), QFileInfo( filename ).path() );
669 setValue( filename, context );
672void QgsProcessingMapLayerComboBox::browseForLayer()
677 widget->
setPanelTitle( tr(
"Browse for \"%1\"" ).arg( mParameter->description() ) );
679 panel->openPanel( widget );
688 if ( widget->
uri().
uri.isEmpty() )
689 setValue( QVariant(), context );
691 setValue( widget->
uri().
uri, context );
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.
@ PointCloudLayer
QgsPointCloudLayer.
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...
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)
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 GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
@ VectorLayer
Vector layer.
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.