17#include "moc_qgsprocessingmaplayercombobox.cpp"
35#include <QDragEnterEvent>
45 , mParameter( parameter->clone() )
47 QHBoxLayout *layout =
new QHBoxLayout();
48 layout->setContentsMargins( 0, 0, 0, 0 );
49 layout->setSpacing( 6 );
52 layout->addWidget( mCombo );
53 layout->setAlignment( mCombo, Qt::AlignTop );
58 mIterateButton =
new QToolButton();
60 mIterateButton->setToolTip( tr(
"Iterate over this layer, creating a separate output for every feature in the layer" ) );
61 mIterateButton->setCheckable(
true );
62 mIterateButton->setAutoRaise(
true );
65 mIterateButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
66 mIterateButton->setIconSize( QSize( iconSize, iconSize ) );
68 layout->addWidget( mIterateButton );
69 layout->setAlignment( mIterateButton, Qt::AlignTop );
74 mSettingsButton =
new QToolButton();
76 mSettingsButton->setToolTip( tr(
"Advanced options" ) );
79 mSettingsButton->setFixedSize( 2 *
static_cast<int>( 1.25 * iconSize / 2.0 ), 2 *
static_cast<int>( iconSize * 1.1 / 2.0 ) );
80 mSettingsButton->setIconSize( QSize( iconSize, iconSize ) );
81 mSettingsButton->setAutoRaise(
true );
83 connect( mSettingsButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::showSourceOptions );
84 layout->addWidget( mSettingsButton );
85 layout->setAlignment( mSettingsButton, Qt::AlignTop );
88 mSelectButton =
new QToolButton();
89 mSelectButton->setText( QString( QChar( 0x2026 ) ) );
90 mSelectButton->setToolTip( tr(
"Select input" ) );
91 layout->addWidget( mSelectButton );
92 layout->setAlignment( mSelectButton, Qt::AlignTop );
95 mFeatureSourceMenu =
new QMenu(
this );
96 QAction *selectFromFileAction =
new QAction( tr(
"Select File…" ), mFeatureSourceMenu );
97 connect( selectFromFileAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
98 mFeatureSourceMenu->addAction( selectFromFileAction );
99 QAction *browseForLayerAction =
new QAction( tr(
"Browse for Layer…" ), mFeatureSourceMenu );
100 connect( browseForLayerAction, &QAction::triggered,
this, &QgsProcessingMapLayerComboBox::browseForLayer );
101 mFeatureSourceMenu->addAction( browseForLayerAction );
102 mSelectButton->setMenu( mFeatureSourceMenu );
103 mSelectButton->setPopupMode( QToolButton::InstantPopup );
107 connect( mSelectButton, &QToolButton::clicked,
this, &QgsProcessingMapLayerComboBox::selectFromFile );
110 QVBoxLayout *vl =
new QVBoxLayout();
111 vl->setContentsMargins( 0, 0, 0, 0 );
113 vl->addLayout( layout );
119 mUseSelectionCheckBox =
new QCheckBox( tr(
"Selected features only" ) );
120 mUseSelectionCheckBox->setChecked(
false );
121 mUseSelectionCheckBox->setEnabled(
false );
122 vl->addWidget( mUseSelectionCheckBox );
125 bool mayBeRaster {
false };
129 QList<int> dataTypes;
161 QList<int> dataTypes;
186 if ( settings.
value( QStringLiteral(
"Processing/Configuration/SHOW_CRS_DEF" ), true ).toBool() )
187 mCombo->setShowCrs(
true );
190 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, [=] {
208 if ( !mBlockChangedSignal )
214 setAcceptDrops(
true );
216 onLayerChanged( mCombo->currentLayer() );
219QgsProcessingMapLayerComboBox::~QgsProcessingMapLayerComboBox() =
default;
221void QgsProcessingMapLayerComboBox::setLayer(
QgsMapLayer *layer )
224 mCombo->setLayer( layer );
227QgsMapLayer *QgsProcessingMapLayerComboBox::currentLayer()
229 return mCombo->currentLayer();
232QString QgsProcessingMapLayerComboBox::currentText()
234 return mCombo->currentText();
237void QgsProcessingMapLayerComboBox::setValue(
const QVariant &value,
QgsProcessingContext &context )
245 QVariant val = value;
247 bool selectedOnly =
false;
248 bool iterate =
false;
249 if ( val.userType() == qMetaTypeId<QgsProcessingFeatureSourceDefinition>() )
263 mFilterExpression.clear();
264 mIsOverridingDefaultGeometryCheck =
false;
268 if ( val.userType() == qMetaTypeId<QgsProperty>() )
280 QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( val.value<QObject *>() );
281 if ( !layer && val.userType() == QMetaType::Type::QString )
288 mBlockChangedSignal++;
291 found =
static_cast<bool>( currentLayer() );
292 bool changed = found && ( currentLayer() != prevLayer );
293 if ( found && mUseSelectionCheckBox )
295 const bool hasSelection = qobject_cast<QgsVectorLayer *>( layer ) && qobject_cast<QgsVectorLayer *>( layer )->selectedFeatureCount() > 0;
296 changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
299 mUseSelectionCheckBox->setEnabled(
true );
300 mUseSelectionCheckBox->setChecked( selectedOnly );
304 mUseSelectionCheckBox->setChecked(
false );
305 mUseSelectionCheckBox->setEnabled(
false );
308 if ( mIterateButton )
310 mIterateButton->setChecked( iterate );
313 mBlockChangedSignal--;
320 const QString
string = val.toString();
321 if ( mIterateButton )
322 mIterateButton->setChecked( iterate );
324 if ( !
string.isEmpty() )
326 mBlockChangedSignal++;
327 if ( mCombo->findText(
string ) < 0 )
329 QStringList additional = mCombo->additionalItems();
330 additional.append(
string );
331 mCombo->setAdditionalItems( additional );
333 mCombo->setCurrentIndex( mCombo->findText(
string ) );
334 if ( mUseSelectionCheckBox )
336 mUseSelectionCheckBox->setChecked(
false );
337 mUseSelectionCheckBox->setEnabled(
false );
339 mBlockChangedSignal--;
340 if ( !mBlockChangedSignal )
345 mCombo->setLayer(
nullptr );
346 if ( mUseSelectionCheckBox )
348 mUseSelectionCheckBox->setChecked(
false );
349 mUseSelectionCheckBox->setEnabled(
false );
355QVariant QgsProcessingMapLayerComboBox::value()
const
357 if ( isEditable() && mCombo->currentText() != mCombo->itemText( mCombo->currentIndex() ) )
358 return mCombo->currentText();
360 const bool iterate = mIterateButton && mIterateButton->isChecked();
361 const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
364 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
371 if ( !mCombo->currentText().isEmpty() )
373 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
376 return mCombo->currentText();
385 mCombo->setProject( context.
project() );
388void QgsProcessingMapLayerComboBox::setEditable(
bool editable )
390 mCombo->setEditable( editable );
393bool QgsProcessingMapLayerComboBox::isEditable()
const
395 return mCombo->isEditable();
398QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData(
const QMimeData *data,
bool &incompatibleLayerSelected )
const
400 incompatibleLayerSelected =
false;
407 if ( mCombo->mProxyModel->acceptsLayer( layer ) )
411 incompatibleLayerSelected =
true;
420QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData(
const QMimeData *data )
const
427 && u.layerType == QLatin1String(
"vector" ) )
432 bool acceptable =
false;
463 && u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" ) )
466 && u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" ) )
476 if ( u.layerType == QLatin1String(
"vector" ) && u.providerKey == QLatin1String(
"ogr" ) )
502 else if ( u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" )
505 else if ( u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" )
510 if ( !uriList.isEmpty() )
514 QStringList rawPaths;
515 if ( data->hasUrls() )
517 const QList<QUrl> urls = data->urls();
518 rawPaths.reserve( urls.count() );
519 for (
const QUrl &url : urls )
521 const QString local = url.toLocalFile();
522 if ( !rawPaths.contains( local ) )
523 rawPaths.append( local );
526 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
527 rawPaths.append( data->text() );
529 for (
const QString &path : std::as_const( rawPaths ) )
531 QFileInfo file( path );
542void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
544 if ( !( event->possibleActions() & Qt::CopyAction ) )
547 bool incompatibleLayerSelected =
false;
548 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
549 const QString uri = compatibleUriFromMimeData( event->mimeData() );
550 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
553 event->setDropAction( Qt::CopyAction );
556 mCombo->mHighlight =
true;
561void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
563 QWidget::dragLeaveEvent( event );
568 mCombo->mHighlight =
false;
573void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
575 if ( !( event->possibleActions() & Qt::CopyAction ) )
578 bool incompatibleLayerSelected =
false;
579 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
580 const QString uri = compatibleUriFromMimeData( event->mimeData() );
581 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
584 setFocus( Qt::MouseFocusReason );
585 event->setDropAction( Qt::CopyAction );
588 setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
591 mCombo->mHighlight =
false;
595void QgsProcessingMapLayerComboBox::onLayerChanged(
QgsMapLayer *layer )
599 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
601 if (
QgsVectorLayer *prevLayer = qobject_cast<QgsVectorLayer *>( mPrevLayer ) )
605 if ( vl->selectedFeatureCount() == 0 )
606 mUseSelectionCheckBox->setChecked(
false );
607 mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
613 if ( !mBlockChangedSignal )
619 if ( selected.isEmpty() )
620 mUseSelectionCheckBox->setChecked(
false );
621 mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
624void QgsProcessingMapLayerComboBox::showSourceOptions()
628 QgsProcessingFeatureSourceOptionsWidget *widget =
new QgsProcessingFeatureSourceOptionsWidget();
629 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
630 widget->setLayer( qobject_cast<QgsVectorLayer *>( mCombo->currentLayer() ) );
632 widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
633 widget->setFeatureLimit( mFeatureLimit );
634 widget->setFilterExpression( mFilterExpression );
636 panel->openPanel( widget );
639 bool changed =
false;
640 changed = changed | ( widget->featureLimit() != mFeatureLimit );
641 changed = changed | ( widget->filterExpression() != mFilterExpression );
642 changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
643 changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
645 mFeatureLimit = widget->featureLimit();
646 mFilterExpression = widget->filterExpression();
647 mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
648 mGeometryCheck = widget->geometryCheckMethod();
656void QgsProcessingMapLayerComboBox::selectFromFile()
659 const QString initialValue = currentText();
662 if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
664 else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() !=
'.' )
665 path = QFileInfo( initialValue ).path();
666 else if ( settings.
contains( QStringLiteral(
"/Processing/LastInputPath" ) ) )
667 path = settings.
value( QStringLiteral(
"/Processing/LastInputPath" ) ).toString();
671 filter = generator->createFileFilter();
673 filter = QObject::tr(
"All files (*.*)" );
675 const QString filename = QFileDialog::getOpenFileName(
this, tr(
"Select File" ), path, filter );
676 if ( filename.isEmpty() )
679 settings.
setValue( QStringLiteral(
"/Processing/LastInputPath" ), QFileInfo( filename ).path() );
681 setValue( filename, context );
684void QgsProcessingMapLayerComboBox::browseForLayer()
689 widget->
setPanelTitle( tr(
"Browse for \"%1\"" ).arg( mParameter->description() ) );
691 panel->openPanel( widget );
698 if ( widget->
uri().
uri.isEmpty() )
699 setValue( QVariant(), context );
701 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.