25#ifdef ENABLE_MODELTEST
35QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
40QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
42 return mChildren.takeAt( mChildren.indexOf( node ) );
45QgsProcessingToolboxModelGroupNode *QgsProcessingToolboxModelNode::getChildGroupNode(
const QString &groupId )
47 for ( QgsProcessingToolboxModelNode *node : std::as_const( mChildren ) )
49 if ( node->nodeType() == NodeType::Group )
51 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >( node );
52 if ( groupNode && groupNode->id() == groupId )
59void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
64 Q_ASSERT( !node->mParent );
67 mChildren.append( node );
70void QgsProcessingToolboxModelNode::deleteChildren()
72 qDeleteAll( mChildren );
80QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode(
QgsProcessingProvider *provider )
81 : mProviderId( provider->id() )
82 , mProvider( provider )
94QgsProcessingToolboxModelGroupNode::QgsProcessingToolboxModelGroupNode(
const QString &
id,
const QString &name )
119 : QAbstractItemModel( parent )
120 , mRegistry( registry ? registry :
QgsApplication::processingRegistry() )
121 , mRecentLog( recentLog )
122 , mRootNode( std::make_unique< QgsProcessingToolboxModelGroupNode >( QString(), QString() ) )
127 connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed,
this, [ = ] { repopulateRecentAlgorithms(); } );
133void QgsProcessingToolboxModel::rebuild()
137 mRootNode->deleteChildren();
138 mRecentNode =
nullptr;
142 std::unique_ptr< QgsProcessingToolboxModelRecentNode > recentNode = std::make_unique< QgsProcessingToolboxModelRecentNode >();
144 mRecentNode = recentNode.get();
145 mRootNode->addChildNode( recentNode.release() );
146 repopulateRecentAlgorithms(
true );
151 const QList< QgsProcessingProvider * > providers = mRegistry->providers();
154 addProvider( provider );
160void QgsProcessingToolboxModel::repopulateRecentAlgorithms(
bool resetting )
162 if ( !mRecentNode || !mRecentLog )
165 QModelIndex recentIndex =
index( 0, 0 );
166 const int prevCount =
rowCount( recentIndex );
167 if ( !resetting && prevCount > 0 )
169 beginRemoveRows( recentIndex, 0, prevCount - 1 );
170 mRecentNode->deleteChildren();
181 const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
182 QList< const QgsProcessingAlgorithm * > recentAlgorithms;
183 recentAlgorithms.reserve( recentAlgIds.count() );
184 for (
const QString &
id : recentAlgIds )
191 if ( recentAlgorithms.empty() )
200 beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
205 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = std::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
206 mRecentNode->addChildNode( algorithmNode.release() );
216void QgsProcessingToolboxModel::providerAdded(
const QString &
id )
225 if ( !isTopLevelProvider(
id ) )
228 beginInsertRows( QModelIndex(), previousRowCount, previousRowCount );
229 addProvider( provider );
237 addProvider( provider );
242void QgsProcessingToolboxModel::providerRemoved(
const QString & )
251 if ( !
index.isValid() )
252 return mRootNode.get();
254 QObject *obj =
reinterpret_cast<QObject *
>(
index.internalPointer() );
255 return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
260 if ( !node || !node->parent() )
261 return QModelIndex();
263 QModelIndex parentIndex =
node2index( node->parent() );
265 int row = node->parent()->children().indexOf( node );
266 Q_ASSERT( row >= 0 );
267 return index( row, 0, parentIndex );
277 QgsProcessingToolboxModelNode *parentNode =
nullptr;
278 if ( !isTopLevelProvider( provider->
id() ) )
280 std::unique_ptr< QgsProcessingToolboxModelProviderNode > node = std::make_unique< QgsProcessingToolboxModelProviderNode >( provider );
281 parentNode = node.get();
282 mRootNode->addChildNode( node.release() );
286 parentNode = mRootNode.get();
289 const QList< const QgsProcessingAlgorithm * > algorithms = provider->
algorithms();
292 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = std::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
295 if ( !groupId.isEmpty() )
298 QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
303 parentNode->addChildNode( groupNode );
305 groupNode->addChildNode( algorithmNode.release() );
311 parentNode->addChildNode( algorithmNode.release() );
316bool QgsProcessingToolboxModel::isTopLevelProvider(
const QString &providerId )
318 return providerId == QLatin1String(
"qgis" ) ||
319 providerId == QLatin1String(
"native" ) ||
320 providerId == QLatin1String(
"3d" ) ||
321 providerId == QLatin1String(
"pdal" );
326 return QStringLiteral(
"<p><b>%1</b></p>%2<p>%3</p>%4" ).arg(
329 QObject::tr(
"Algorithm ID: ‘%1’" ).arg( QStringLiteral(
"<i>%1</i>" ).arg(
algorithm->id() ) ),
330 (
algorithm->
flags() &
Qgis::ProcessingAlgorithmFlag::KnownIssues ) ? QStringLiteral(
"<b style=\"color:red\">%1</b>" ).arg( QObject::tr(
"Warning: Algorithm has known issues" ) ) : QString()
336 if ( !
index.isValid() )
337 return Qt::ItemFlags();
339 return QAbstractItemModel::flags(
index );
344 if ( !
index.isValid() )
350 return static_cast< int >( node->nodeType() );
355 bool isRecentNode =
false;
357 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeType::Recent;
360 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >(
index2node(
index ) );
365 case Qt::DisplayRole:
367 switch (
index.column() )
371 return provider->
name();
374 else if ( groupNode )
375 return groupNode->name();
376 else if ( isRecentNode )
377 return tr(
"Recently used" );
387 case Qt::ToolTipRole:
393 else if ( groupNode )
394 return groupNode->name();
399 case Qt::ForegroundRole:
402 return QBrush( QColor( Qt::red ) );
407 case Qt::DecorationRole:
409 switch (
index.column() )
414 return provider->
icon();
421 else if ( isRecentNode )
423 else if ( !
index.parent().isValid() )
437 switch (
index.column() )
453 switch (
index.column() )
458 return static_cast< int >( provider->
flags() );
473 switch (
index.column() )
489 switch (
index.column() )
505 switch (
index.column() )
521 switch (
index.column() )
550 return n->children().count();
560 if ( !hasIndex( row, column,
parent ) )
561 return QModelIndex();
565 return QModelIndex();
567 return createIndex( row, column,
static_cast<QObject *
>( n->children().at( row ) ) );
572 if ( !child.isValid() )
573 return QModelIndex();
575 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
582 return QModelIndex();
588 if ( !indexes.isEmpty() &&
isAlgorithm( indexes.at( 0 ) ) )
590 QByteArray encodedData;
591 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
593 std::unique_ptr< QMimeData >
mimeData = std::make_unique< QMimeData >();
599 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
608 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
611 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->provider();
617 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Provider )
620 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->providerId();
626 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeType::Algorithm )
629 return qobject_cast< QgsProcessingToolboxModelAlgorithmNode * >( n )->algorithm();
635 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeType::Algorithm );
640 std::function< QModelIndex(
const QModelIndex &
parent,
const QString &providerId ) > findIndex = [&](
const QModelIndex &
parent,
const QString & providerId )->QModelIndex
646 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
649 QModelIndex checkChildren = findIndex( current, providerId );
650 if ( checkChildren.isValid() )
651 return checkChildren;
653 return QModelIndex();
656 return findIndex( QModelIndex(), providerId );
661 Q_ASSERT( parentNode );
663 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
664 if ( !grandParentNode )
665 return QModelIndex();
667 int row = grandParentNode->children().indexOf( parentNode );
668 Q_ASSERT( row >= 0 );
670 return createIndex( row, 0,
static_cast<QObject *
>( parentNode ) );
678 QgsProcessingRecentAlgorithmLog *recentLog )
679 : QSortFilterProxyModel( parent )
682 setSourceModel( mModel );
683 setDynamicSortFilter(
true );
684 setSortLocaleAware(
true );
685 setFilterCaseSensitivity( Qt::CaseInsensitive );
709 mInPlaceLayer = layer;
716 mFilterString = filter;
722 QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
729 if ( !mFilterString.trimmed().isEmpty() )
736 QStringList parentText;
737 QModelIndex parent = sourceIndex.parent();
738 while ( parent.isValid() )
740 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
741 if ( !parentParts.empty() )
742 parentText.append( parentParts );
743 parent = parent.parent();
746 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
748 QStringList partsToSearch = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
749 partsToSearch << algId << algName;
750 partsToSearch.append( algTags );
751 if ( !shortDesc.isEmpty() )
752 partsToSearch.append( shortDesc.split(
' ' ) );
753 partsToSearch.append( parentText );
755 for (
const QString &part : partsToMatch )
758 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
760 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
774 if ( !supportsInPlace )
786 return !isHiddenFromModeler;
791 return !isHiddenFromToolbox;
796 bool hasChildren =
false;
798 int count = sourceModel()->rowCount( sourceIndex );
799 for (
int i = 0; i < count; ++i )
816 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Recent )
818 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Recent )
820 else if ( leftType != rightType )
822 if ( leftType == QgsProcessingToolboxModelNode::NodeType::Provider )
824 else if ( rightType == QgsProcessingToolboxModelNode::NodeType::Provider )
826 else if ( leftType == QgsProcessingToolboxModelNode::NodeType::Group )
833 bool isRecentNode =
false;
834 QModelIndex parent = left.parent();
835 while ( parent.isValid() )
842 parent = parent.parent();
846 return left.row() < right.row();
851 QString leftStr = sourceModel()->data( left ).toString();
852 QString rightStr = sourceModel()->data( right ).toString();
853 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
858 if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
860 QModelIndex sourceIndex = mapToSource( index );
864 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
865 QColor fadedTextColor = brush.color();
866 fadedTextColor.setAlpha( 100 );
867 brush.setColor( fadedTextColor );
871 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