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" ) ||
395 providerId == QLatin1String(
"native" ) ||
396 providerId == QLatin1String(
"3d" ) ||
397 providerId == QLatin1String(
"pdal" );
402 return QStringLiteral(
"<p><b>%1</b></p>%2<p>%3</p>%4" ).arg(
405 QObject::tr(
"Algorithm ID: ‘%1’" ).arg( QStringLiteral(
"<i>%1</i>" ).arg(
algorithm->id() ) ),
406 (
algorithm->
flags() &
Qgis::ProcessingAlgorithmFlag::KnownIssues ) ? QStringLiteral(
"<b style=\"color:red\">%1</b>" ).arg( QObject::tr(
"Warning: Algorithm has known issues" ) ) : QString()
412 if ( !
index.isValid() )
413 return Qt::ItemFlags();
415 return QAbstractItemModel::flags(
index );
420 if ( !
index.isValid() )
426 return static_cast< int >( node->nodeType() );
431 bool isRecentNode =
false;
433 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Recent;
435 bool isFavoriteNode =
false;
437 isFavoriteNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Favorite;
440 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >(
index2node(
index ) );
445 case Qt::DisplayRole:
447 switch (
index.column() )
451 return provider->
name();
454 else if ( groupNode )
455 return groupNode->name();
456 else if ( isRecentNode )
457 return tr(
"Recently used" );
458 else if ( isFavoriteNode )
459 return tr(
"Favorites" );
469 case Qt::ToolTipRole:
475 else if ( groupNode )
476 return groupNode->name();
481 case Qt::ForegroundRole:
484 return QBrush( QColor( Qt::red ) );
489 case Qt::DecorationRole:
491 switch (
index.column() )
496 return provider->
icon();
503 else if ( isRecentNode )
505 else if ( isFavoriteNode )
507 else if ( !
index.parent().isValid() )
521 switch (
index.column() )
537 switch (
index.column() )
542 return static_cast< int >( provider->
flags() );
557 switch (
index.column() )
573 switch (
index.column() )
589 switch (
index.column() )
605 switch (
index.column() )
634 return n->children().count();
644 if ( !hasIndex( row, column,
parent ) )
645 return QModelIndex();
649 return QModelIndex();
651 return createIndex( row, column,
static_cast<QObject *
>( n->children().at( row ) ) );
656 if ( !child.isValid() )
657 return QModelIndex();
659 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
666 return QModelIndex();
672 if ( !indexes.isEmpty() &&
isAlgorithm( indexes.at( 0 ) ) )
674 QByteArray encodedData;
675 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
677 std::unique_ptr< QMimeData >
mimeData = std::make_unique< QMimeData >();
683 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
692 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
695 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->provider();
701 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
704 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->providerId();
710 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Algorithm )
713 return qobject_cast< QgsProcessingToolboxModelAlgorithmNode * >( n )->algorithm();
719 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Algorithm );
724 std::function< QModelIndex(
const QModelIndex &
parent,
const QString &providerId ) > findIndex = [&](
const QModelIndex &
parent,
const QString & providerId )->QModelIndex
730 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
733 QModelIndex checkChildren = findIndex( current, providerId );
734 if ( checkChildren.isValid() )
735 return checkChildren;
737 return QModelIndex();
740 return findIndex( QModelIndex(), providerId );
745 Q_ASSERT( parentNode );
747 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
748 if ( !grandParentNode )
749 return QModelIndex();
751 int row = grandParentNode->children().indexOf( parentNode );
752 Q_ASSERT( row >= 0 );
754 return createIndex( row, 0,
static_cast<QObject *
>( parentNode ) );
762 QgsProcessingRecentAlgorithmLog *recentLog, QgsProcessingFavoriteAlgorithmManager *favoriteManager )
763 : QSortFilterProxyModel( parent )
766 setSourceModel( mModel );
767 setDynamicSortFilter(
true );
768 setSortLocaleAware(
true );
769 setFilterCaseSensitivity( Qt::CaseInsensitive );
794 mInPlaceLayer = layer;
801 mFilterString = filter;
807 QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
814 if ( !mFilterString.trimmed().isEmpty() )
821 QStringList parentText;
822 QModelIndex parent = sourceIndex.parent();
823 while ( parent.isValid() )
825 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
826 if ( !parentParts.empty() )
827 parentText.append( parentParts );
828 parent = parent.parent();
831 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
833 QStringList partsToSearch = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
834 partsToSearch << algId << algName;
835 partsToSearch.append( algTags );
836 if ( !shortDesc.isEmpty() )
837 partsToSearch.append( shortDesc.split(
' ' ) );
838 partsToSearch.append( parentText );
840 for (
const QString &part : partsToMatch )
843 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
845 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
859 if ( !supportsInPlace )
871 return !isHiddenFromModeler;
876 return !isHiddenFromToolbox;
881 bool hasChildren =
false;
883 int count = sourceModel()->rowCount( sourceIndex );
884 for (
int i = 0; i < count; ++i )
901 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Recent )
903 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Recent )
905 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Favorite )
907 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Favorite )
909 else if ( leftType != rightType )
911 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Provider )
913 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Provider )
915 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Group )
922 bool isRecentNode =
false;
923 QModelIndex parent = left.parent();
924 while ( parent.isValid() )
931 parent = parent.parent();
935 return left.row() < right.row();
939 QString leftStr = sourceModel()->data( left ).toString();
940 QString rightStr = sourceModel()->data( right ).toString();
941 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
946 if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
948 QModelIndex sourceIndex = mapToSource( index );
952 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
953 QColor fadedTextColor = brush.color();
954 fadedTextColor.setAlpha( 100 );
955 brush.setColor( fadedTextColor );
959 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