26#ifdef ENABLE_MODELTEST
36QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
41QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
43 return mChildren.takeAt( mChildren.indexOf( node ) );
46QgsProcessingToolboxModelGroupNode *QgsProcessingToolboxModelNode::getChildGroupNode(
const QString &groupId )
48 for ( QgsProcessingToolboxModelNode *node : std::as_const( mChildren ) )
50 if ( node->nodeType() == NodeType::Group )
52 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >( node );
53 if ( groupNode && groupNode->id() == groupId )
60void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
65 Q_ASSERT( !node->mParent );
68 mChildren.append( node );
71void QgsProcessingToolboxModelNode::deleteChildren()
73 qDeleteAll( mChildren );
81QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode(
QgsProcessingProvider *provider )
82 : mProviderId( provider->id() )
83 , mProvider( provider )
95QgsProcessingToolboxModelGroupNode::QgsProcessingToolboxModelGroupNode(
const QString &
id,
const QString &name )
120 : QAbstractItemModel( parent )
121 , mRegistry( registry ? registry :
QgsApplication::processingRegistry() )
122 , mRecentLog( recentLog )
123 , mFavoriteManager( favoriteManager )
124 , mRootNode( std::make_unique< QgsProcessingToolboxModelGroupNode >( QString(), QString() ) )
129 connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed,
this, [ = ] { repopulateRecentAlgorithms(); } );
131 if ( mFavoriteManager )
132 connect( mFavoriteManager, &QgsProcessingFavoriteAlgorithmManager::changed,
this, [ = ] { repopulateFavoriteAlgorithms(); } );
138void QgsProcessingToolboxModel::rebuild()
142 mRootNode->deleteChildren();
143 mRecentNode =
nullptr;
144 mFavoriteNode =
nullptr;
148 std::unique_ptr< QgsProcessingToolboxModelRecentNode > recentNode = std::make_unique< QgsProcessingToolboxModelRecentNode >();
150 mRecentNode = recentNode.get();
151 mRootNode->addChildNode( recentNode.release() );
152 repopulateRecentAlgorithms(
true );
155 if ( mFavoriteManager )
157 std::unique_ptr< QgsProcessingToolboxModelFavoriteNode > favoriteNode = std::make_unique< QgsProcessingToolboxModelFavoriteNode >();
159 mFavoriteNode = favoriteNode.get();
160 mRootNode->addChildNode( favoriteNode.release() );
161 repopulateFavoriteAlgorithms(
true );
166 const QList< QgsProcessingProvider * > providers = mRegistry->providers();
169 addProvider( provider );
175void QgsProcessingToolboxModel::repopulateRecentAlgorithms(
bool resetting )
177 if ( !mRecentNode || !mRecentLog )
180 QModelIndex recentIndex =
index( 0, 0 );
181 const int prevCount =
rowCount( recentIndex );
182 if ( !resetting && prevCount > 0 )
184 beginRemoveRows( recentIndex, 0, prevCount - 1 );
185 mRecentNode->deleteChildren();
196 const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
197 QList< const QgsProcessingAlgorithm * > recentAlgorithms;
198 recentAlgorithms.reserve( recentAlgIds.count() );
199 for (
const QString &
id : recentAlgIds )
206 if ( recentAlgorithms.empty() )
215 beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
220 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = std::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
221 mRecentNode->addChildNode( algorithmNode.release() );
231void QgsProcessingToolboxModel::repopulateFavoriteAlgorithms(
bool resetting )
233 if ( !mFavoriteNode || !mFavoriteManager )
238 int idx = ( mRecentNode && mRecentLog ) ? 1 : 0;
240 QModelIndex favoriteIndex =
index( idx, 0 );
241 const int prevCount =
rowCount( favoriteIndex );
242 if ( !resetting && prevCount > 0 )
244 beginRemoveRows( favoriteIndex, 0, prevCount - 1 );
245 mFavoriteNode->deleteChildren();
256 const QStringList favoriteAlgIds = mFavoriteManager->favoriteAlgorithmIds();
257 QList< const QgsProcessingAlgorithm * > favoriteAlgorithms;
258 favoriteAlgorithms.reserve( favoriteAlgIds.count() );
259 for (
const QString &
id : favoriteAlgIds )
266 if ( favoriteAlgorithms.empty() )
275 beginInsertRows( favoriteIndex, 0, favoriteAlgorithms.count() - 1 );
280 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = std::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
281 mFavoriteNode->addChildNode( algorithmNode.release() );
291void QgsProcessingToolboxModel::providerAdded(
const QString &
id )
300 if ( !isTopLevelProvider(
id ) )
303 beginInsertRows( QModelIndex(), previousRowCount, previousRowCount );
304 addProvider( provider );
312 addProvider( provider );
317void QgsProcessingToolboxModel::providerRemoved(
const QString & )
326 if ( !
index.isValid() )
327 return mRootNode.get();
329 QObject *obj =
reinterpret_cast<QObject *
>(
index.internalPointer() );
330 return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
335 if ( !node || !node->parent() )
336 return QModelIndex();
338 QModelIndex parentIndex =
node2index( node->parent() );
340 int row = node->parent()->children().indexOf( node );
341 Q_ASSERT( row >= 0 );
342 return index( row, 0, parentIndex );
352 QgsProcessingToolboxModelNode *parentNode =
nullptr;
353 if ( !isTopLevelProvider( provider->
id() ) )
355 std::unique_ptr< QgsProcessingToolboxModelProviderNode > node = std::make_unique< QgsProcessingToolboxModelProviderNode >( provider );
356 parentNode = node.get();
357 mRootNode->addChildNode( node.release() );
361 parentNode = mRootNode.get();
364 const QList< const QgsProcessingAlgorithm * > algorithms = provider->
algorithms();
367 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = std::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
370 if ( !groupId.isEmpty() )
373 QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
378 parentNode->addChildNode( groupNode );
380 groupNode->addChildNode( algorithmNode.release() );
386 parentNode->addChildNode( algorithmNode.release() );
391bool QgsProcessingToolboxModel::isTopLevelProvider(
const QString &providerId )
393 return providerId == QLatin1String(
"qgis" ) ||
394 providerId == QLatin1String(
"native" ) ||
395 providerId == QLatin1String(
"3d" ) ||
396 providerId == QLatin1String(
"pdal" );
401 return QStringLiteral(
"<p><b>%1</b></p>%2<p>%3</p>%4" ).arg(
404 QObject::tr(
"Algorithm ID: ‘%1’" ).arg( QStringLiteral(
"<i>%1</i>" ).arg(
algorithm->id() ) ),
405 (
algorithm->
flags() &
Qgis::ProcessingAlgorithmFlag::KnownIssues ) ? QStringLiteral(
"<b style=\"color:red\">%1</b>" ).arg( QObject::tr(
"Warning: Algorithm has known issues" ) ) : QString()
411 if ( !
index.isValid() )
412 return Qt::ItemFlags();
414 return QAbstractItemModel::flags(
index );
419 if ( !
index.isValid() )
425 return static_cast< int >( node->nodeType() );
430 bool isRecentNode =
false;
432 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Recent;
434 bool isFavoriteNode =
false;
436 isFavoriteNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Favorite;
439 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >(
index2node(
index ) );
444 case Qt::DisplayRole:
446 switch (
index.column() )
450 return provider->
name();
453 else if ( groupNode )
454 return groupNode->name();
455 else if ( isRecentNode )
456 return tr(
"Recently used" );
457 else if ( isFavoriteNode )
458 return tr(
"Favorites" );
468 case Qt::ToolTipRole:
474 else if ( groupNode )
475 return groupNode->name();
480 case Qt::ForegroundRole:
483 return QBrush( QColor( Qt::red ) );
488 case Qt::DecorationRole:
490 switch (
index.column() )
495 return provider->
icon();
502 else if ( isRecentNode )
504 else if ( isFavoriteNode )
506 else if ( !
index.parent().isValid() )
520 switch (
index.column() )
536 switch (
index.column() )
541 return static_cast< int >( provider->
flags() );
556 switch (
index.column() )
572 switch (
index.column() )
588 switch (
index.column() )
604 switch (
index.column() )
633 return n->children().count();
643 if ( !hasIndex( row, column,
parent ) )
644 return QModelIndex();
648 return QModelIndex();
650 return createIndex( row, column,
static_cast<QObject *
>( n->children().at( row ) ) );
655 if ( !child.isValid() )
656 return QModelIndex();
658 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
665 return QModelIndex();
671 if ( !indexes.isEmpty() &&
isAlgorithm( indexes.at( 0 ) ) )
673 QByteArray encodedData;
674 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
676 std::unique_ptr< QMimeData >
mimeData = std::make_unique< QMimeData >();
682 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
691 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
694 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->provider();
700 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
703 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->providerId();
709 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Algorithm )
712 return qobject_cast< QgsProcessingToolboxModelAlgorithmNode * >( n )->algorithm();
718 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Algorithm );
723 std::function< QModelIndex(
const QModelIndex &
parent,
const QString &providerId ) > findIndex = [&](
const QModelIndex &
parent,
const QString & providerId )->QModelIndex
729 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
732 QModelIndex checkChildren = findIndex( current, providerId );
733 if ( checkChildren.isValid() )
734 return checkChildren;
736 return QModelIndex();
739 return findIndex( QModelIndex(), providerId );
744 Q_ASSERT( parentNode );
746 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
747 if ( !grandParentNode )
748 return QModelIndex();
750 int row = grandParentNode->children().indexOf( parentNode );
751 Q_ASSERT( row >= 0 );
753 return createIndex( row, 0,
static_cast<QObject *
>( parentNode ) );
761 QgsProcessingRecentAlgorithmLog *recentLog, QgsProcessingFavoriteAlgorithmManager *favoriteManager )
762 : QSortFilterProxyModel( parent )
765 setSourceModel( mModel );
766 setDynamicSortFilter(
true );
767 setSortLocaleAware(
true );
768 setFilterCaseSensitivity( Qt::CaseInsensitive );
793 mInPlaceLayer = layer;
800 mFilterString = filter;
806 QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
813 if ( !mFilterString.trimmed().isEmpty() )
820 QStringList parentText;
821 QModelIndex parent = sourceIndex.parent();
822 while ( parent.isValid() )
824 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
825 if ( !parentParts.empty() )
826 parentText.append( parentParts );
827 parent = parent.parent();
830 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
832 QStringList partsToSearch = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
833 partsToSearch << algId << algName;
834 partsToSearch.append( algTags );
835 if ( !shortDesc.isEmpty() )
836 partsToSearch.append( shortDesc.split(
' ' ) );
837 partsToSearch.append( parentText );
839 for (
const QString &part : partsToMatch )
842 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
844 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
858 if ( !supportsInPlace )
870 return !isHiddenFromModeler;
875 return !isHiddenFromToolbox;
880 bool hasChildren =
false;
882 int count = sourceModel()->rowCount( sourceIndex );
883 for (
int i = 0; i < count; ++i )
900 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Recent )
902 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Recent )
904 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Favorite )
906 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Favorite )
908 else if ( leftType != rightType )
910 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Provider )
912 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Provider )
914 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Group )
921 bool isRecentNode =
false;
922 QModelIndex parent = left.parent();
923 while ( parent.isValid() )
930 parent = parent.parent();
934 return left.row() < right.row();
938 QString leftStr = sourceModel()->data( left ).toString();
939 QString rightStr = sourceModel()->data( right ).toString();
940 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
945 if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
947 QModelIndex sourceIndex = mapToSource( index );
951 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
952 QColor fadedTextColor = brush.color();
953 fadedTextColor.setAlpha( 100 );
954 brush.setColor( fadedTextColor );
958 return QSortFilterProxyModel::data( index, role );
The Qgis class provides global constants for use throughout the application.
@ 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 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.
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 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