23 #ifdef ENABLE_MODELTEST 24 #include "modeltest.h" 33 QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
38 QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
40 return mChildren.takeAt( mChildren.indexOf( node ) );
43 QgsProcessingToolboxModelGroupNode *QgsProcessingToolboxModelNode::getChildGroupNode(
const QString &groupId )
45 for ( QgsProcessingToolboxModelNode *node : qgis::as_const( mChildren ) )
47 if ( node->nodeType() == NodeGroup )
49 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >( node );
50 if ( groupNode && groupNode->id() == groupId )
57 void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
62 Q_ASSERT( !node->mParent );
65 mChildren.append( node );
68 void QgsProcessingToolboxModelNode::deleteChildren()
70 qDeleteAll( mChildren );
78 QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode(
QgsProcessingProvider *provider )
79 : mProviderId( provider->id() )
80 , mProvider( provider )
92 QgsProcessingToolboxModelGroupNode::QgsProcessingToolboxModelGroupNode(
const QString &
id,
const QString &name )
102 : mAlgorithm( algorithm )
117 : QAbstractItemModel( parent )
118 , mRegistry( registry ? registry :
QgsApplication::processingRegistry() )
119 , mRecentLog( recentLog )
120 , mRootNode( qgis::make_unique< QgsProcessingToolboxModelGroupNode >( QString(), QString() ) )
125 connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed,
this, [ = ] { repopulateRecentAlgorithms(); } );
131 void QgsProcessingToolboxModel::rebuild()
135 mRootNode->deleteChildren();
136 mRecentNode =
nullptr;
140 std::unique_ptr< QgsProcessingToolboxModelRecentNode > recentNode = qgis::make_unique< QgsProcessingToolboxModelRecentNode >();
141 mRecentNode = recentNode.get();
142 mRootNode->addChildNode( recentNode.release() );
143 repopulateRecentAlgorithms(
true );
148 const QList< QgsProcessingProvider * > providers = mRegistry->providers();
151 addProvider( provider );
157 void QgsProcessingToolboxModel::repopulateRecentAlgorithms(
bool resetting )
159 if ( !mRecentNode || !mRecentLog )
162 QModelIndex recentIndex =
index( 0, 0 );
163 const int prevCount =
rowCount( recentIndex );
164 if ( !resetting && prevCount > 0 )
166 beginRemoveRows( recentIndex, 0, prevCount - 1 );
167 mRecentNode->deleteChildren();
178 const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
179 QList< const QgsProcessingAlgorithm * > recentAlgorithms;
180 recentAlgorithms.reserve( recentAlgIds.count() );
181 for (
const QString &
id : recentAlgIds )
188 if ( recentAlgorithms.empty() )
197 beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
202 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = qgis::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
203 mRecentNode->addChildNode( algorithmNode.release() );
213 void QgsProcessingToolboxModel::providerAdded(
const QString &
id )
222 if ( !isTopLevelProvider(
id ) )
225 beginInsertRows( QModelIndex(), previousRowCount, previousRowCount );
226 addProvider( provider );
234 addProvider( provider );
239 void QgsProcessingToolboxModel::providerRemoved(
const QString & )
248 if ( !index.isValid() )
249 return mRootNode.get();
251 QObject *obj =
reinterpret_cast<QObject *
>( index.internalPointer() );
252 return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
257 if ( !node || !node->parent() )
258 return QModelIndex();
260 QModelIndex parentIndex =
node2index( node->parent() );
262 int row = node->parent()->children().indexOf( node );
263 Q_ASSERT( row >= 0 );
264 return index( row, 0, parentIndex );
274 QgsProcessingToolboxModelNode *parentNode =
nullptr;
275 if ( !isTopLevelProvider( provider->
id() ) )
277 std::unique_ptr< QgsProcessingToolboxModelProviderNode > node = qgis::make_unique< QgsProcessingToolboxModelProviderNode >( provider );
278 parentNode = node.get();
279 mRootNode->addChildNode( node.release() );
283 parentNode = mRootNode.get();
286 const QList< const QgsProcessingAlgorithm * > algorithms = provider->
algorithms();
289 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = qgis::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
292 if ( !groupId.isEmpty() )
294 QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
298 parentNode->addChildNode( groupNode );
300 groupNode->addChildNode( algorithmNode.release() );
305 parentNode->addChildNode( algorithmNode.release() );
310 bool QgsProcessingToolboxModel::isTopLevelProvider(
const QString &providerId )
312 return providerId == QLatin1String(
"qgis" ) ||
313 providerId == QLatin1String(
"native" ) ||
314 providerId == QLatin1String(
"3d" );
319 return QStringLiteral(
"<p><b>%1</b></p>%2<p>%3</p>" ).arg(
322 QObject::tr(
"Algorithm ID: ‘%1’" ).arg( QStringLiteral(
"<i>%1</i>" ).arg( algorithm->
id() ) )
328 if ( !index.isValid() )
331 return QAbstractItemModel::flags( index );
336 if ( !index.isValid() )
341 if ( QgsProcessingToolboxModelNode *node =
index2node( index ) )
342 return node->nodeType();
347 bool isRecentNode =
false;
348 if ( QgsProcessingToolboxModelNode *node =
index2node( index ) )
349 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeRecent;
352 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >(
index2node( index ) );
357 case Qt::DisplayRole:
359 switch ( index.column() )
363 return provider->
name();
364 else if ( algorithm )
365 return algorithm->displayName();
366 else if ( groupNode )
367 return groupNode->name();
368 else if ( isRecentNode )
369 return tr(
"Recently used" );
379 case Qt::ToolTipRole:
383 else if ( algorithm )
384 return toolTipForAlgorithm( algorithm );
385 else if ( groupNode )
386 return groupNode->name();
391 case Qt::DecorationRole:
392 switch ( index.column() )
397 return provider->
icon();
398 else if ( algorithm )
399 return algorithm->icon();
400 else if ( isRecentNode )
402 else if ( !index.parent().isValid() )
415 switch ( index.column() )
420 return static_cast< int >( algorithm->flags() );
431 switch ( index.column() )
436 return algorithm->id();
447 switch ( index.column() )
452 return algorithm->name();
463 switch ( index.column() )
468 return algorithm->tags();
479 switch ( index.column() )
484 return algorithm->shortDescription();
503 QgsProcessingToolboxModelNode *n =
index2node( parent );
507 return n->children().count();
517 if ( !hasIndex( row, column, parent ) )
518 return QModelIndex();
520 QgsProcessingToolboxModelNode *n =
index2node( parent );
522 return QModelIndex();
524 return createIndex( row, column, static_cast<QObject *>( n->children().at( row ) ) );
529 if ( !child.isValid() )
530 return QModelIndex();
532 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
539 return QModelIndex();
545 if ( !indexes.isEmpty() &&
isAlgorithm( indexes.at( 0 ) ) )
547 QByteArray encodedData;
548 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
550 std::unique_ptr< QMimeData >
mimeData = qgis::make_unique< QMimeData >();
554 stream << algorithm->
id();
556 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
557 return mimeData.release();
564 QgsProcessingToolboxModelNode *n =
index2node( index );
565 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
568 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->provider();
573 QgsProcessingToolboxModelNode *n =
index2node( index );
574 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
577 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->providerId();
582 QgsProcessingToolboxModelNode *n =
index2node( index );
583 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeAlgorithm )
586 return qobject_cast< QgsProcessingToolboxModelAlgorithmNode * >( n )->
algorithm();
591 QgsProcessingToolboxModelNode *n =
index2node( index );
592 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeAlgorithm );
597 std::function< QModelIndex( const QModelIndex &parent, const QString &providerId ) > findIndex = [&](
const QModelIndex &
parent,
const QString & providerId )->QModelIndex
599 for (
int row = 0; row <
rowCount( parent ); ++row )
601 QModelIndex current =
index( row, 0, parent );
603 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
606 QModelIndex checkChildren = findIndex( current, providerId );
607 if ( checkChildren.isValid() )
608 return checkChildren;
610 return QModelIndex();
613 return findIndex( QModelIndex(), providerId );
618 Q_ASSERT( parentNode );
620 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
621 if ( !grandParentNode )
622 return QModelIndex();
624 int row = grandParentNode->children().indexOf( parentNode );
625 Q_ASSERT( row >= 0 );
627 return createIndex( row, 0, static_cast<QObject *>( parentNode ) );
635 QgsProcessingRecentAlgorithmLog *recentLog )
636 : QSortFilterProxyModel( parent )
639 setSourceModel( mModel );
640 setDynamicSortFilter(
true );
641 setSortLocaleAware(
true );
642 setFilterCaseSensitivity( Qt::CaseInsensitive );
661 mInPlaceLayer = layer;
668 mFilterString = filter;
674 QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
677 if ( !mFilterString.trimmed().isEmpty() )
684 QStringList parentText;
685 QModelIndex parent = sourceIndex.parent();
686 while ( parent.isValid() )
688 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
689 if ( !parentParts.empty() )
690 parentText.append( parentParts );
691 parent = parent.parent();
694 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
696 QStringList partsToSearch = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
697 partsToSearch << algId << algName;
698 partsToSearch.append( algTags );
699 if ( !shortDesc.isEmpty() )
700 partsToSearch.append( shortDesc.split(
' ' ) );
701 partsToSearch.append( parentText );
703 for (
const QString &part : partsToMatch )
706 for (
const QString &partToSearch : qgis::as_const( partsToSearch ) )
708 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
722 if ( !supportsInPlace )
734 return !isHiddenFromModeler;
739 return !isHiddenFromToolbox;
744 bool hasChildren =
false;
746 int count = sourceModel()->rowCount( sourceIndex );
747 for (
int i = 0; i < count; ++i )
764 if ( leftType == QgsProcessingToolboxModelNode::NodeRecent )
766 else if ( rightType == QgsProcessingToolboxModelNode::NodeRecent )
768 else if ( leftType != rightType )
770 if ( leftType == QgsProcessingToolboxModelNode::NodeProvider )
772 else if ( rightType == QgsProcessingToolboxModelNode::NodeProvider )
774 else if ( leftType == QgsProcessingToolboxModelNode::NodeGroup )
781 bool isRecentNode =
false;
782 QModelIndex parent = left.parent();
783 while ( parent.isValid() )
790 parent = parent.parent();
794 return left.row() < right.row();
799 QString leftStr = sourceModel()->data( left ).toString();
800 QString rightStr = sourceModel()->data( right ).toString();
801 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
Algorithm should be hidden from the toolbox.
QString id() const
Returns the unique ID for the algorithm, which is a combination of the algorithm provider's ID and th...
Extends QApplication to provide access to QGIS specific resources such as theme paths, database paths etc.
void providerAdded(const QString &id)
Emitted when a provider has been added to the registry.
virtual QString name() const =0
Returns the provider name, which is used to describe the provider within the GUI. ...
QList< const QgsProcessingAlgorithm *> algorithms() const
Returns a list of algorithms supplied by this provider.
virtual QString group() const
Returns the name of the group this algorithm belongs to.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Abstract base class for processing providers.
Abstract base class for processing algorithms.
virtual bool supportInPlaceEdit(const QgsMapLayer *layer) const
Checks whether this algorithm supports in-place editing on the given layer Default implementation ret...
void providerRemoved(const QString &id)
Emitted when a provider is removed from the registry.
virtual QString id() const =0
Returns the unique provider id, used for identifying the provider.
Algorithm should be hidden from the modeler.
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
Algorithm supports in-place editing.
Registry for various processing components, including providers, algorithms and various parameters an...
virtual QString displayName() const =0
Returns the translated algorithm name, which should be used for any user-visible display of the algor...
virtual QString shortDescription() const
Returns an optional translated short description of the algorithm.
virtual QString groupId() const
Returns the unique ID of the group this algorithm belongs to.
virtual QIcon icon() const
Returns an icon for the provider.
virtual QString longName() const
Returns the longer version of the provider name, which can include extra details such as version numb...
Represents a vector layer which manages a vector based data sets.
void algorithmsLoaded()
Emitted when the provider has loaded (or refreshed) its list of available algorithms.