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;
188 if ( settings.
value( QStringLiteral(
"Processing/Configuration/SHOW_CRS_DEF" ), true ).toBool() )
189 mCombo->setShowCrs(
true );
192 mCombo->setFilters( filters );
198 mCombo->setExcludedProviders( mCombo->excludedProviders() << QStringLiteral(
"virtualraster" ) );
203 mCombo->setAllowEmptyLayer(
true );
204 mCombo->setLayer(
nullptr );
208 if ( mUseSelectionCheckBox )
209 connect( mUseSelectionCheckBox, &QCheckBox::toggled,
this, [=] {
210 if ( !mBlockChangedSignal )
216 setAcceptDrops(
true );
218 onLayerChanged( mCombo->currentLayer() );
221QgsProcessingMapLayerComboBox::~QgsProcessingMapLayerComboBox() =
default;
223void QgsProcessingMapLayerComboBox::setLayer(
QgsMapLayer *layer )
227 mCombo->setLayer( layer );
231QgsMapLayer *QgsProcessingMapLayerComboBox::currentLayer()
233 return mCombo->currentLayer();
236QString QgsProcessingMapLayerComboBox::currentText()
238 return mCombo->currentText();
241void QgsProcessingMapLayerComboBox::setValue(
const QVariant &value,
QgsProcessingContext &context )
249 QVariant val = value;
251 bool selectedOnly =
false;
252 bool iterate =
false;
253 if ( val.userType() == qMetaTypeId<QgsProcessingFeatureSourceDefinition>() )
267 mFilterExpression.clear();
268 mIsOverridingDefaultGeometryCheck =
false;
272 if ( val.userType() == qMetaTypeId<QgsProperty>() )
284 QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( val.value<QObject *>() );
285 if ( !layer && val.userType() == QMetaType::Type::QString )
292 mBlockChangedSignal++;
295 found =
static_cast<bool>( currentLayer() );
296 bool changed = found && ( currentLayer() != prevLayer );
297 if ( found && mUseSelectionCheckBox )
299 const bool hasSelection = qobject_cast<QgsVectorLayer *>( layer ) && qobject_cast<QgsVectorLayer *>( layer )->selectedFeatureCount() > 0;
300 changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
303 mUseSelectionCheckBox->setEnabled(
true );
304 mUseSelectionCheckBox->setChecked( selectedOnly );
308 mUseSelectionCheckBox->setChecked(
false );
309 mUseSelectionCheckBox->setEnabled(
false );
312 if ( mIterateButton )
314 mIterateButton->setChecked( iterate );
317 mBlockChangedSignal--;
324 const QString
string = val.toString();
325 if ( mIterateButton )
326 mIterateButton->setChecked( iterate );
328 if ( !
string.isEmpty() )
330 mBlockChangedSignal++;
331 if ( mCombo->findText(
string ) < 0 )
333 QStringList additional = mCombo->additionalItems();
334 additional.append(
string );
335 mCombo->setAdditionalItems( additional );
337 mCombo->setCurrentIndex( mCombo->findText(
string ) );
338 if ( mUseSelectionCheckBox )
340 mUseSelectionCheckBox->setChecked(
false );
341 mUseSelectionCheckBox->setEnabled(
false );
343 mBlockChangedSignal--;
344 if ( !mBlockChangedSignal )
349 mCombo->setLayer(
nullptr );
350 if ( mUseSelectionCheckBox )
352 mUseSelectionCheckBox->setChecked(
false );
353 mUseSelectionCheckBox->setEnabled(
false );
359QVariant QgsProcessingMapLayerComboBox::value()
const
361 if ( isEditable() && mCombo->currentText() != mCombo->itemText( mCombo->currentIndex() ) )
362 return mCombo->currentText();
364 const bool iterate = mIterateButton && mIterateButton->isChecked();
365 const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
368 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
375 if ( !mCombo->currentText().isEmpty() )
377 if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck || !mFilterExpression.isEmpty() )
380 return mCombo->currentText();
389 mCombo->setProject( context.
project() );
392void QgsProcessingMapLayerComboBox::setEditable(
bool editable )
394 mCombo->setEditable( editable );
397bool QgsProcessingMapLayerComboBox::isEditable()
const
399 return mCombo->isEditable();
402QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData(
const QMimeData *data,
bool &incompatibleLayerSelected )
const
404 incompatibleLayerSelected =
false;
411 if ( mCombo->mProxyModel->acceptsLayer( layer ) )
415 incompatibleLayerSelected =
true;
424QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData(
const QMimeData *data )
const
431 && u.layerType == QLatin1String(
"vector" ) )
436 bool acceptable =
false;
467 && u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" ) )
470 && u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" ) )
480 if ( u.layerType == QLatin1String(
"vector" ) && u.providerKey == QLatin1String(
"ogr" ) )
506 else if ( u.layerType == QLatin1String(
"raster" ) && u.providerKey == QLatin1String(
"gdal" )
509 else if ( u.layerType == QLatin1String(
"mesh" ) && u.providerKey == QLatin1String(
"mdal" )
514 if ( !uriList.isEmpty() )
518 QStringList rawPaths;
519 if ( data->hasUrls() )
521 const QList<QUrl> urls = data->urls();
522 rawPaths.reserve( urls.count() );
523 for (
const QUrl &url : urls )
525 const QString local = url.toLocalFile();
526 if ( !rawPaths.contains( local ) )
527 rawPaths.append( local );
530 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
531 rawPaths.append( data->text() );
533 for (
const QString &path : std::as_const( rawPaths ) )
535 QFileInfo file( path );
546void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
548 if ( !( event->possibleActions() & Qt::CopyAction ) )
551 bool incompatibleLayerSelected =
false;
552 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
553 const QString uri = compatibleUriFromMimeData( event->mimeData() );
554 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
557 event->setDropAction( Qt::CopyAction );
560 mCombo->mHighlight =
true;
565void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
567 QWidget::dragLeaveEvent( event );
572 mCombo->mHighlight =
false;
577void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
579 if ( !( event->possibleActions() & Qt::CopyAction ) )
582 bool incompatibleLayerSelected =
false;
583 QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
584 const QString uri = compatibleUriFromMimeData( event->mimeData() );
585 if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
588 setFocus( Qt::MouseFocusReason );
589 event->setDropAction( Qt::CopyAction );
592 setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
595 mCombo->mHighlight =
false;
599void QgsProcessingMapLayerComboBox::onLayerChanged(
QgsMapLayer *layer )
603 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
605 if (
QgsVectorLayer *prevLayer = qobject_cast<QgsVectorLayer *>( mPrevLayer ) )
609 if ( vl->selectedFeatureCount() == 0 )
610 mUseSelectionCheckBox->setChecked(
false );
611 mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
617 if ( !mBlockChangedSignal )
623 if ( selected.isEmpty() )
624 mUseSelectionCheckBox->setChecked(
false );
625 mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
628void QgsProcessingMapLayerComboBox::showSourceOptions()
632 QgsProcessingFeatureSourceOptionsWidget *widget =
new QgsProcessingFeatureSourceOptionsWidget();
633 widget->setPanelTitle( tr(
"%1 Options" ).arg( mParameter->description() ) );
634 widget->setLayer( qobject_cast<QgsVectorLayer *>( mCombo->currentLayer() ) );
636 widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
637 widget->setFeatureLimit( mFeatureLimit );
638 widget->setFilterExpression( mFilterExpression );
640 panel->openPanel( widget );
643 bool changed =
false;
644 changed = changed | ( widget->featureLimit() != mFeatureLimit );
645 changed = changed | ( widget->filterExpression() != mFilterExpression );
646 changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
647 changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
649 mFeatureLimit = widget->featureLimit();
650 mFilterExpression = widget->filterExpression();
651 mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
652 mGeometryCheck = widget->geometryCheckMethod();
660void QgsProcessingMapLayerComboBox::selectFromFile()
663 const QString initialValue = currentText();
666 if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
668 else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() !=
'.' )
669 path = QFileInfo( initialValue ).path();
670 else if ( settings.
contains( QStringLiteral(
"/Processing/LastInputPath" ) ) )
671 path = settings.
value( QStringLiteral(
"/Processing/LastInputPath" ) ).toString();
675 filter = generator->createFileFilter();
677 filter = QObject::tr(
"All files (*.*)" );
679 const QString filename = QFileDialog::getOpenFileName(
this, tr(
"Select File" ), path, filter );
680 if ( filename.isEmpty() )
683 settings.
setValue( QStringLiteral(
"/Processing/LastInputPath" ), QFileInfo( filename ).path() );
685 setValue( filename, context );
688void QgsProcessingMapLayerComboBox::browseForLayer()
693 widget->
setPanelTitle( tr(
"Browse for \"%1\"" ).arg( mParameter->description() ) );
695 panel->openPanel( widget );
702 if ( widget->
uri().
uri.isEmpty() )
703 setValue( QVariant(), context );
705 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.