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 );