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 )
121 : QAbstractItemModel( parent )
122 , mRegistry( registry ? registry :
QgsApplication::processingRegistry() )
123 , mRecentLog( recentLog )
124 , mFavoriteManager( favoriteManager )
125 , mRootNode( std::make_unique<QgsProcessingToolboxModelGroupNode>( QString(), QString() ) )
130 connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed,
this, [=] { repopulateRecentAlgorithms(); } );
132 if ( mFavoriteManager )
133 connect( mFavoriteManager, &QgsProcessingFavoriteAlgorithmManager::changed,
this, [=] { repopulateFavoriteAlgorithms(); } );
139void QgsProcessingToolboxModel::rebuild()
143 mRootNode->deleteChildren();
144 mRecentNode =
nullptr;
145 mFavoriteNode =
nullptr;
149 std::unique_ptr<QgsProcessingToolboxModelRecentNode> recentNode = std::make_unique<QgsProcessingToolboxModelRecentNode>();
151 mRecentNode = recentNode.get();
152 mRootNode->addChildNode( recentNode.release() );
153 repopulateRecentAlgorithms(
true );
156 if ( mFavoriteManager )
158 std::unique_ptr<QgsProcessingToolboxModelFavoriteNode> favoriteNode = std::make_unique<QgsProcessingToolboxModelFavoriteNode>();
160 mFavoriteNode = favoriteNode.get();
161 mRootNode->addChildNode( favoriteNode.release() );
162 repopulateFavoriteAlgorithms(
true );
167 const QList<QgsProcessingProvider *> providers = mRegistry->providers();
170 addProvider( provider );
176void QgsProcessingToolboxModel::repopulateRecentAlgorithms(
bool resetting )
178 if ( !mRecentNode || !mRecentLog )
181 QModelIndex recentIndex =
index( 0, 0 );
182 const int prevCount =
rowCount( recentIndex );
183 if ( !resetting && prevCount > 0 )
185 beginRemoveRows( recentIndex, 0, prevCount - 1 );
186 mRecentNode->deleteChildren();
197 const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
198 QList<const QgsProcessingAlgorithm *> recentAlgorithms;
199 recentAlgorithms.reserve( recentAlgIds.count() );
200 for (
const QString &
id : recentAlgIds )
207 if ( recentAlgorithms.empty() )
216 beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
221 std::unique_ptr<QgsProcessingToolboxModelAlgorithmNode> algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>(
algorithm );
222 mRecentNode->addChildNode( algorithmNode.release() );
232void QgsProcessingToolboxModel::repopulateFavoriteAlgorithms(
bool resetting )
234 if ( !mFavoriteNode || !mFavoriteManager )
239 int idx = ( mRecentNode && mRecentLog ) ? 1 : 0;
241 QModelIndex favoriteIndex =
index( idx, 0 );
242 const int prevCount =
rowCount( favoriteIndex );
243 if ( !resetting && prevCount > 0 )
245 beginRemoveRows( favoriteIndex, 0, prevCount - 1 );
246 mFavoriteNode->deleteChildren();
257 const QStringList favoriteAlgIds = mFavoriteManager->favoriteAlgorithmIds();
258 QList<const QgsProcessingAlgorithm *> favoriteAlgorithms;
259 favoriteAlgorithms.reserve( favoriteAlgIds.count() );
260 for (
const QString &
id : favoriteAlgIds )
267 if ( favoriteAlgorithms.empty() )
276 beginInsertRows( favoriteIndex, 0, favoriteAlgorithms.count() - 1 );
281 std::unique_ptr<QgsProcessingToolboxModelAlgorithmNode> algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>(
algorithm );
282 mFavoriteNode->addChildNode( algorithmNode.release() );
292void QgsProcessingToolboxModel::providerAdded(
const QString &
id )
301 if ( !isTopLevelProvider(
id ) )
304 beginInsertRows( QModelIndex(), previousRowCount, previousRowCount );
305 addProvider( provider );
313 addProvider( provider );
318void QgsProcessingToolboxModel::providerRemoved(
const QString & )
327 if ( !
index.isValid() )
328 return mRootNode.get();
330 QObject *obj =
reinterpret_cast<QObject *
>(
index.internalPointer() );
331 return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
336 if ( !node || !node->parent() )
337 return QModelIndex();
339 QModelIndex parentIndex =
node2index( node->parent() );
341 int row = node->parent()->children().indexOf( node );
342 Q_ASSERT( row >= 0 );
343 return index( row, 0, parentIndex );
353 QgsProcessingToolboxModelNode *parentNode =
nullptr;
354 if ( !isTopLevelProvider( provider->
id() ) )
356 std::unique_ptr<QgsProcessingToolboxModelProviderNode> node = std::make_unique<QgsProcessingToolboxModelProviderNode>( provider );
357 parentNode = node.get();
358 mRootNode->addChildNode( node.release() );
362 parentNode = mRootNode.get();
365 const QList<const QgsProcessingAlgorithm *> algorithms = provider->
algorithms();
368 std::unique_ptr<QgsProcessingToolboxModelAlgorithmNode> algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>(
algorithm );
371 if ( !groupId.isEmpty() )
374 QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
379 parentNode->addChildNode( groupNode );
381 groupNode->addChildNode( algorithmNode.release() );
387 parentNode->addChildNode( algorithmNode.release() );
392bool QgsProcessingToolboxModel::isTopLevelProvider(
const QString &providerId )
394 return providerId == QLatin1String(
"qgis" ) || providerId == QLatin1String(
"native" ) || providerId == QLatin1String(
"3d" ) || providerId == QLatin1String(
"pdal" );
399 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() );
404 if ( !
index.isValid() )
405 return Qt::ItemFlags();
407 return QAbstractItemModel::flags(
index );
412 if ( !
index.isValid() )
418 return static_cast<int>( node->nodeType() );
423 bool isRecentNode =
false;
425 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Recent;
427 bool isFavoriteNode =
false;
429 isFavoriteNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Favorite;
432 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast<QgsProcessingToolboxModelGroupNode *>(
index2node(
index ) );
437 case Qt::DisplayRole:
439 switch (
index.column() )
443 return provider->
name();
446 else if ( groupNode )
447 return groupNode->name();
448 else if ( isRecentNode )
449 return tr(
"Recently used" );
450 else if ( isFavoriteNode )
451 return tr(
"Favorites" );
461 case Qt::ToolTipRole:
467 else if ( groupNode )
468 return groupNode->name();
473 case Qt::ForegroundRole:
476 return QBrush( QColor( Qt::red ) );
481 case Qt::DecorationRole:
483 switch (
index.column() )
488 return provider->
icon();
495 else if ( isRecentNode )
497 else if ( isFavoriteNode )
499 else if ( !
index.parent().isValid() )
513 switch (
index.column() )
529 switch (
index.column() )
534 return static_cast<int>( provider->
flags() );
549 switch (
index.column() )
565 switch (
index.column() )
581 switch (
index.column() )
597 switch (
index.column() )
626 return n->children().count();
636 if ( !hasIndex( row, column,
parent ) )
637 return QModelIndex();
641 return QModelIndex();
643 return createIndex( row, column,
static_cast<QObject *
>( n->children().at( row ) ) );
648 if ( !child.isValid() )
649 return QModelIndex();
651 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
658 return QModelIndex();
664 if ( !indexes.isEmpty() &&
isAlgorithm( indexes.at( 0 ) ) )
666 QByteArray encodedData;
667 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
669 std::unique_ptr<QMimeData>
mimeData = std::make_unique<QMimeData>();
675 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
684 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
687 return qobject_cast<QgsProcessingToolboxModelProviderNode *>( n )->provider();
693 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
696 return qobject_cast<QgsProcessingToolboxModelProviderNode *>( n )->providerId();
702 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Algorithm )
705 return qobject_cast<QgsProcessingToolboxModelAlgorithmNode *>( n )->algorithm();
711 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Algorithm );
716 std::function<QModelIndex(
const QModelIndex &
parent,
const QString &providerId )> findIndex = [&](
const QModelIndex &
parent,
const QString &providerId ) -> QModelIndex {
721 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
724 QModelIndex checkChildren = findIndex( current, providerId );
725 if ( checkChildren.isValid() )
726 return checkChildren;
728 return QModelIndex();
731 return findIndex( QModelIndex(), providerId );
736 Q_ASSERT( parentNode );
738 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
739 if ( !grandParentNode )
740 return QModelIndex();
742 int row = grandParentNode->children().indexOf( parentNode );
743 Q_ASSERT( row >= 0 );
745 return createIndex( row, 0,
static_cast<QObject *
>( parentNode ) );
753 : QSortFilterProxyModel( parent )
756 setSourceModel( mModel );
757 setDynamicSortFilter(
true );
758 setSortLocaleAware(
true );
759 setFilterCaseSensitivity( Qt::CaseInsensitive );
784 mInPlaceLayer = layer;
791 mFilterString = filter;
797 QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
804 if ( !mFilterString.trimmed().isEmpty() )
811 QStringList parentText;
812 QModelIndex parent = sourceIndex.parent();
813 while ( parent.isValid() )
815 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
816 if ( !parentParts.empty() )
817 parentText.append( parentParts );
818 parent = parent.parent();
821 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
823 QStringList partsToSearch = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
824 partsToSearch << algId << algName;
825 partsToSearch.append( algTags );
826 if ( !shortDesc.isEmpty() )
827 partsToSearch.append( shortDesc.split(
' ' ) );
828 partsToSearch.append( parentText );
830 for (
const QString &part : partsToMatch )
833 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
835 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
849 if ( !supportsInPlace )
861 return !isHiddenFromModeler;
866 return !isHiddenFromToolbox;
871 bool hasChildren =
false;
873 int count = sourceModel()->rowCount( sourceIndex );
874 for (
int i = 0; i < count; ++i )
891 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Recent )
893 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Recent )
895 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Favorite )
897 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Favorite )
899 else if ( leftType != rightType )
901 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Provider )
903 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Provider )
905 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Group )
912 bool isRecentNode =
false;
913 QModelIndex parent = left.parent();
914 while ( parent.isValid() )
921 parent = parent.parent();
925 return left.row() < right.row();
929 QString leftStr = sourceModel()->data( left ).toString();
930 QString rightStr = sourceModel()->data( right ).toString();
931 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
936 if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
938 QModelIndex sourceIndex = mapToSource( index );
942 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
943 QColor fadedTextColor = brush.color();
944 fadedTextColor.setAlpha( 100 );
945 brush.setColor( fadedTextColor );
949 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