17#include "moc_qgsprocessingtoolboxmodel.cpp" 
   27#ifdef ENABLE_MODELTEST 
   37QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
 
   42QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
 
   44  return mChildren.takeAt( mChildren.indexOf( node ) );
 
   47QgsProcessingToolboxModelGroupNode *QgsProcessingToolboxModelNode::getChildGroupNode( 
const QString &groupId )
 
   49  for ( QgsProcessingToolboxModelNode *node : std::as_const( mChildren ) )
 
   51    if ( node->nodeType() == NodeType::Group )
 
   53      QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast<QgsProcessingToolboxModelGroupNode *>( node );
 
   54      if ( groupNode && groupNode->id() == groupId )
 
   61void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
 
   66  Q_ASSERT( !node->mParent );
 
   69  mChildren.append( node );
 
   72void QgsProcessingToolboxModelNode::deleteChildren()
 
   74  qDeleteAll( mChildren );
 
   82QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode( 
QgsProcessingProvider *provider )
 
   83  : mProviderId( provider->id() )
 
   84  , mProvider( provider )
 
   96QgsProcessingToolboxModelGroupNode::QgsProcessingToolboxModelGroupNode( 
const QString &
id, 
const QString &name )
 
  115  : mParamType( paramType )
 
  130  : QAbstractItemModel( parent )
 
  131  , mRegistry( registry ? registry : 
QgsApplication::processingRegistry() )
 
  132  , mRecentLog( recentLog )
 
  133  , mFavoriteManager( favoriteManager )
 
  134  , mRootNode( std::make_unique<QgsProcessingToolboxModelGroupNode>( QString(), QString() ) )
 
  139    connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed, 
this, [
this] { repopulateRecentAlgorithms(); } );
 
  141  if ( mFavoriteManager )
 
  142    connect( mFavoriteManager, &QgsProcessingFavoriteAlgorithmManager::changed, 
this, [
this] { repopulateFavoriteAlgorithms(); } );
 
 
  151void QgsProcessingToolboxModel::rebuild()
 
  155  mRootNode->deleteChildren();
 
  156  mRecentNode = 
nullptr;
 
  157  mFavoriteNode = 
nullptr;
 
  161    auto recentNode = std::make_unique<QgsProcessingToolboxModelRecentNode>();
 
  163    mRecentNode = recentNode.get();
 
  164    mRootNode->addChildNode( recentNode.release() );
 
  165    repopulateRecentAlgorithms( 
true );
 
  168  if ( mFavoriteManager )
 
  170    auto favoriteNode = std::make_unique<QgsProcessingToolboxModelFavoriteNode>();
 
  172    mFavoriteNode = favoriteNode.get();
 
  173    mRootNode->addChildNode( favoriteNode.release() );
 
  174    repopulateFavoriteAlgorithms( 
true );
 
  180    auto groupNode = std::make_unique<QgsProcessingToolboxModelParameterGroupNode>();
 
  185      return QString::localeAwareCompare( a->name(), b->name() ) < 0;
 
  191        auto paramNode = std::make_unique<QgsProcessingToolboxModelParameterNode>( param );
 
  192        groupNode->addChildNode( paramNode.release() );
 
  195    mRootNode->addChildNode( groupNode.release() );
 
  201    const QList<QgsProcessingProvider *> providers = mRegistry->providers();
 
  204      addProvider( provider );
 
  210void QgsProcessingToolboxModel::repopulateRecentAlgorithms( 
bool resetting )
 
  212  if ( !mRecentNode || !mRecentLog )
 
  215  QModelIndex recentIndex = 
index( 0, 0 );
 
  216  const int prevCount = 
rowCount( recentIndex );
 
  217  if ( !resetting && prevCount > 0 )
 
  219    beginRemoveRows( recentIndex, 0, prevCount - 1 );
 
  220    mRecentNode->deleteChildren();
 
  231  const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
 
  232  QList<const QgsProcessingAlgorithm *> recentAlgorithms;
 
  233  recentAlgorithms.reserve( recentAlgIds.count() );
 
  234  for ( 
const QString &
id : recentAlgIds )
 
  241  if ( recentAlgorithms.empty() )
 
  250    beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
 
  255    auto algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>( 
algorithm );
 
  256    mRecentNode->addChildNode( algorithmNode.release() );
 
  266void QgsProcessingToolboxModel::repopulateFavoriteAlgorithms( 
bool resetting )
 
  268  if ( !mFavoriteNode || !mFavoriteManager )
 
  273  int idx = ( mRecentNode && mRecentLog ) ? 1 : 0;
 
  275  QModelIndex favoriteIndex = 
index( idx, 0 );
 
  276  const int prevCount = 
rowCount( favoriteIndex );
 
  277  if ( !resetting && prevCount > 0 )
 
  279    beginRemoveRows( favoriteIndex, 0, prevCount - 1 );
 
  280    mFavoriteNode->deleteChildren();
 
  291  const QStringList favoriteAlgIds = mFavoriteManager->favoriteAlgorithmIds();
 
  292  QList<const QgsProcessingAlgorithm *> favoriteAlgorithms;
 
  293  favoriteAlgorithms.reserve( favoriteAlgIds.count() );
 
  294  for ( 
const QString &
id : favoriteAlgIds )
 
  301  if ( favoriteAlgorithms.empty() )
 
  310    beginInsertRows( favoriteIndex, 0, favoriteAlgorithms.count() - 1 );
 
  315    auto algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>( 
algorithm );
 
  316    mFavoriteNode->addChildNode( algorithmNode.release() );
 
  328  if ( !
index.isValid() )
 
  329    return mRootNode.get();
 
  331  QObject *obj = 
reinterpret_cast<QObject *
>( 
index.internalPointer() );
 
  332  return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
 
 
  337  if ( !node || !node->parent() )
 
  338    return QModelIndex(); 
 
  340  QModelIndex parentIndex = 
node2index( node->parent() );
 
  342  int row = node->parent()->children().indexOf( node );
 
  343  Q_ASSERT( row >= 0 );
 
  344  return index( row, 0, parentIndex );
 
 
  354  QgsProcessingToolboxModelNode *parentNode = 
nullptr;
 
  355  if ( !isTopLevelProvider( provider->
id() ) )
 
  357    auto node = std::make_unique<QgsProcessingToolboxModelProviderNode>( provider );
 
  358    parentNode = node.get();
 
  359    mRootNode->addChildNode( node.release() );
 
  363    parentNode = mRootNode.get();
 
  366  const QList<const QgsProcessingAlgorithm *> algorithms = provider->
algorithms();
 
  369    auto algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>( 
algorithm );
 
  372    if ( !groupId.isEmpty() )
 
  375      QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
 
  380        parentNode->addChildNode( groupNode );
 
  382      groupNode->addChildNode( algorithmNode.release() );
 
  388      parentNode->addChildNode( algorithmNode.release() );
 
  393bool QgsProcessingToolboxModel::isTopLevelProvider( 
const QString &providerId )
 
  395  return providerId == QLatin1String( 
"qgis" ) || providerId == QLatin1String( 
"native" ) || providerId == QLatin1String( 
"3d" ) || providerId == QLatin1String( 
"pdal" );
 
  400  return QStringLiteral( 
"<p><b>%1</b></p>%2<p>%3</p>%4" ).arg( 
algorithm->
displayName(), !
algorithm->
shortDescription().isEmpty() ? QStringLiteral( 
"<p>%1</p>" ).arg( 
algorithm->
shortDescription() ) : QString(), QObject::tr( 
"Algorithm ID: ‘%1’" ).arg( QStringLiteral( 
"<i>%1</i>" ).arg( 
algorithm->id() ) ), ( 
algorithm->
flags() & 
Qgis::ProcessingAlgorithmFlag::KnownIssues ) ? QStringLiteral( 
"<b style=\"color:red\">%1</b>" ).arg( QObject::tr( 
"Warning: Algorithm has known issues" ) ) : QString() );
 
  405  if ( !
index.isValid() )
 
  406    return Qt::ItemFlags();
 
  408  return QAbstractItemModel::flags( 
index );
 
 
  413  if ( !
index.isValid() )
 
  419      return static_cast<int>( node->nodeType() );
 
  424  bool isRecentNode = 
false;
 
  426    isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Recent;
 
  428  bool isFavoriteNode = 
false;
 
  430    isFavoriteNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Favorite;
 
  432  bool isParameterGroupNode = 
false;
 
  434    isParameterGroupNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::ParameterGroup;
 
  437  QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast<QgsProcessingToolboxModelGroupNode *>( 
index2node( 
index ) );
 
  443    case Qt::DisplayRole:
 
  445      switch ( 
index.column() )
 
  449            return provider->
name();
 
  452          else if ( paramType )
 
  453            return paramType->
name();
 
  454          else if ( groupNode )
 
  455            return groupNode->name();
 
  456          else if ( isRecentNode )
 
  457            return tr( 
"Recently used" );
 
  458          else if ( isFavoriteNode )
 
  459            return tr( 
"Favorites" );
 
  460          else if ( isParameterGroupNode )
 
  461            return tr( 
"Input parameters" );
 
  471    case Qt::ToolTipRole:
 
  477      else if ( paramType )
 
  479      else if ( groupNode )
 
  480        return groupNode->name();
 
  481      else if ( isParameterGroupNode )
 
  482        return tr( 
"Input parameters used in the modeler" );
 
  487    case Qt::ForegroundRole:
 
  490        return QBrush( QColor( Qt::red ) );
 
  495    case Qt::DecorationRole:
 
  497      switch ( 
index.column() )
 
  502            return provider->
icon();
 
  509          else if ( paramType )
 
  511          else if ( isRecentNode )
 
  513          else if ( isFavoriteNode )
 
  515          else if ( isParameterGroupNode )
 
  517          else if ( !
index.parent().isValid() )
 
  531      switch ( 
index.column() )
 
  547      switch ( 
index.column() )
 
  552            return static_cast<int>( provider->
flags() );
 
  567      switch ( 
index.column() )
 
  583      switch ( 
index.column() )
 
  599      switch ( 
index.column() )
 
  615      switch ( 
index.column() )
 
  630      switch ( 
index.column() )
 
  635            return paramType->
id();
 
 
  658  return n->children().count();
 
 
  668  if ( !hasIndex( row, column, 
parent ) )
 
  669    return QModelIndex();
 
  673    return QModelIndex(); 
 
  675  return createIndex( row, column, 
static_cast<QObject *
>( n->children().at( row ) ) );
 
 
  680  if ( !child.isValid() )
 
  681    return QModelIndex();
 
  683  if ( QgsProcessingToolboxModelNode *n = 
index2node( child ) )
 
  690    return QModelIndex();
 
 
  696  if ( indexes.isEmpty() )
 
  702    QByteArray encodedData;
 
  703    QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
 
  705    auto mimeData = std::make_unique<QMimeData>();
 
  711    mimeData->setData( QStringLiteral( 
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
 
  716    QByteArray encodedData;
 
  717    QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
 
  719    auto mimeData = std::make_unique<QMimeData>();
 
  723      stream << paramType->
id();
 
  725    mimeData->setData( QStringLiteral( 
"application/x-vnd.qgis.qgis.parametertypeid" ), encodedData );
 
 
  734  if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
 
  737  return qobject_cast<QgsProcessingToolboxModelProviderNode *>( n )->provider();
 
 
  743  if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
 
  746  return qobject_cast<QgsProcessingToolboxModelProviderNode *>( n )->providerId();
 
 
  752  if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Algorithm )
 
  755  return qobject_cast<QgsProcessingToolboxModelAlgorithmNode *>( n )->algorithm();
 
 
  761  return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Algorithm );
 
 
  767  return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Parameter );
 
 
  773  if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Parameter )
 
  776  return qobject_cast<QgsProcessingToolboxModelParameterNode *>( n )->parameterType();
 
 
  781  std::function<QModelIndex( 
const QModelIndex &
parent, 
const QString &providerId )> findIndex = [&]( 
const QModelIndex &
parent, 
const QString &providerId ) -> QModelIndex {
 
  786      if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
 
  789      QModelIndex checkChildren = findIndex( current, providerId );
 
  790      if ( checkChildren.isValid() )
 
  791        return checkChildren;
 
  793    return QModelIndex();
 
  796  return findIndex( QModelIndex(), providerId );
 
 
  801  Q_ASSERT( parentNode );
 
  803  QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
 
  804  if ( !grandParentNode )
 
  805    return QModelIndex(); 
 
  807  int row = grandParentNode->children().indexOf( parentNode );
 
  808  Q_ASSERT( row >= 0 );
 
  810  return createIndex( row, 0, 
static_cast<QObject *
>( parentNode ) );
 
 
  818  : QSortFilterProxyModel( parent )
 
  821  setSourceModel( mModel );
 
  822  setDynamicSortFilter( 
true );
 
  823  setSortLocaleAware( 
true );
 
  824  setFilterCaseSensitivity( Qt::CaseInsensitive );
 
 
  849  mInPlaceLayer = layer;
 
 
  856  mFilterString = filter;
 
 
  862  QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
 
  869    if ( !mFilterString.trimmed().isEmpty() )
 
  876      QStringList parentText;
 
  877      QModelIndex parent = sourceIndex.parent();
 
  878      while ( parent.isValid() )
 
  880        const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split( 
' ' );
 
  881        if ( !parentParts.empty() )
 
  882          parentText.append( parentParts );
 
  883        parent = parent.parent();
 
  886      QStringList partsToSearch;
 
  887      partsToSearch << sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split( 
' ' );
 
  888      partsToSearch << algId << algName;
 
  889      partsToSearch.append( algTags );
 
  890      if ( !shortDesc.isEmpty() )
 
  891        partsToSearch.append( shortDesc.split( 
' ' ) );
 
  892      partsToSearch.append( parentText );
 
  894      const QStringList partsToMatch = mFilterString.trimmed().split( 
' ' );
 
  895      for ( 
const QString &part : partsToMatch )
 
  898        for ( 
const QString &partToSearch : std::as_const( partsToSearch ) )
 
  900          if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
 
  914      if ( !supportsInPlace )
 
  926      return !isHiddenFromModeler;
 
  931      return !isHiddenFromToolbox;
 
  943    if ( !mFilterString.trimmed().isEmpty() )
 
  945      QStringList partsToSearch;
 
  946      partsToSearch << sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split( 
' ' );
 
  949      const QStringList partsToMatch = mFilterString.trimmed().split( 
' ' );
 
  950      for ( 
const QString &part : partsToMatch )
 
  953        for ( 
const QString &partToSearch : std::as_const( partsToSearch ) )
 
  955          if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
 
  968  bool hasChildren = 
false;
 
  970  int count = sourceModel()->rowCount( sourceIndex );
 
  971  for ( 
int i = 0; i < count; ++i )
 
 
  988  if ( leftType == QgsProcessingToolboxModelNode::NodeType::Recent )
 
  990  else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Recent )
 
  992  else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Favorite )
 
  994  else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Favorite )
 
  996  else if ( leftType != rightType )
 
  998    if ( leftType == QgsProcessingToolboxModelNode::NodeType::Provider )
 
 1000    else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Provider )
 
 1002    else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Group )
 
 1009  bool isRecentNode = 
false;
 
 1010  QModelIndex parent = left.parent();
 
 1011  while ( parent.isValid() )
 
 1015      isRecentNode = 
true;
 
 1018    parent = parent.parent();
 
 1022    return left.row() < right.row();
 
 1026  QString leftStr = sourceModel()->data( left ).toString();
 
 1027  QString rightStr = sourceModel()->data( right ).toString();
 
 1028  return QString::localeAwareCompare( leftStr, rightStr ) < 0;
 
 
 1033  if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
 
 1035    QModelIndex sourceIndex = mapToSource( index );
 
 1039      QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
 
 1040      QColor fadedTextColor = brush.color();
 
 1041      fadedTextColor.setAlpha( 100 );
 
 1042      brush.setColor( fadedTextColor );
 
 1046  return QSortFilterProxyModel::data( index, role );
 
 
Provides global constants and enumerations for use throughout the application.
 
@ ExposeToModeler
Is this parameter available in the modeler. Is set to on by default.
 
@ DeemphasiseSearchResults
Algorithms should be de-emphasised in the search results when searching for algorithms....
 
@ HideFromToolbox
Algorithm should be hidden from the toolbox.
 
@ SupportsInPlaceEdits
Algorithm supports in-place editing.
 
@ HideFromModeler
Algorithm should be hidden from the modeler.
 
@ KnownIssues
Algorithm has known issues.
 
Extends QApplication to provide access to QGIS specific resources such as theme paths,...
 
static QgsProcessingRegistry * processingRegistry()
Returns the application's processing registry, used for managing processing providers,...
 
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
 
Abstract base class for processing algorithms.
 
virtual QString group() const
Returns the name of the group this algorithm belongs to.
 
virtual QString groupId() const
Returns the unique ID of the group this algorithm belongs to.
 
virtual QIcon icon() const
Returns an icon for the algorithm.
 
virtual QString shortDescription() const
Returns an optional translated short description of the algorithm.
 
QString id() const
Returns the unique ID for the algorithm, which is a combination of the algorithm provider's ID and th...
 
virtual QString displayName() const =0
Returns the translated algorithm name, which should be used for any user-visible display of the algor...
 
virtual QStringList tags() const
Returns a list of tags which relate to the algorithm, and are used to assist users in searching for s...
 
QgsProcessingProvider * provider() const
Returns the provider to which this algorithm belongs.
 
virtual bool supportInPlaceEdit(const QgsMapLayer *layer) const
Checks whether this algorithm supports in-place editing on the given layer Default implementation ret...
 
virtual QString name() const =0
Returns the algorithm name, used for identifying the algorithm.
 
Qgis::ProcessingAlgorithmFlags flags() const override
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
 
Makes metadata of processing parameters available.
 
virtual QString name() const =0
A human readable and translatable short name for this parameter type.
 
virtual QString description() const =0
A human readable and translatable description for this parameter type.
 
virtual QString id() const =0
A static id for this type which will be used for storing this parameter type.
 
Abstract base class for processing providers.
 
virtual QIcon icon() const
Returns an icon for the provider.
 
virtual Qgis::ProcessingProviderFlags flags() const
Returns the flags indicating how and when the provider operates and should be exposed to users.
 
virtual QString name() const =0
Returns the provider name, which is used to describe the provider within the GUI.
 
void algorithmsLoaded()
Emitted when the provider has loaded (or refreshed) its list of available algorithms.
 
virtual QString id() const =0
Returns the unique provider id, used for identifying the provider.
 
virtual QString longName() const
Returns the longer version of the provider name, which can include extra details such as version numb...
 
QList< const QgsProcessingAlgorithm * > algorithms() const
Returns a list of algorithms supplied by this provider.
 
Registry for various processing components, including providers, algorithms and various parameters an...
 
void parameterTypeAdded(QgsProcessingParameterType *type)
Emitted when a new parameter type has been added to the registry.
 
void parameterTypeRemoved(QgsProcessingParameterType *type)
Emitted when a parameter type has been removed from the registry and is about to be deleted.
 
void providerAdded(const QString &id)
Emitted when a provider has been added to the registry.
 
QList< QgsProcessingParameterType * > parameterTypes() const
Returns a list with all known parameter types.
 
void providerRemoved(const QString &id)
Emitted when a provider is removed from the registry.
 
Represents a vector layer which manages a vector based dataset.
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call