20 #include "qgssettings.h" 
   29 #include <QHBoxLayout> 
   30 #include <QVBoxLayout> 
   31 #include <QToolButton> 
   33 #include <QDragEnterEvent> 
   36 #include <QFileDialog> 
   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;
 
  152     QList<int> dataTypes;
 
  171   QgsSettings settings;
 
  172   if ( settings.value( QStringLiteral( 
"Processing/Configuration/SHOW_CRS_DEF" ), true ).toBool() )
 
  173     mCombo->setShowCrs( 
true );
 
  176     mCombo->setFilters( filters );
 
  177   mCombo->setExcludedProviders( QStringList() << QStringLiteral( 
"grass" ) ); 
 
  181     mCombo->setAllowEmptyLayer( 
true );
 
  182     mCombo->setLayer( 
nullptr );
 
  186   if ( mUseSelectionCheckBox )
 
  187     connect( mUseSelectionCheckBox, &QCheckBox::toggled, 
this, [ = ]
 
  189     if ( !mBlockChangedSignal )
 
  195   setAcceptDrops( 
true );
 
  197   onLayerChanged( mCombo->currentLayer() );
 
  200 QgsProcessingMapLayerComboBox::~QgsProcessingMapLayerComboBox() = 
default;
 
  202 void QgsProcessingMapLayerComboBox::setLayer( 
QgsMapLayer *layer )
 
  205     mCombo->setLayer( layer );
 
  208 QgsMapLayer *QgsProcessingMapLayerComboBox::currentLayer()
 
  210   return mCombo->currentLayer();
 
  213 QString QgsProcessingMapLayerComboBox::currentText()
 
  215   return mCombo->currentText();
 
  218 void QgsProcessingMapLayerComboBox::setValue( 
const QVariant &value, 
QgsProcessingContext &context )
 
  226   QVariant val = value;
 
  228   bool selectedOnly = 
false;
 
  229   bool iterate = 
false;
 
  235     iterate = fromVar.
flags & QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature;
 
  237     mIsOverridingDefaultGeometryCheck = fromVar.
flags & QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck;
 
  243     mIsOverridingDefaultGeometryCheck = 
false;
 
  259   QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( val.value< QObject * >() );
 
  260   if ( !layer && val.type() == QVariant::String )
 
  267     mBlockChangedSignal++;
 
  270     found = 
static_cast< bool >( currentLayer() );
 
  271     bool changed = found && ( currentLayer() != prevLayer );
 
  272     if ( found && mUseSelectionCheckBox )
 
  274       const bool hasSelection = qobject_cast< QgsVectorLayer * >( layer ) && qobject_cast< QgsVectorLayer * >( layer )->selectedFeatureCount() > 0;
 
  275       changed = changed | ( ( hasSelection && selectedOnly ) != mUseSelectionCheckBox->isChecked() );
 
  278         mUseSelectionCheckBox->setEnabled( 
true );
 
  279         mUseSelectionCheckBox->setChecked( selectedOnly );
 
  283         mUseSelectionCheckBox->setChecked( 
false );
 
  284         mUseSelectionCheckBox->setEnabled( 
false );
 
  287       if ( mIterateButton )
 
  289         mIterateButton->setChecked( iterate );
 
  292     mBlockChangedSignal--;
 
  299     const QString 
string = val.toString();
 
  300     if ( mIterateButton )
 
  301       mIterateButton->setChecked( iterate );
 
  303     if ( !
string.isEmpty() )
 
  305       mBlockChangedSignal++;
 
  306       if ( mCombo->findText( 
string ) < 0 )
 
  308         QStringList additional = mCombo->additionalItems();
 
  309         additional.append( 
string );
 
  310         mCombo->setAdditionalItems( additional );
 
  312       mCombo->setCurrentIndex( mCombo->findText( 
string ) ); 
 
  313       if ( mUseSelectionCheckBox )
 
  315         mUseSelectionCheckBox->setChecked( 
false );
 
  316         mUseSelectionCheckBox->setEnabled( 
false );
 
  318       mBlockChangedSignal--;
 
  319       if ( !mBlockChangedSignal )
 
  324       mCombo->setLayer( 
nullptr );
 
  325       if ( mUseSelectionCheckBox )
 
  327         mUseSelectionCheckBox->setChecked( 
false );
 
  328         mUseSelectionCheckBox->setEnabled( 
false );
 
  334 QVariant QgsProcessingMapLayerComboBox::value()
 const 
  336   if ( isEditable() && mCombo->currentText() != mCombo->itemText( mCombo->currentIndex() ) )
 
  337     return mCombo->currentText();
 
  339   const bool iterate = mIterateButton && mIterateButton->isChecked();
 
  340   const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
 
  343     if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck )
 
  345              ( iterate ? QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature : QgsProcessingFeatureSourceDefinition::Flags() )
 
  346              | ( mIsOverridingDefaultGeometryCheck ? QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck : QgsProcessingFeatureSourceDefinition::Flags() ),
 
  353     if ( !mCombo->currentText().isEmpty() )
 
  355       if ( selectedOnly || iterate || mFeatureLimit != -1 || mIsOverridingDefaultGeometryCheck )
 
  357                ( iterate ? QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature : QgsProcessingFeatureSourceDefinition::Flags() )
 
  358                | ( mIsOverridingDefaultGeometryCheck ? QgsProcessingFeatureSourceDefinition::Flag::FlagOverrideDefaultGeometryCheck : QgsProcessingFeatureSourceDefinition::Flags() ),
 
  361         return mCombo->currentText();
 
  372 void QgsProcessingMapLayerComboBox::setEditable( 
bool editable )
 
  374   mCombo->setEditable( editable );
 
  377 bool QgsProcessingMapLayerComboBox::isEditable()
 const 
  379   return mCombo->isEditable();
 
  382 QgsMapLayer *QgsProcessingMapLayerComboBox::compatibleMapLayerFromMimeData( 
const QMimeData *data, 
bool &incompatibleLayerSelected )
 const 
  384   incompatibleLayerSelected = 
false;
 
  391       if ( mCombo->mProxyModel->acceptsLayer( layer ) )
 
  395         incompatibleLayerSelected = 
true;
 
  404 QString QgsProcessingMapLayerComboBox::compatibleUriFromMimeData( 
const QMimeData *data )
 const 
  411          && u.layerType == QLatin1String( 
"vector" ) )
 
  416       bool acceptable = 
false;
 
  447               && u.layerType == QLatin1String( 
"raster" ) && u.providerKey == QLatin1String( 
"gdal" ) )
 
  450               && u.layerType == QLatin1String( 
"mesh" ) && u.providerKey == QLatin1String( 
"mdal" ) )
 
  460       if ( u.layerType == QLatin1String( 
"vector" ) && u.providerKey == QLatin1String( 
"ogr" ) )
 
  486       else if ( u.layerType == QLatin1String( 
"raster" ) && u.providerKey == QLatin1String( 
"gdal" )
 
  489       else if ( u.layerType == QLatin1String( 
"mesh" ) && u.providerKey == QLatin1String( 
"mdal" )
 
  494   if ( !uriList.isEmpty() )
 
  498   QStringList rawPaths;
 
  499   if ( data->hasUrls() )
 
  501     const QList< QUrl > urls = data->urls();
 
  502     rawPaths.reserve( urls.count() );
 
  503     for ( 
const QUrl &url : urls )
 
  505       const QString local =  url.toLocalFile();
 
  506       if ( !rawPaths.contains( local ) )
 
  507         rawPaths.append( local );
 
  510   if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
 
  511     rawPaths.append( data->text() );
 
  513   for ( 
const QString &path : std::as_const( rawPaths ) )
 
  515     QFileInfo file( path );
 
  526 void QgsProcessingMapLayerComboBox::dragEnterEvent( QDragEnterEvent *event )
 
  528   if ( !( event->possibleActions() & Qt::CopyAction ) )
 
  531   bool incompatibleLayerSelected = 
false;
 
  532   QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
 
  533   const QString uri = compatibleUriFromMimeData( event->mimeData() );
 
  534   if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
 
  537     event->setDropAction( Qt::CopyAction );
 
  540     mCombo->mHighlight = 
true;
 
  545 void QgsProcessingMapLayerComboBox::dragLeaveEvent( QDragLeaveEvent *event )
 
  547   QWidget::dragLeaveEvent( event );
 
  552     mCombo->mHighlight = 
false;
 
  557 void QgsProcessingMapLayerComboBox::dropEvent( QDropEvent *event )
 
  559   if ( !( event->possibleActions() & Qt::CopyAction ) )
 
  562   bool incompatibleLayerSelected = 
false;
 
  563   QgsMapLayer *layer = compatibleMapLayerFromMimeData( event->mimeData(), incompatibleLayerSelected );
 
  564   const QString uri = compatibleUriFromMimeData( event->mimeData() );
 
  565   if ( layer || ( !incompatibleLayerSelected && !uri.isEmpty() ) )
 
  568     setFocus( Qt::MouseFocusReason );
 
  569     event->setDropAction( Qt::CopyAction );
 
  572     setValue( layer ? QVariant::fromValue( layer ) : QVariant::fromValue( uri ), context );
 
  575   mCombo->mHighlight = 
false;
 
  579 void QgsProcessingMapLayerComboBox::onLayerChanged( 
QgsMapLayer *layer )
 
  583     if ( 
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
 
  585       if ( 
QgsVectorLayer *prevLayer = qobject_cast< QgsVectorLayer * >( mPrevLayer ) )
 
  589       if ( vl->selectedFeatureCount() == 0 )
 
  590         mUseSelectionCheckBox->setChecked( 
false );
 
  591       mUseSelectionCheckBox->setEnabled( vl->selectedFeatureCount() > 0 );
 
  597   if ( !mBlockChangedSignal )
 
  603   if ( selected.isEmpty() )
 
  604     mUseSelectionCheckBox->setChecked( 
false );
 
  605   mUseSelectionCheckBox->setEnabled( !selected.isEmpty() );
 
  608 void QgsProcessingMapLayerComboBox::showSourceOptions()
 
  612     QgsProcessingFeatureSourceOptionsWidget *widget = 
new QgsProcessingFeatureSourceOptionsWidget();
 
  613     widget->setPanelTitle( tr( 
"%1 Options" ).arg( mParameter->description() ) );
 
  615     widget->setGeometryCheckMethod( mIsOverridingDefaultGeometryCheck, mGeometryCheck );
 
  616     widget->setFeatureLimit( mFeatureLimit );
 
  618     panel->openPanel( widget );
 
  622       bool changed = 
false;
 
  623       changed = changed | ( widget->featureLimit() != mFeatureLimit );
 
  624       changed = changed | ( widget->isOverridingInvalidGeometryCheck() != mIsOverridingDefaultGeometryCheck );
 
  625       changed = changed | ( widget->geometryCheckMethod() != mGeometryCheck );
 
  627       mFeatureLimit = widget->featureLimit();
 
  628       mIsOverridingDefaultGeometryCheck = widget->isOverridingInvalidGeometryCheck();
 
  629       mGeometryCheck = widget->geometryCheckMethod();
 
  637 void QgsProcessingMapLayerComboBox::selectFromFile()
 
  639   QgsSettings settings;
 
  640   const QString initialValue = currentText();
 
  643   if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
 
  645   else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) && QFileInfo( initialValue ).path() != 
'.' )
 
  646     path = QFileInfo( initialValue ).path();
 
  647   else if ( settings.contains( QStringLiteral( 
"/Processing/LastInputPath" ) ) )
 
  648     path = settings.value( QStringLiteral( 
"/Processing/LastInputPath" ) ).toString();
 
  652     filter = generator->createFileFilter();
 
  654     filter = QObject::tr( 
"All files (*.*)" );
 
  656   const QString filename = QFileDialog::getOpenFileName( 
this, tr( 
"Select File" ), path, filter );
 
  657   if ( filename.isEmpty() )
 
  660   settings.setValue( QStringLiteral( 
"/Processing/LastInputPath" ), QFileInfo( filename ).path() );
 
  662   setValue( filename, context );
 
  665 void QgsProcessingMapLayerComboBox::browseForLayer()
 
  670     widget->
setPanelTitle( tr( 
"Browse for \"%1\"" ).arg( mParameter->description() ) );
 
  672     panel->openPanel( widget );
 
  681       if ( widget->
uri().
uri.isEmpty() )
 
  682         setValue( QVariant(), context );
 
  684         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.
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.
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,...
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 or vector or mesh)
@ TypeVectorPolygon
Vector polygon 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.
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...
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.