25 #ifdef ENABLE_MODELTEST
26 #include "modeltest.h"
35 QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
40 QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
42 return mChildren.takeAt( mChildren.indexOf( node ) );
45 QgsProcessingToolboxModelGroupNode *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 )
59 void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
64 Q_ASSERT( !node->mParent );
67 mChildren.append( node );
70 void QgsProcessingToolboxModelNode::deleteChildren()
72 qDeleteAll( mChildren );
80 QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode(
QgsProcessingProvider *provider )
81 : mProviderId( provider->id() )
82 , mProvider( provider )
94 QgsProcessingToolboxModelGroupNode::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(); } );
133 void 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 );
159 void 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() );
215 void QgsProcessingToolboxModel::providerAdded(
const QString &
id )
224 if ( !isTopLevelProvider(
id ) )
227 beginInsertRows( QModelIndex(), previousRowCount, previousRowCount );
228 addProvider( provider );
236 addProvider( provider );
241 void 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() );
312 bool QgsProcessingToolboxModel::isTopLevelProvider(
const QString &providerId )
314 return providerId == QLatin1String(
"qgis" ) ||
315 providerId == QLatin1String(
"native" ) ||
316 providerId == QLatin1String(
"3d" );
321 return QStringLiteral(
"<p><b>%1</b></p>%2<p>%3</p>%4" ).arg(
324 QObject::tr(
"Algorithm ID: ‘%1’" ).arg( QStringLiteral(
"<i>%1</i>" ).arg(
algorithm->
id() ) ),
331 if ( !
index.isValid() )
332 return Qt::ItemFlags();
334 return QAbstractItemModel::flags(
index );
339 if ( !
index.isValid() )
345 return node->nodeType();
350 bool isRecentNode =
false;
352 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeRecent;
355 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >(
index2node(
index ) );
360 case Qt::DisplayRole:
362 switch (
index.column() )
366 return provider->
name();
369 else if ( groupNode )
370 return groupNode->name();
371 else if ( isRecentNode )
372 return tr(
"Recently used" );
382 case Qt::ToolTipRole:
388 else if ( groupNode )
389 return groupNode->name();
394 case Qt::ForegroundRole:
397 return QBrush( QColor( Qt::red ) );
402 case Qt::DecorationRole:
404 switch (
index.column() )
409 return provider->
icon();
416 else if ( isRecentNode )
418 else if ( !
index.parent().isValid() )
432 switch (
index.column() )
448 switch (
index.column() )
453 return static_cast< int >( provider->
flags() );
468 switch (
index.column() )
484 switch (
index.column() )
500 switch (
index.column() )
516 switch (
index.column() )
545 return n->children().count();
555 if ( !hasIndex( row, column,
parent ) )
556 return QModelIndex();
560 return QModelIndex();
562 return createIndex( row, column,
static_cast<QObject *
>( n->children().at( row ) ) );
567 if ( !child.isValid() )
568 return QModelIndex();
570 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
577 return QModelIndex();
583 if ( !indexes.isEmpty() &&
isAlgorithm( indexes.at( 0 ) ) )
585 QByteArray encodedData;
586 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
588 std::unique_ptr< QMimeData >
mimeData = std::make_unique< QMimeData >();
594 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
603 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
606 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->provider();
612 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
615 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->providerId();
621 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeAlgorithm )
624 return qobject_cast< QgsProcessingToolboxModelAlgorithmNode * >( n )->algorithm();
630 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeAlgorithm );
635 std::function< QModelIndex(
const QModelIndex &
parent,
const QString &providerId ) > findIndex = [&](
const QModelIndex &
parent,
const QString & providerId )->QModelIndex
641 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
644 QModelIndex checkChildren = findIndex( current, providerId );
645 if ( checkChildren.isValid() )
646 return checkChildren;
648 return QModelIndex();
651 return findIndex( QModelIndex(), providerId );
656 Q_ASSERT( parentNode );
658 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
659 if ( !grandParentNode )
660 return QModelIndex();
662 int row = grandParentNode->children().indexOf( parentNode );
663 Q_ASSERT( row >= 0 );
665 return createIndex( row, 0,
static_cast<QObject *
>( parentNode ) );
673 QgsProcessingRecentAlgorithmLog *recentLog )
674 : QSortFilterProxyModel( parent )
677 setSourceModel( mModel );
678 setDynamicSortFilter(
true );
679 setSortLocaleAware(
true );
680 setFilterCaseSensitivity( Qt::CaseInsensitive );
704 mInPlaceLayer = layer;
711 mFilterString = filter;
717 QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
724 if ( !mFilterString.trimmed().isEmpty() )
731 QStringList parentText;
732 QModelIndex parent = sourceIndex.parent();
733 while ( parent.isValid() )
735 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
736 if ( !parentParts.empty() )
737 parentText.append( parentParts );
738 parent = parent.parent();
741 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
743 QStringList partsToSearch = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
744 partsToSearch << algId << algName;
745 partsToSearch.append( algTags );
746 if ( !shortDesc.isEmpty() )
747 partsToSearch.append( shortDesc.split(
' ' ) );
748 partsToSearch.append( parentText );
750 for (
const QString &part : partsToMatch )
753 for (
const QString &partToSearch : std::as_const( partsToSearch ) )
755 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
769 if ( !supportsInPlace )
781 return !isHiddenFromModeler;
786 return !isHiddenFromToolbox;
791 bool hasChildren =
false;
793 int count = sourceModel()->rowCount( sourceIndex );
794 for (
int i = 0; i < count; ++i )
811 if ( leftType == QgsProcessingToolboxModelNode::NodeRecent )
813 else if ( rightType == QgsProcessingToolboxModelNode::NodeRecent )
815 else if ( leftType != rightType )
817 if ( leftType == QgsProcessingToolboxModelNode::NodeProvider )
819 else if ( rightType == QgsProcessingToolboxModelNode::NodeProvider )
821 else if ( leftType == QgsProcessingToolboxModelNode::NodeGroup )
828 bool isRecentNode =
false;
829 QModelIndex parent = left.parent();
830 while ( parent.isValid() )
837 parent = parent.parent();
841 return left.row() < right.row();
846 QString leftStr = sourceModel()->data( left ).toString();
847 QString rightStr = sourceModel()->data( right ).toString();
848 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
853 if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
855 QModelIndex sourceIndex = mapToSource( index );
859 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
860 QColor fadedTextColor = brush.color();
861 fadedTextColor.setAlpha( 100 );
862 brush.setColor( fadedTextColor );
866 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