24 #ifdef ENABLE_MODELTEST
25 #include "modeltest.h"
34 QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
39 QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
41 return mChildren.takeAt( mChildren.indexOf( node ) );
44 QgsProcessingToolboxModelGroupNode *QgsProcessingToolboxModelNode::getChildGroupNode(
const QString &groupId )
46 for ( QgsProcessingToolboxModelNode *node : qgis::as_const( mChildren ) )
48 if ( node->nodeType() == NodeGroup )
50 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >( node );
51 if ( groupNode && groupNode->id() == groupId )
58 void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
63 Q_ASSERT( !node->mParent );
66 mChildren.append( node );
69 void QgsProcessingToolboxModelNode::deleteChildren()
71 qDeleteAll( mChildren );
79 QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode(
QgsProcessingProvider *provider )
80 : mProviderId( provider->id() )
81 , mProvider( provider )
93 QgsProcessingToolboxModelGroupNode::QgsProcessingToolboxModelGroupNode(
const QString &
id,
const QString &name )
118 : QAbstractItemModel( parent )
119 , mRegistry( registry ? registry :
QgsApplication::processingRegistry() )
120 , mRecentLog( recentLog )
121 , mRootNode( qgis::make_unique< QgsProcessingToolboxModelGroupNode >( QString(), QString() ) )
126 connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed,
this, [ = ] { repopulateRecentAlgorithms(); } );
132 void QgsProcessingToolboxModel::rebuild()
136 mRootNode->deleteChildren();
137 mRecentNode =
nullptr;
141 std::unique_ptr< QgsProcessingToolboxModelRecentNode > recentNode = qgis::make_unique< QgsProcessingToolboxModelRecentNode >();
142 mRecentNode = recentNode.get();
143 mRootNode->addChildNode( recentNode.release() );
144 repopulateRecentAlgorithms(
true );
149 const QList< QgsProcessingProvider * > providers = mRegistry->providers();
152 addProvider( provider );
158 void QgsProcessingToolboxModel::repopulateRecentAlgorithms(
bool resetting )
160 if ( !mRecentNode || !mRecentLog )
163 QModelIndex recentIndex =
index( 0, 0 );
164 const int prevCount =
rowCount( recentIndex );
165 if ( !resetting && prevCount > 0 )
167 beginRemoveRows( recentIndex, 0, prevCount - 1 );
168 mRecentNode->deleteChildren();
179 const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
180 QList< const QgsProcessingAlgorithm * > recentAlgorithms;
181 recentAlgorithms.reserve( recentAlgIds.count() );
182 for (
const QString &
id : recentAlgIds )
189 if ( recentAlgorithms.empty() )
198 beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
203 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = qgis::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
204 mRecentNode->addChildNode( algorithmNode.release() );
214 void QgsProcessingToolboxModel::providerAdded(
const QString &
id )
223 if ( !isTopLevelProvider(
id ) )
226 beginInsertRows( QModelIndex(), previousRowCount, previousRowCount );
227 addProvider( provider );
235 addProvider( provider );
240 void QgsProcessingToolboxModel::providerRemoved(
const QString & )
249 if ( !
index.isValid() )
250 return mRootNode.get();
252 QObject *obj =
reinterpret_cast<QObject *
>(
index.internalPointer() );
253 return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
258 if ( !node || !node->parent() )
259 return QModelIndex();
261 QModelIndex parentIndex =
node2index( node->parent() );
263 int row = node->parent()->children().indexOf( node );
264 Q_ASSERT( row >= 0 );
265 return index( row, 0, parentIndex );
275 QgsProcessingToolboxModelNode *parentNode =
nullptr;
276 if ( !isTopLevelProvider( provider->
id() ) )
278 std::unique_ptr< QgsProcessingToolboxModelProviderNode > node = qgis::make_unique< QgsProcessingToolboxModelProviderNode >( provider );
279 parentNode = node.get();
280 mRootNode->addChildNode( node.release() );
284 parentNode = mRootNode.get();
287 const QList< const QgsProcessingAlgorithm * > algorithms = provider->
algorithms();
290 std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = qgis::make_unique< QgsProcessingToolboxModelAlgorithmNode >(
algorithm );
293 if ( !groupId.isEmpty() )
295 QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
299 parentNode->addChildNode( groupNode );
301 groupNode->addChildNode( algorithmNode.release() );
306 parentNode->addChildNode( algorithmNode.release() );
311 bool QgsProcessingToolboxModel::isTopLevelProvider(
const QString &providerId )
313 return providerId == QLatin1String(
"qgis" ) ||
314 providerId == QLatin1String(
"native" ) ||
315 providerId == QLatin1String(
"3d" );
320 return QStringLiteral(
"<p><b>%1</b></p>%2<p>%3</p>%4" ).arg(
323 QObject::tr(
"Algorithm ID: ‘%1’" ).arg( QStringLiteral(
"<i>%1</i>" ).arg(
algorithm->
id() ) ),
330 if ( !
index.isValid() )
331 return Qt::ItemFlags();
333 return QAbstractItemModel::flags(
index );
338 if ( !
index.isValid() )
344 return node->nodeType();
349 bool isRecentNode =
false;
351 isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeRecent;
354 QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >(
index2node(
index ) );
359 case Qt::DisplayRole:
361 switch (
index.column() )
365 return provider->
name();
368 else if ( groupNode )
369 return groupNode->name();
370 else if ( isRecentNode )
371 return tr(
"Recently used" );
381 case Qt::ToolTipRole:
387 else if ( groupNode )
388 return groupNode->name();
393 case Qt::ForegroundRole:
396 return QBrush( QColor( Qt::red ) );
401 case Qt::DecorationRole:
403 switch (
index.column() )
408 return provider->
icon();
415 else if ( isRecentNode )
417 else if ( !
index.parent().isValid() )
431 switch (
index.column() )
447 switch (
index.column() )
452 return static_cast< int >( provider->
flags() );
467 switch (
index.column() )
483 switch (
index.column() )
499 switch (
index.column() )
515 switch (
index.column() )
533 #ifndef _MSC_VER // avoid warning
544 return n->children().count();
554 if ( !hasIndex( row, column,
parent ) )
555 return QModelIndex();
559 return QModelIndex();
561 return createIndex( row, column,
static_cast<QObject *
>( n->children().at( row ) ) );
566 if ( !child.isValid() )
567 return QModelIndex();
569 if ( QgsProcessingToolboxModelNode *n =
index2node( child ) )
576 return QModelIndex();
582 if ( !indexes.isEmpty() &&
isAlgorithm( indexes.at( 0 ) ) )
584 QByteArray encodedData;
585 QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
587 std::unique_ptr< QMimeData >
mimeData = qgis::make_unique< QMimeData >();
593 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
602 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
605 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->provider();
611 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
614 return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->providerId();
620 if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeAlgorithm )
623 return qobject_cast< QgsProcessingToolboxModelAlgorithmNode * >( n )->algorithm();
629 return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeAlgorithm );
634 std::function< QModelIndex(
const QModelIndex &
parent,
const QString &providerId ) > findIndex = [&](
const QModelIndex &
parent,
const QString & providerId )->QModelIndex
640 if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
643 QModelIndex checkChildren = findIndex( current, providerId );
644 if ( checkChildren.isValid() )
645 return checkChildren;
647 return QModelIndex();
650 return findIndex( QModelIndex(), providerId );
655 Q_ASSERT( parentNode );
657 QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
658 if ( !grandParentNode )
659 return QModelIndex();
661 int row = grandParentNode->children().indexOf( parentNode );
662 Q_ASSERT( row >= 0 );
664 return createIndex( row, 0,
static_cast<QObject *
>( parentNode ) );
672 QgsProcessingRecentAlgorithmLog *recentLog )
673 : QSortFilterProxyModel( parent )
676 setSourceModel( mModel );
677 setDynamicSortFilter(
true );
678 setSortLocaleAware(
true );
679 setFilterCaseSensitivity( Qt::CaseInsensitive );
703 mInPlaceLayer = layer;
710 mFilterString = filter;
716 QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
723 if ( !mFilterString.trimmed().isEmpty() )
730 QStringList parentText;
731 QModelIndex parent = sourceIndex.parent();
732 while ( parent.isValid() )
734 const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split(
' ' );
735 if ( !parentParts.empty() )
736 parentText.append( parentParts );
737 parent = parent.parent();
740 const QStringList partsToMatch = mFilterString.trimmed().split(
' ' );
742 QStringList partsToSearch = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString().split(
' ' );
743 partsToSearch << algId << algName;
744 partsToSearch.append( algTags );
745 if ( !shortDesc.isEmpty() )
746 partsToSearch.append( shortDesc.split(
' ' ) );
747 partsToSearch.append( parentText );
749 for (
const QString &part : partsToMatch )
752 for (
const QString &partToSearch : qgis::as_const( partsToSearch ) )
754 if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
768 if ( !supportsInPlace )
780 return !isHiddenFromModeler;
785 return !isHiddenFromToolbox;
790 bool hasChildren =
false;
792 int count = sourceModel()->rowCount( sourceIndex );
793 for (
int i = 0; i < count; ++i )
810 if ( leftType == QgsProcessingToolboxModelNode::NodeRecent )
812 else if ( rightType == QgsProcessingToolboxModelNode::NodeRecent )
814 else if ( leftType != rightType )
816 if ( leftType == QgsProcessingToolboxModelNode::NodeProvider )
818 else if ( rightType == QgsProcessingToolboxModelNode::NodeProvider )
820 else if ( leftType == QgsProcessingToolboxModelNode::NodeGroup )
827 bool isRecentNode =
false;
828 QModelIndex parent = left.parent();
829 while ( parent.isValid() )
836 parent = parent.parent();
840 return left.row() < right.row();
845 QString leftStr = sourceModel()->data( left ).toString();
846 QString rightStr = sourceModel()->data( right ).toString();
847 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
852 if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
854 QModelIndex sourceIndex = mapToSource( index );
858 QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
859 QColor fadedTextColor = brush.color();
860 fadedTextColor.setAlpha( 100 );
861 brush.setColor( fadedTextColor );
865 return QSortFilterProxyModel::data( index, role );