25 #ifdef ENABLE_MODELTEST 
   26 #include "modeltest.h" 
   35 QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
 
   40 QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
 
   42   return mChildren.takeAt( mChildren.indexOf( node ) );
 
   45 QgsProcessingToolboxModelGroupNode *QgsProcessingToolboxModelNode::getChildGroupNode( 
const QString &groupId )
 
   47   for ( QgsProcessingToolboxModelNode *node : std::as_const( mChildren ) )
 
   49     if ( node->nodeType() == NodeGroup )
 
   51       QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >( node );
 
   52       if ( groupNode && groupNode->id() == groupId )
 
   59 void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
 
   64   Q_ASSERT( !node->mParent );
 
   67   mChildren.append( node );
 
   70 void QgsProcessingToolboxModelNode::deleteChildren()
 
   72   qDeleteAll( mChildren );
 
   80 QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode( 
QgsProcessingProvider *provider )
 
   81   : mProviderId( provider->id() )
 
   82   , mProvider( provider )
 
   94 QgsProcessingToolboxModelGroupNode::QgsProcessingToolboxModelGroupNode( 
const QString &
id, 
const QString &name )
 
  119   : QAbstractItemModel( parent )
 
  120   , mRegistry( registry ? registry : 
QgsApplication::processingRegistry() )
 
  121   , mRecentLog( recentLog )
 
  122   , mRootNode( std::make_unique< QgsProcessingToolboxModelGroupNode >( QString(), QString() ) )
 
  127     connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed, 
this, [ = ] { repopulateRecentAlgorithms(); } );
 
  133 void QgsProcessingToolboxModel::rebuild()
 
  137   mRootNode->deleteChildren();
 
  138   mRecentNode = 
nullptr;
 
  142     std::unique_ptr< QgsProcessingToolboxModelRecentNode > recentNode = std::make_unique< QgsProcessingToolboxModelRecentNode >();
 
  143     mRecentNode = recentNode.get();
 
  144     mRootNode->addChildNode( recentNode.release() );
 
  145     repopulateRecentAlgorithms( 
true );
 
  150     const QList< QgsProcessingProvider * > providers = mRegistry->providers();
 
  153       addProvider( provider );
 
  159 void QgsProcessingToolboxModel::repopulateRecentAlgorithms( 
bool resetting )
 
  161   if ( !mRecentNode || !mRecentLog )
 
  164   QModelIndex recentIndex = 
index( 0, 0 );
 
  165   const int prevCount = 
rowCount( recentIndex );
 
  166   if ( !resetting && prevCount > 0 )
 
  168     beginRemoveRows( recentIndex, 0, prevCount - 1 );
 
  169     mRecentNode->deleteChildren();
 
  180   const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
 
  181   QList< const QgsProcessingAlgorithm * > recentAlgorithms;
 
  182   recentAlgorithms.reserve( recentAlgIds.count() );
 
  183   for ( 
const QString &
id : recentAlgIds )
 
  190   if ( recentAlgorithms.empty() )
 
  199     beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
 
  204     std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = std::make_unique< QgsProcessingToolboxModelAlgorithmNode >( 
algorithm );
 
  205     mRecentNode->addChildNode( algorithmNode.release() );
 
  215 void QgsProcessingToolboxModel::providerAdded( 
const QString &
id )
 
  224   if ( !isTopLevelProvider( 
id ) )
 
  227     beginInsertRows( QModelIndex(), previousRowCount, previousRowCount );
 
  228     addProvider( provider );
 
  236     addProvider( provider );
 
  241 void QgsProcessingToolboxModel::providerRemoved( 
const QString & )
 
  250   if ( !
index.isValid() )
 
  251     return mRootNode.get();
 
  253   QObject *obj = 
reinterpret_cast<QObject *
>( 
index.internalPointer() );
 
  254   return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
 
  259   if ( !node || !node->parent() )
 
  260     return QModelIndex(); 
 
  262   QModelIndex parentIndex = 
node2index( node->parent() );
 
  264   int row = node->parent()->children().indexOf( node );
 
  265   Q_ASSERT( row >= 0 );
 
  266   return index( row, 0, parentIndex );
 
  276   QgsProcessingToolboxModelNode *parentNode = 
nullptr;
 
  277   if ( !isTopLevelProvider( provider->
id() ) )
 
  279     std::unique_ptr< QgsProcessingToolboxModelProviderNode > node = std::make_unique< QgsProcessingToolboxModelProviderNode >( provider );
 
  280     parentNode = node.get();
 
  281     mRootNode->addChildNode( node.release() );
 
  285     parentNode = mRootNode.get();
 
  288   const QList< const QgsProcessingAlgorithm * > algorithms = provider->
algorithms();
 
  291     std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = std::make_unique< QgsProcessingToolboxModelAlgorithmNode >( 
algorithm );
 
  294     if ( !groupId.isEmpty() )
 
  296       QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
 
  300         parentNode->addChildNode( groupNode );
 
  302       groupNode->addChildNode( algorithmNode.release() );
 
  307       parentNode->addChildNode( algorithmNode.release() );
 
  312 bool QgsProcessingToolboxModel::isTopLevelProvider( 
const QString &providerId )
 
  314   return providerId == QLatin1String( 
"qgis" ) ||
 
  315          providerId == QLatin1String( 
"native" ) ||
 
  316          providerId == QLatin1String( 
"3d" );
 
  321   return QStringLiteral( 
"<p><b>%1</b></p>%2<p>%3</p>%4" ).arg(
 
  324            QObject::tr( 
"Algorithm ID: ‘%1’" ).arg( QStringLiteral( 
"<i>%1</i>" ).arg( 
algorithm->
id() ) ),
 
  331   if ( !
index.isValid() )
 
  332     return Qt::ItemFlags();
 
  334   return QAbstractItemModel::flags( 
index );
 
  339   if ( !
index.isValid() )
 
  345       return node->nodeType();
 
  350   bool isRecentNode = 
false;
 
  352     isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeRecent;
 
  355   QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >( 
index2node( 
index ) );
 
  360     case Qt::DisplayRole:
 
  362       switch ( 
index.column() )
 
  366             return provider->
name();
 
  369           else if ( groupNode )
 
  370             return groupNode->name();
 
  371           else if ( isRecentNode )
 
  372             return tr( 
"Recently used" );
 
  382     case Qt::ToolTipRole:
 
  388       else if ( groupNode )
 
  389         return groupNode->name();
 
  394     case Qt::ForegroundRole:
 
  397         return QBrush( QColor( Qt::red ) );
 
  402     case Qt::DecorationRole:
 
  404       switch ( 
index.column() )
 
  409             return provider->
icon();
 
  416           else if ( isRecentNode )
 
  418           else if ( !
index.parent().isValid() )
 
  432       switch ( 
index.column() )
 
  448       switch ( 
index.column() )
 
  453             return static_cast< int >( provider->
flags() );
 
  468       switch ( 
index.column() )
 
  484       switch ( 
index.column() )
 
  500       switch ( 
index.column() )
 
  516       switch ( 
index.column() )
 
  545   return n->children().count();
 
  555   if ( !hasIndex( row, column, 
parent ) )
 
  556     return QModelIndex();
 
  560     return QModelIndex(); 
 
  562   return createIndex( row, column, 
static_cast<QObject *
>( n->children().at( row ) ) );
 
  567   if ( !child.isValid() )
 
  568     return QModelIndex();
 
  570   if ( QgsProcessingToolboxModelNode *n = 
index2node( child ) )
 
  577     return QModelIndex();
 
  583   if ( !indexes.isEmpty() && 
isAlgorithm( indexes.at( 0 ) ) )
 
  585     QByteArray encodedData;
 
  586     QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
 
  588     std::unique_ptr< QMimeData > 
mimeData = std::make_unique< QMimeData >();
 
  594     mimeData->setData( QStringLiteral( 
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
 
  603   if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
 
  606   return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->provider();
 
  612   if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
 
  615   return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->providerId();
 
  621   if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeAlgorithm )
 
  624   return qobject_cast< QgsProcessingToolboxModelAlgorithmNode * >( n )->algorithm();
 
  630   return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeAlgorithm );
 
  635   std::function< QModelIndex( 
const QModelIndex &
parent, 
const QString &providerId ) > findIndex = [&]( 
const QModelIndex & 
parent, 
const QString & providerId )->QModelIndex
 
  641       if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
 
  644       QModelIndex checkChildren = findIndex( current, providerId );
 
  645       if ( checkChildren.isValid() )
 
  646         return checkChildren;
 
  648     return QModelIndex();
 
  651   return findIndex( QModelIndex(), providerId );
 
  656   Q_ASSERT( parentNode );
 
  658   QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
 
  659   if ( !grandParentNode )
 
  660     return QModelIndex();  
 
  662   int row = grandParentNode->children().indexOf( parentNode );
 
  663   Q_ASSERT( row >= 0 );
 
  665   return createIndex( row, 0, 
static_cast<QObject *
>( parentNode ) );
 
  673     QgsProcessingRecentAlgorithmLog *recentLog )
 
  674   : QSortFilterProxyModel( parent )
 
  677   setSourceModel( mModel );
 
  678   setDynamicSortFilter( 
true );
 
  679   setSortLocaleAware( 
true );
 
  680   setFilterCaseSensitivity( Qt::CaseInsensitive );
 
  704   mInPlaceLayer = layer;
 
  711   mFilterString = filter;
 
  717   QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
 
  724     if ( !mFilterString.trimmed().isEmpty() )
 
  731       QStringList parentText;
 
  732       QModelIndex parent = sourceIndex.parent();
 
  733       while ( parent.isValid() )
 
  735         const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split( 
' ' );
 
  736         if ( !parentParts.empty() )
 
  737           parentText.append( parentParts );
 
  738         parent = parent.parent();
 
  741       const QStringList partsToMatch = mFilterString.trimmed().split( 
' ' );
 
  743       QStringList partsToSearch = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split( 
' ' );
 
  744       partsToSearch << algId << algName;
 
  745       partsToSearch.append( algTags );
 
  746       if ( !shortDesc.isEmpty() )
 
  747         partsToSearch.append( shortDesc.split( 
' ' ) );
 
  748       partsToSearch.append( parentText );
 
  750       for ( 
const QString &part : partsToMatch )
 
  753         for ( 
const QString &partToSearch : std::as_const( partsToSearch ) )
 
  755           if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
 
  769       if ( !supportsInPlace )
 
  781       return !isHiddenFromModeler;
 
  786       return !isHiddenFromToolbox;
 
  791   bool hasChildren = 
false;
 
  793   int count = sourceModel()->rowCount( sourceIndex );
 
  794   for ( 
int i = 0; i < count; ++i )
 
  811   if ( leftType == QgsProcessingToolboxModelNode::NodeRecent )
 
  813   else if ( rightType == QgsProcessingToolboxModelNode::NodeRecent )
 
  815   else if ( leftType != rightType )
 
  817     if ( leftType == QgsProcessingToolboxModelNode::NodeProvider )
 
  819     else if ( rightType == QgsProcessingToolboxModelNode::NodeProvider )
 
  821     else if ( leftType == QgsProcessingToolboxModelNode::NodeGroup )
 
  828   bool isRecentNode = 
false;
 
  829   QModelIndex parent = left.parent();
 
  830   while ( parent.isValid() )
 
  837     parent = parent.parent();
 
  841     return left.row() < right.row();
 
  846   QString leftStr = sourceModel()->data( left ).toString();
 
  847   QString rightStr = sourceModel()->data( right ).toString();
 
  848   return QString::localeAwareCompare( leftStr, rightStr ) < 0;
 
  853   if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
 
  855     QModelIndex sourceIndex = mapToSource( index );
 
  859       QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
 
  860       QColor fadedTextColor = brush.color();
 
  861       fadedTextColor.setAlpha( 100 );
 
  862       brush.setColor( fadedTextColor );
 
  866   return QSortFilterProxyModel::data( index, role );
 
Extends QApplication to provide access to QGIS specific resources such as theme paths,...
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...
@ FlagSupportsInPlaceEdits
Algorithm supports in-place editing.
@ FlagKnownIssues
Algorithm has known issues.
@ FlagHideFromToolbox
Algorithm should be hidden from the toolbox.
@ FlagHideFromModeler
Algorithm should be hidden from the modeler.
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.
QgsProcessingAlgorithm::Flags flags() const override
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Abstract base class for processing providers.
virtual QIcon icon() const
Returns an icon for the provider.
virtual QString name() const =0
Returns the provider name, which is used to describe the provider within the GUI.
@ FlagDeemphasiseSearchResults
Algorithms should be de-emphasised in the search results when searching for algorithms....
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...
virtual Flags flags() const
Returns the flags indicating how and when the provider operates and should be exposed to users.
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 providerAdded(const QString &id)
Emitted when a provider has been added to the registry.
void providerRemoved(const QString &id)
Emitted when a provider is removed from the registry.
Represents a vector layer which manages a vector based data sets.
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