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() == NodeGroup )
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 >();
143 mRecentNode = recentNode.get();
144 mRootNode->addChildNode( recentNode.release() );
145 repopulateRecentAlgorithms(
true );
150 const QList< QgsProcessingProvider * > providers = mRegistry->providers();
153 addProvider( provider );
159void QgsProcessingToolboxModel::repopulateRecentAlgorithms(
bool resetting )
161 if ( !mRecentNode || !mRecentLog )
164 QModelIndex recentIndex =
index( 0, 0 );
165 const int prevCount =
rowCount( recentIndex );
166 if ( !resetting && prevCount > 0 )
168 beginRemoveRows( recentIndex, 0, prevCount - 1 );
169 mRecentNode->deleteChildren();
180 const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
181 QList< const QgsProcessingAlgorithm * > recentAlgorithms;
182 recentAlgorithms.reserve( recentAlgIds.count() );
183 for (
const QString &
id : recentAlgIds )
190 if ( recentAlgorithms.empty() )
199 beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
204 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = std::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
205 mRecentNode->addChildNode( algorithmNode.release() );
215void QgsProcessingToolboxModel::providerAdded(
const QString &
id )
224 if ( !isTopLevelProvider(
id ) )
227 beginInsertRows( QModelIndex(), previousRowCount, previousRowCount );
228 addProvider( provider );
236 addProvider( provider );
241void QgsProcessingToolboxModel::providerRemoved(
const QString & )
250 if ( !
index.isValid() )
251 return mRootNode.get();
253 QObject *obj =
reinterpret_cast<QObject *
>(
index.internalPointer() );
254 return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
259 if ( !node || !node->parent() )
260 return QModelIndex();
262 QModelIndex parentIndex =
node2index( node->parent() );
264 int row = node->parent()->children().indexOf( node );
265 Q_ASSERT( row >= 0 );
266 return index( row, 0, parentIndex );
276 QgsProcessingToolboxModelNode *parentNode =
nullptr;
277 if ( !isTopLevelProvider( provider->
id() ) )
279 std::unique_ptr< QgsProcessingToolboxModelProviderNode > node = std::make_unique< QgsProcessingToolboxModelProviderNode >( provider );
280 parentNode = node.get();
281 mRootNode->addChildNode( node.release() );
285 parentNode = mRootNode.get();
288 const QList< const QgsProcessingAlgorithm * > algorithms = provider->
algorithms();
291 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = std::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
294 if ( !groupId.isEmpty() )
296 QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
300 parentNode->addChildNode( groupNode );
302 groupNode->addChildNode( algorithmNode.release() );
307 parentNode->addChildNode( algorithmNode.release() );
312bool QgsProcessingToolboxModel::isTopLevelProvider(
const QString &providerId )
314 return providerId == QLatin1String(
"qgis" ) ||
315 providerId == QLatin1String(
"native" ) ||
316 providerId == QLatin1String(
"3d" ) ||
317 providerId == QLatin1String(
"pdal" );
322 return QStringLiteral(
"<p><b>%1</b></p>%2<p>%3</p>%4" ).arg(
325 QObject::tr(
"Algorithm ID: ‘%1’" ).arg( QStringLiteral(
"<i>%1</i>" ).arg(
algorithm->
id() ) ),
332 if ( !
index.isValid() )
333 return Qt::ItemFlags();
335 return QAbstractItemModel::flags(
index );
340 if ( !
index.isValid() )
346 return node->nodeType();
351 bool isRecentNode =
false;
353 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeRecent;
356 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >(
index2node(
index ) );
361 case Qt::DisplayRole:
363 switch (
index.column() )
367 return provider->
name();
370 else if ( groupNode )
371 return groupNode->name();
372 else if ( isRecentNode )
373 return tr(
"Recently used" );
383 case Qt::ToolTipRole:
389 else if ( groupNode )
390 return groupNode->name();
395 case Qt::ForegroundRole:
398 return QBrush( QColor( Qt::red ) );
403 case Qt::DecorationRole:
405 switch (
index.column() )
410 return provider->
icon();
417 else if ( isRecentNode )
419 else if ( !
index.parent().isValid() )
433 switch (
index.column() )
449 switch (
index.column() )
454 return static_cast< int >( provider->
flags() );
469 switch (
index.column() )
485 switch (
index.column() )
501 switch (
index.column() )
517 switch (
index.column() )
546 return n->children().count();
556 if ( !hasIndex( row, column,
parent ) )
557 return QModelIndex();
561 return QModelIndex();
563 return createIndex( row, column,
static_cast<QObject *
>( n->children().at( row ) ) );
568 if ( !child.isValid() )
569 return QModelIndex();
571 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
578 return QModelIndex();
584 if ( !indexes.isEmpty() &&
isAlgorithm( indexes.at( 0 ) ) )
586 QByteArray encodedData;
587 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
589 std::unique_ptr< QMimeData >
mimeData = std::make_unique< QMimeData >();
595 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
604 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
607 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->provider();
613 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
616 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->providerId();
622 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeAlgorithm )
625 return qobject_cast< QgsProcessingToolboxModelAlgorithmNode * >( n )->algorithm();
631 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeAlgorithm );
636 std::function< QModelIndex(
const QModelIndex &
parent,
const QString &providerId ) > findIndex = [&](
const QModelIndex &
parent,
const QString & providerId )->QModelIndex
642 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
645 QModelIndex checkChildren = findIndex( current, providerId );
646 if ( checkChildren.isValid() )
647 return checkChildren;
649 return QModelIndex();
652 return findIndex( QModelIndex(), providerId );
657 Q_ASSERT( parentNode );
659 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
660 if ( !grandParentNode )
661 return QModelIndex();
663 int row = grandParentNode->children().indexOf( parentNode );
664 Q_ASSERT( row >= 0 );
666 return createIndex( row, 0,
static_cast<QObject *
>( parentNode ) );
674 QgsProcessingRecentAlgorithmLog *recentLog )
675 : QSortFilterProxyModel( parent )
678 setSourceModel( mModel );
679 setDynamicSortFilter(
true );
680 setSortLocaleAware(
true );
681 setFilterCaseSensitivity( Qt::CaseInsensitive );
705 mInPlaceLayer = layer;
712 mFilterString = filter;
718 QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
725 if ( !mFilterString.trimmed().isEmpty() )
732 QStringList parentText;
733 QModelIndex parent = sourceIndex.parent();
734 while ( parent.isValid() )
736 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
737 if ( !parentParts.empty() )
738 parentText.append( parentParts );
739 parent = parent.parent();
742 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
744 QStringList partsToSearch = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
745 partsToSearch << algId << algName;
746 partsToSearch.append( algTags );
747 if ( !shortDesc.isEmpty() )
748 partsToSearch.append( shortDesc.split(
' ' ) );
749 partsToSearch.append( parentText );
751 for (
const QString &part : partsToMatch )
754 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
756 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
770 if ( !supportsInPlace )
782 return !isHiddenFromModeler;
787 return !isHiddenFromToolbox;
792 bool hasChildren =
false;
794 int count = sourceModel()->rowCount( sourceIndex );
795 for (
int i = 0; i < count; ++i )
812 if ( leftType == QgsProcessingToolboxModelNode::NodeRecent )
814 else if ( rightType == QgsProcessingToolboxModelNode::NodeRecent )
816 else if ( leftType != rightType )
818 if ( leftType == QgsProcessingToolboxModelNode::NodeProvider )
820 else if ( rightType == QgsProcessingToolboxModelNode::NodeProvider )
822 else if ( leftType == QgsProcessingToolboxModelNode::NodeGroup )
829 bool isRecentNode =
false;
830 QModelIndex parent = left.parent();
831 while ( parent.isValid() )
838 parent = parent.parent();
842 return left.row() < right.row();
847 QString leftStr = sourceModel()->data( left ).toString();
848 QString rightStr = sourceModel()->data( right ).toString();
849 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
854 if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
856 QModelIndex sourceIndex = mapToSource( index );
860 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
861 QColor fadedTextColor = brush.color();
862 fadedTextColor.setAlpha( 100 );
863 brush.setColor( fadedTextColor );
867 return QSortFilterProxyModel::data( index, role );
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...
@ FlagSupportsInPlaceEdits
Algorithm supports in-place editing.
@ FlagKnownIssues
Algorithm has known issues.
@ FlagHideFromToolbox
Algorithm should be hidden from the toolbox.
@ FlagHideFromModeler
Algorithm should be hidden from the modeler.
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.
QgsProcessingAlgorithm::Flags 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 QString name() const =0
Returns the provider name, which is used to describe the provider within the GUI.
@ FlagDeemphasiseSearchResults
Algorithms should be de-emphasised in the search results when searching for algorithms....
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...
virtual Flags flags() const
Returns the flags indicating how and when the provider operates and should be exposed to users.
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