31#include "moc_qgsprocessingtoolboxmodel.cpp"
33using namespace Qt::StringLiterals;
35#ifdef ENABLE_MODELTEST
45QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
50QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
52 return mChildren.takeAt( mChildren.indexOf( node ) );
55QgsProcessingToolboxModelGroupNode *QgsProcessingToolboxModelNode::getChildGroupNode(
const QString &groupId )
57 for ( QgsProcessingToolboxModelNode *node : std::as_const( mChildren ) )
59 if ( node->nodeType() == NodeType::Group )
61 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast<QgsProcessingToolboxModelGroupNode *>( node );
62 if ( groupNode && groupNode->id() == groupId )
69void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
74 Q_ASSERT( !node->mParent );
77 mChildren.append( node );
80void QgsProcessingToolboxModelNode::deleteChildren()
82 qDeleteAll( mChildren );
90QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode(
QgsProcessingProvider *provider )
91 : mProviderId( provider->id() )
92 , mProvider( provider )
104QgsProcessingToolboxModelGroupNode::QgsProcessingToolboxModelGroupNode(
const QString &
id,
const QString &name )
123 : mParamType( paramType )
138 : QAbstractItemModel(
parent )
139 , mRegistry( registry ? registry :
QgsApplication::processingRegistry() )
140 , mRecentLog( recentLog )
141 , mFavoriteManager( favoriteManager )
142 , mRootNode( std::make_unique<QgsProcessingToolboxModelGroupNode>( QString(), QString() ) )
147 connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed,
this, [
this] { repopulateRecentAlgorithms(); } );
149 if ( mFavoriteManager )
150 connect( mFavoriteManager, &QgsProcessingFavoriteAlgorithmManager::changed,
this, [
this] { repopulateFavoriteAlgorithms(); } );
159void QgsProcessingToolboxModel::rebuild()
163 mRootNode->deleteChildren();
164 mRecentNode =
nullptr;
165 mFavoriteNode =
nullptr;
169 auto recentNode = std::make_unique<QgsProcessingToolboxModelRecentNode>();
171 mRecentNode = recentNode.get();
172 mRootNode->addChildNode( recentNode.release() );
173 repopulateRecentAlgorithms(
true );
176 if ( mFavoriteManager )
178 auto favoriteNode = std::make_unique<QgsProcessingToolboxModelFavoriteNode>();
180 mFavoriteNode = favoriteNode.get();
181 mRootNode->addChildNode( favoriteNode.release() );
182 repopulateFavoriteAlgorithms(
true );
188 auto groupNode = std::make_unique<QgsProcessingToolboxModelParameterGroupNode>();
192 std::sort( available.begin(), available.end(), [](
const QgsProcessingParameterType *a,
const QgsProcessingParameterType *b ) ->
bool {
193 return QString::localeAwareCompare( a->name(), b->name() ) < 0;
195 for ( QgsProcessingParameterType *param : std::as_const( available ) )
199 auto paramNode = std::make_unique<QgsProcessingToolboxModelParameterNode>( param );
200 groupNode->addChildNode( paramNode.release() );
203 mRootNode->addChildNode( groupNode.release() );
209 const QList<QgsProcessingProvider *> providers = mRegistry->providers();
210 for ( QgsProcessingProvider *provider : providers )
212 addProvider( provider );
218void QgsProcessingToolboxModel::repopulateRecentAlgorithms(
bool resetting )
220 if ( !mRecentNode || !mRecentLog )
223 QModelIndex recentIndex =
index( 0, 0 );
224 const int prevCount =
rowCount( recentIndex );
225 if ( !resetting && prevCount > 0 )
227 beginRemoveRows( recentIndex, 0, prevCount - 1 );
228 mRecentNode->deleteChildren();
239 const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
240 QList<const QgsProcessingAlgorithm *> recentAlgorithms;
241 recentAlgorithms.reserve( recentAlgIds.count() );
242 for (
const QString &
id : recentAlgIds )
244 const QgsProcessingAlgorithm *
algorithm = mRegistry->algorithmById(
id );
249 if ( recentAlgorithms.empty() )
258 beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
261 for (
const QgsProcessingAlgorithm *
algorithm : std::as_const( recentAlgorithms ) )
263 auto algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>(
algorithm );
264 mRecentNode->addChildNode( algorithmNode.release() );
274void QgsProcessingToolboxModel::repopulateFavoriteAlgorithms(
bool resetting )
276 if ( !mFavoriteNode || !mFavoriteManager )
281 int idx = ( mRecentNode && mRecentLog ) ? 1 : 0;
283 QModelIndex favoriteIndex =
index( idx, 0 );
284 const int prevCount =
rowCount( favoriteIndex );
285 if ( !resetting && prevCount > 0 )
287 beginRemoveRows( favoriteIndex, 0, prevCount - 1 );
288 mFavoriteNode->deleteChildren();
299 const QStringList favoriteAlgIds = mFavoriteManager->favoriteAlgorithmIds();
300 QList<const QgsProcessingAlgorithm *> favoriteAlgorithms;
301 favoriteAlgorithms.reserve( favoriteAlgIds.count() );
302 for (
const QString &
id : favoriteAlgIds )
304 const QgsProcessingAlgorithm *
algorithm = mRegistry->algorithmById(
id );
309 if ( favoriteAlgorithms.empty() )
318 beginInsertRows( favoriteIndex, 0, favoriteAlgorithms.count() - 1 );
321 for (
const QgsProcessingAlgorithm *
algorithm : std::as_const( favoriteAlgorithms ) )
323 auto algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>(
algorithm );
324 mFavoriteNode->addChildNode( algorithmNode.release() );
336 if ( !
index.isValid() )
337 return mRootNode.get();
339 QObject *obj =
reinterpret_cast<QObject *
>(
index.internalPointer() );
340 return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
345 if ( !node || !node->parent() )
346 return QModelIndex();
348 QModelIndex parentIndex =
node2index( node->parent() );
350 int row = node->parent()->children().indexOf( node );
351 Q_ASSERT( row >= 0 );
352 return index( row, 0, parentIndex );
362 QgsProcessingToolboxModelNode *parentNode =
nullptr;
363 if ( !isTopLevelProvider( provider->
id() ) )
365 auto node = std::make_unique<QgsProcessingToolboxModelProviderNode>( provider );
366 parentNode = node.get();
367 mRootNode->addChildNode( node.release() );
371 parentNode = mRootNode.get();
374 const QList<const QgsProcessingAlgorithm *> algorithms = provider->
algorithms();
375 for (
const QgsProcessingAlgorithm *
algorithm : algorithms )
377 auto algorithmNode = std::make_unique<QgsProcessingToolboxModelAlgorithmNode>(
algorithm );
380 if ( !groupId.isEmpty() )
383 QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
388 parentNode->addChildNode( groupNode );
390 groupNode->addChildNode( algorithmNode.release() );
396 parentNode->addChildNode( algorithmNode.release() );
401bool QgsProcessingToolboxModel::isTopLevelProvider(
const QString &providerId )
403 return providerId ==
"qgis"_L1 || providerId ==
"native"_L1 || providerId ==
"3d"_L1 || providerId ==
"pdal"_L1;
408 return u
"<p><b>%1</b></p>%2<p>%3</p>%4"_s.arg(
411 QObject::tr(
"Algorithm ID: ‘%1’" ).arg( u
"<i>%1</i>"_s.arg(
algorithm->
id() ) ),
418 if ( !
index.isValid() )
419 return Qt::ItemFlags();
421 return QAbstractItemModel::flags(
index );
426 if ( !
index.isValid() )
432 return static_cast<int>( node->nodeType() );
437 bool isRecentNode =
false;
439 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Recent;
441 bool isFavoriteNode =
false;
443 isFavoriteNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Favorite;
445 bool isParameterGroupNode =
false;
447 isParameterGroupNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::ParameterGroup;
450 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast<QgsProcessingToolboxModelGroupNode *>(
index2node(
index ) );
456 case Qt::DisplayRole:
458 switch (
index.column() )
462 return provider->
name();
465 else if ( paramType )
466 return paramType->
name();
467 else if ( groupNode )
468 return groupNode->name();
469 else if ( isRecentNode )
470 return tr(
"Recently used" );
471 else if ( isFavoriteNode )
472 return tr(
"Favorites" );
473 else if ( isParameterGroupNode )
474 return tr(
"Input parameters" );
484 case Qt::ToolTipRole:
490 else if ( paramType )
492 else if ( groupNode )
493 return groupNode->name();
494 else if ( isParameterGroupNode )
495 return tr(
"Input parameters used in the modeler" );
500 case Qt::ForegroundRole:
503 return QBrush( QColor( Qt::red ) );
508 case Qt::DecorationRole:
510 switch (
index.column() )
515 return provider->
icon();
522 else if ( paramType )
524 else if ( isRecentNode )
526 else if ( isFavoriteNode )
528 else if ( isParameterGroupNode )
530 else if ( !
index.parent().isValid() )
544 switch (
index.column() )
549 return static_cast<int>(
algorithm->flags() );
560 switch (
index.column() )
565 return static_cast<int>( provider->
flags() );
580 switch (
index.column() )
596 switch (
index.column() )
612 switch (
index.column() )
628 switch (
index.column() )
643 switch (
index.column() )
648 return paramType->
id();
671 return n->children().count();
681 if ( !hasIndex( row, column,
parent ) )
682 return QModelIndex();
686 return QModelIndex();
688 return createIndex( row, column,
static_cast<QObject *
>( n->children().at( row ) ) );
693 if ( !child.isValid() )
694 return QModelIndex();
696 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
703 return QModelIndex();
709 if ( indexes.isEmpty() )
715 QByteArray encodedData;
716 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
718 auto mimeData = std::make_unique<QMimeData>();
724 mimeData->setData( u
"application/x-vnd.qgis.qgis.algorithmid"_s, encodedData );
729 QByteArray encodedData;
730 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
732 auto mimeData = std::make_unique<QMimeData>();
736 stream << paramType->
id();
738 mimeData->setData( u
"application/x-vnd.qgis.qgis.parametertypeid"_s, encodedData );
747 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
750 return qobject_cast<QgsProcessingToolboxModelProviderNode *>( n )->provider();
756 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
759 return qobject_cast<QgsProcessingToolboxModelProviderNode *>( n )->providerId();
765 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Algorithm )
768 return qobject_cast<QgsProcessingToolboxModelAlgorithmNode *>( n )->algorithm();
774 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Algorithm );
780 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Parameter );
786 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Parameter )
789 return qobject_cast<QgsProcessingToolboxModelParameterNode *>( n )->parameterType();
794 std::function<QModelIndex(
const QModelIndex &
parent,
const QString &providerId )> findIndex = [&](
const QModelIndex &
parent,
const QString &providerId ) -> QModelIndex {
799 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
802 QModelIndex checkChildren = findIndex( current, providerId );
803 if ( checkChildren.isValid() )
804 return checkChildren;
806 return QModelIndex();
809 return findIndex( QModelIndex(), providerId );
814 Q_ASSERT( parentNode );
816 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
817 if ( !grandParentNode )
818 return QModelIndex();
820 int row = grandParentNode->children().indexOf( parentNode );
821 Q_ASSERT( row >= 0 );
823 return createIndex( row, 0,
static_cast<QObject *
>( parentNode ) );
831 QObject *parent,
QgsProcessingRegistry *registry, QgsProcessingRecentAlgorithmLog *recentLog, QgsProcessingFavoriteAlgorithmManager *favoriteManager
833 : QSortFilterProxyModel( parent )
836 setSourceModel( mModel );
837 setDynamicSortFilter(
true );
838 setSortLocaleAware(
true );
839 setFilterCaseSensitivity( Qt::CaseInsensitive );
864 mInPlaceLayer = layer;
871 mFilterString = filter;
877 QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
878 if ( mModel->isAlgorithm( sourceIndex ) )
885 if ( !mFilterString.trimmed().isEmpty() )
892 QStringList parentText;
893 QModelIndex parent = sourceIndex.parent();
894 while ( parent.isValid() )
896 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
897 if ( !parentParts.empty() )
898 parentText.append( parentParts );
899 parent = parent.parent();
902 QStringList partsToSearch;
903 partsToSearch << sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
904 partsToSearch << algId << algName;
905 partsToSearch.append( algTags );
906 if ( !shortDesc.isEmpty() )
907 partsToSearch.append( shortDesc.split(
' ' ) );
908 partsToSearch.append( parentText );
910 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
911 for (
const QString &part : partsToMatch )
915 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
932 if ( !supportsInPlace )
945 return !isHiddenFromModeler;
951 return !isHiddenFromToolbox;
955 if ( mModel->isParameter( sourceIndex ) )
963 if ( !mFilterString.trimmed().isEmpty() )
965 QStringList partsToSearch;
966 partsToSearch << sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
969 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
970 for (
const QString &part : partsToMatch )
974 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
989 bool hasChildren =
false;
991 int count = sourceModel()->rowCount( sourceIndex );
992 for (
int i = 0; i < count; ++i )
1006 QgsProcessingToolboxModelNode::NodeType leftType =
static_cast<QgsProcessingToolboxModelNode::NodeType
>(
1009 QgsProcessingToolboxModelNode::NodeType rightType =
static_cast<QgsProcessingToolboxModelNode::NodeType
>(
1013 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Recent )
1015 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Recent )
1017 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Favorite )
1019 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Favorite )
1021 else if ( leftType != rightType )
1023 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Provider )
1025 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Provider )
1027 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Group )
1034 bool isRecentNode =
false;
1035 QModelIndex parent = left.parent();
1036 while ( parent.isValid() )
1040 isRecentNode =
true;
1043 parent = parent.parent();
1047 return left.row() < right.row();
1051 QString leftStr = sourceModel()->data( left ).toString();
1052 QString rightStr = sourceModel()->data( right ).toString();
1053 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
1058 if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
1060 QModelIndex sourceIndex = mapToSource( index );
1064 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
1065 QColor fadedTextColor = brush.color();
1066 fadedTextColor.setAlpha( 100 );
1067 brush.setColor( fadedTextColor );
1071 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.
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 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 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.
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.
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