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, [
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 );
 
Provides global constants and enumerations 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.
 
ProcessingMode
Types of modes which Processing widgets can be created for.
 
@ Standard
Standard (single-run) algorithm mode.
 
@ 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.
 
A combobox which displays a dynamic list of layers from a QGIS project.
 
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.
 
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.
 
Stores settings for use within QGIS.
 
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 dataset.
 
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.