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() )
534 #ifndef _MSC_VER // avoid warning
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 );