31#include "moc_qgsprocessingtoolboxmodel.cpp"
33using namespace Qt::StringLiterals;
41QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
46QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
48 return mChildren.takeAt( mChildren.indexOf( node ) );
51QgsProcessingToolboxModelGroupNode *QgsProcessingToolboxModelNode::getChildGroupNode(
const QString &groupId )
53 for ( QgsProcessingToolboxModelNode *node : std::as_const( mChildren ) )
55 if ( node->nodeType() == NodeType::Group )
57 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast<QgsProcessingToolboxModelGroupNode *>( node );
58 if ( groupNode && groupNode->id() == groupId )
65void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
70 Q_ASSERT( !node->mParent );
73 mChildren.append( node );
76void QgsProcessingToolboxModelNode::deleteChildren()
78 qDeleteAll( mChildren );
86QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode(
QgsProcessingProvider *provider )
87 : mProviderId( provider->id() )
88 , mProvider( provider )
100QgsProcessingToolboxModelGroupNode::QgsProcessingToolboxModelGroupNode(
const QString &
id,
const QString &name )
119 : mParamType( paramType )
134 : QAbstractItemModel(
parent )
135 , mRegistry( registry ? registry :
QgsApplication::processingRegistry() )
136 , mRecentLog( recentLog )
137 , mFavoriteManager( favoriteManager )
138 , mRootNode( std::make_unique<QgsProcessingToolboxModelGroupNode>( QString(), QString() ) )
143 connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed,
this, [
this] { repopulateRecentAlgorithms(); } );
145 if ( mFavoriteManager )
146 connect( mFavoriteManager, &QgsProcessingFavoriteAlgorithmManager::changed,
this, [
this] { repopulateFavoriteAlgorithms(); } );
155void QgsProcessingToolboxModel::rebuild()
159 mRootNode->deleteChildren();
160 mRecentNode =
nullptr;
161 mFavoriteNode =
nullptr;
165 auto recentNode = std::make_unique<QgsProcessingToolboxModelRecentNode>();
167 mRecentNode = recentNode.get();
168 mRootNode->addChildNode( recentNode.release() );
169 repopulateRecentAlgorithms(
true );
172 if ( mFavoriteManager )
174 auto favoriteNode = std::make_unique<QgsProcessingToolboxModelFavoriteNode>();
176 mFavoriteNode = favoriteNode.get();
177 mRootNode->addChildNode( favoriteNode.release() );
178 repopulateFavoriteAlgorithms(
true );
184 auto groupNode = std::make_unique<QgsProcessingToolboxModelParameterGroupNode>();
188 std::sort( available.begin(), available.end(), [](
const QgsProcessingParameterType *a,
const QgsProcessingParameterType *b ) ->
bool {
189 return QString::localeAwareCompare( a->name(), b->name() ) < 0;
191 for ( QgsProcessingParameterType *param : std::as_const( available ) )
195 auto paramNode = std::make_unique<QgsProcessingToolboxModelParameterNode>( param );
196 groupNode->addChildNode( paramNode.release() );
199 mRootNode->addChildNode( groupNode.release() );
205 const QList<QgsProcessingProvider *> providers = mRegistry->providers();
206 for ( QgsProcessingProvider *provider : providers )
208 addProvider( provider );
214void QgsProcessingToolboxModel::repopulateRecentAlgorithms(
bool resetting )
216 if ( !mRecentNode || !mRecentLog )
219 QModelIndex recentIndex =
index( 0, 0 );
220 const int prevCount =
rowCount( recentIndex );
221 if ( !resetting && prevCount > 0 )
223 beginRemoveRows( recentIndex, 0, prevCount - 1 );
224 mRecentNode->deleteChildren();
235 const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
236 QList<const QgsProcessingAlgorithm *> recentAlgorithms;
237 recentAlgorithms.reserve( recentAlgIds.count() );
238 for (
const QString &
id : recentAlgIds )
240 const QgsProcessingAlgorithm *
algorithm = mRegistry->algorithmById(
id );
245 if ( recentAlgorithms.empty() )
254 beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
257 for (
const QgsProcessingAlgorithm *
algorithm : std::as_const( recentAlgorithms ) )
259 auto algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>(
algorithm );
260 mRecentNode->addChildNode( algorithmNode.release() );
270void QgsProcessingToolboxModel::repopulateFavoriteAlgorithms(
bool resetting )
272 if ( !mFavoriteNode || !mFavoriteManager )
277 int idx = ( mRecentNode && mRecentLog ) ? 1 : 0;
279 QModelIndex favoriteIndex =
index( idx, 0 );
280 const int prevCount =
rowCount( favoriteIndex );
281 if ( !resetting && prevCount > 0 )
283 beginRemoveRows( favoriteIndex, 0, prevCount - 1 );
284 mFavoriteNode->deleteChildren();
295 const QStringList favoriteAlgIds = mFavoriteManager->favoriteAlgorithmIds();
296 QList<const QgsProcessingAlgorithm *> favoriteAlgorithms;
297 favoriteAlgorithms.reserve( favoriteAlgIds.count() );
298 for (
const QString &
id : favoriteAlgIds )
300 const QgsProcessingAlgorithm *
algorithm = mRegistry->algorithmById(
id );
305 if ( favoriteAlgorithms.empty() )
314 beginInsertRows( favoriteIndex, 0, favoriteAlgorithms.count() - 1 );
317 for (
const QgsProcessingAlgorithm *
algorithm : std::as_const( favoriteAlgorithms ) )
319 auto algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>(
algorithm );
320 mFavoriteNode->addChildNode( algorithmNode.release() );
332 if ( !
index.isValid() )
333 return mRootNode.get();
335 QObject *obj =
reinterpret_cast<QObject *
>(
index.internalPointer() );
336 return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
341 if ( !node || !node->parent() )
342 return QModelIndex();
344 QModelIndex parentIndex =
node2index( node->parent() );
346 int row = node->parent()->children().indexOf( node );
347 Q_ASSERT( row >= 0 );
348 return index( row, 0, parentIndex );
358 QgsProcessingToolboxModelNode *parentNode =
nullptr;
359 if ( !isTopLevelProvider( provider->
id() ) )
361 auto node = std::make_unique<QgsProcessingToolboxModelProviderNode>( provider );
362 parentNode = node.get();
363 mRootNode->addChildNode( node.release() );
367 parentNode = mRootNode.get();
370 const QList<const QgsProcessingAlgorithm *> algorithms = provider->
algorithms();
371 for (
const QgsProcessingAlgorithm *
algorithm : algorithms )
373 auto algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>(
algorithm );
376 if ( !groupId.isEmpty() )
379 QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
384 parentNode->addChildNode( groupNode );
386 groupNode->addChildNode( algorithmNode.release() );
392 parentNode->addChildNode( algorithmNode.release() );
397bool QgsProcessingToolboxModel::isTopLevelProvider(
const QString &providerId )
399 return providerId ==
"qgis"_L1 || providerId ==
"native"_L1 || providerId ==
"3d"_L1 || providerId ==
"pdal"_L1;
404 return u
"<p><b>%1</b></p>%2<p>%3</p>%4"_s.arg(
407 QObject::tr(
"Algorithm ID: ‘%1’" ).arg( u
"<i>%1</i>"_s.arg(
algorithm->
id() ) ),
414 if ( !
index.isValid() )
415 return Qt::ItemFlags();
417 return QAbstractItemModel::flags(
index );
422 if ( !
index.isValid() )
428 return static_cast<int>( node->nodeType() );
433 bool isRecentNode =
false;
435 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Recent;
437 bool isFavoriteNode =
false;
439 isFavoriteNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Favorite;
441 bool isParameterGroupNode =
false;
443 isParameterGroupNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::ParameterGroup;
446 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast<QgsProcessingToolboxModelGroupNode *>(
index2node(
index ) );
452 case Qt::DisplayRole:
454 switch (
index.column() )
458 return provider->
name();
461 else if ( paramType )
462 return paramType->
name();
463 else if ( groupNode )
464 return groupNode->name();
465 else if ( isRecentNode )
466 return tr(
"Recently used" );
467 else if ( isFavoriteNode )
468 return tr(
"Favorites" );
469 else if ( isParameterGroupNode )
470 return tr(
"Input parameters" );
480 case Qt::ToolTipRole:
486 else if ( paramType )
488 else if ( groupNode )
489 return groupNode->name();
490 else if ( isParameterGroupNode )
491 return tr(
"Input parameters used in the modeler" );
496 case Qt::ForegroundRole:
499 return QBrush( QColor( Qt::red ) );
504 case Qt::DecorationRole:
506 switch (
index.column() )
511 return provider->
icon();
518 else if ( paramType )
520 else if ( isRecentNode )
522 else if ( isFavoriteNode )
524 else if ( isParameterGroupNode )
526 else if ( !
index.parent().isValid() )
540 switch (
index.column() )
545 return static_cast<int>(
algorithm->flags() );
556 switch (
index.column() )
561 return static_cast<int>( provider->
flags() );
576 switch (
index.column() )
592 switch (
index.column() )
608 switch (
index.column() )
624 switch (
index.column() )
639 switch (
index.column() )
644 return paramType->
id();
667 return n->children().count();
677 if ( !hasIndex( row, column,
parent ) )
678 return QModelIndex();
682 return QModelIndex();
684 return createIndex( row, column,
static_cast<QObject *
>( n->children().at( row ) ) );
689 if ( !child.isValid() )
690 return QModelIndex();
692 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
699 return QModelIndex();
705 if ( indexes.isEmpty() )
711 QByteArray encodedData;
712 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
714 auto mimeData = std::make_unique<QMimeData>();
720 mimeData->setData( u
"application/x-vnd.qgis.qgis.algorithmid"_s, encodedData );
725 QByteArray encodedData;
726 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
728 auto mimeData = std::make_unique<QMimeData>();
732 stream << paramType->
id();
734 mimeData->setData( u
"application/x-vnd.qgis.qgis.parametertypeid"_s, encodedData );
743 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
746 return qobject_cast<QgsProcessingToolboxModelProviderNode *>( n )->provider();
752 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
755 return qobject_cast<QgsProcessingToolboxModelProviderNode *>( n )->providerId();
761 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Algorithm )
764 return qobject_cast<QgsProcessingToolboxModelAlgorithmNode *>( n )->algorithm();
770 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Algorithm );
776 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Parameter );
782 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Parameter )
785 return qobject_cast<QgsProcessingToolboxModelParameterNode *>( n )->parameterType();
790 std::function<QModelIndex(
const QModelIndex &
parent,
const QString &providerId )> findIndex = [&](
const QModelIndex &
parent,
const QString &providerId ) -> QModelIndex {
795 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
798 QModelIndex checkChildren = findIndex( current, providerId );
799 if ( checkChildren.isValid() )
800 return checkChildren;
802 return QModelIndex();
805 return findIndex( QModelIndex(), providerId );
810 Q_ASSERT( parentNode );
812 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
813 if ( !grandParentNode )
814 return QModelIndex();
816 int row = grandParentNode->children().indexOf( parentNode );
817 Q_ASSERT( row >= 0 );
819 return createIndex( row, 0,
static_cast<QObject *
>( parentNode ) );
827 QObject *parent,
QgsProcessingRegistry *registry, QgsProcessingRecentAlgorithmLog *recentLog, QgsProcessingFavoriteAlgorithmManager *favoriteManager
829 : QSortFilterProxyModel( parent )
832 setSourceModel( mModel );
833 setDynamicSortFilter(
true );
834 setSortLocaleAware(
true );
835 setFilterCaseSensitivity( Qt::CaseInsensitive );
860 mInPlaceLayer = layer;
867 mFilterString = filter;
873 mFilterParameterDefinition.reset( parameterDefinition->
clone() );
874 mFilterOutputDefinition.reset();
881 mFilterParameterDefinition.reset();
882 mFilterOutputDefinition.reset( outputDefinition->
clone() );
890 QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
891 if ( mModel->isAlgorithm( sourceIndex ) )
898 if ( !mFilterString.trimmed().isEmpty() )
905 QStringList parentText;
906 QModelIndex parent = sourceIndex.parent();
907 while ( parent.isValid() )
909 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
910 if ( !parentParts.empty() )
911 parentText.append( parentParts );
912 parent = parent.parent();
915 QStringList partsToSearch;
916 partsToSearch << sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
917 partsToSearch << algId << algName;
918 partsToSearch.append( algTags );
919 if ( !shortDesc.isEmpty() )
920 partsToSearch.append( shortDesc.split(
' ' ) );
921 partsToSearch.append( parentText );
923 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
924 for (
const QString &part : partsToMatch )
928 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
945 if ( !supportsInPlace )
958 if ( mFilterParameterDefinition )
961 const QList<const QgsProcessingOutputDefinition *> outputs = alg->
outputDefinitions();
979 if ( mFilterOutputDefinition )
993 if ( mFilterParameterDefinition )
1015 return !isHiddenFromModeler;
1021 return !isHiddenFromToolbox;
1025 if ( mModel->isParameter( sourceIndex ) )
1038 if ( !mFilterString.trimmed().isEmpty() )
1040 QStringList partsToSearch;
1041 partsToSearch << sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
1044 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
1045 for (
const QString &part : partsToMatch )
1049 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
1064 if ( mFilterParameterDefinition )
1075 bool hasChildren =
false;
1077 int count = sourceModel()->rowCount( sourceIndex );
1078 for (
int i = 0; i < count; ++i )
1092 QgsProcessingToolboxModelNode::NodeType leftType =
static_cast<QgsProcessingToolboxModelNode::NodeType
>(
1095 QgsProcessingToolboxModelNode::NodeType rightType =
static_cast<QgsProcessingToolboxModelNode::NodeType
>(
1099 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Recent )
1101 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Recent )
1103 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Favorite )
1105 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Favorite )
1107 else if ( leftType != rightType )
1109 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Provider )
1111 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Provider )
1113 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Group )
1120 bool isRecentNode =
false;
1121 QModelIndex parent = left.parent();
1122 while ( parent.isValid() )
1126 isRecentNode =
true;
1129 parent = parent.parent();
1133 return left.row() < right.row();
1137 QString leftStr = sourceModel()->data( left ).toString();
1138 QString rightStr = sourceModel()->data( right ).toString();
1139 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
1144 if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
1146 QModelIndex sourceIndex = mapToSource( index );
1150 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
1151 QColor fadedTextColor = brush.color();
1152 fadedTextColor.setAlpha( 100 );
1153 brush.setColor( fadedTextColor );
1157 return QSortFilterProxyModel::data( index, role );
@ 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.
@ Hidden
Parameter is hidden and should not be shown to users.
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.
QgsProcessingOutputDefinitions outputDefinitions() const
Returns an ordered list of output definitions utilized by the algorithm.
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 QString shortDescription() const
Returns an optional translated short description of the algorithm.
QgsProcessingParameterDefinitions parameterDefinitions() const
Returns an ordered list of parameter definitions utilized by 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 bool supportInPlaceEdit(const QgsMapLayer *layer) const
Checks whether this algorithm supports in-place editing on the given layer Default implementation ret...
Qgis::ProcessingAlgorithmFlags flags() const override
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Base class for the definition of processing outputs.
virtual QgsProcessingOutputDefinition * clone() const =0
Creates a clone of the output definition.
Base class for the definition of processing parameters.
virtual QgsProcessingParameterDefinition * clone() const =0
Creates a clone of the parameter definition.
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.
virtual QStringList acceptedParameterTypes() const =0
Returns a list of compatible Processing parameter types for inputs for 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.
QgsProcessingParameterType * parameterType(const QString &id) const
Returns the parameter type registered for id.
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.
static QString unaccent(const QString &input)
Removes accents and other diacritical marks from a string, replacing accented characters with their u...
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