QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsprocessingtoolboxmodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprocessingtoolboxmodel.cpp
3  -------------------------------
4  begin : May 2018
5  copyright : (C) 2018 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 #include "qgsapplication.h"
18 #include "qgsvectorlayer.h"
19 #include "qgsprocessingregistry.h"
21 #include <functional>
22 #include <QPalette>
23 
24 #ifdef ENABLE_MODELTEST
25 #include "modeltest.h"
26 #endif
27 
29 
30 //
31 // QgsProcessingToolboxModelNode
32 //
33 
34 QgsProcessingToolboxModelNode::~QgsProcessingToolboxModelNode()
35 {
36  deleteChildren();
37 }
38 
39 QgsProcessingToolboxModelNode *QgsProcessingToolboxModelNode::takeChild( QgsProcessingToolboxModelNode *node )
40 {
41  return mChildren.takeAt( mChildren.indexOf( node ) );
42 }
43 
44 QgsProcessingToolboxModelGroupNode *QgsProcessingToolboxModelNode::getChildGroupNode( const QString &groupId )
45 {
46  for ( QgsProcessingToolboxModelNode *node : qgis::as_const( mChildren ) )
47  {
48  if ( node->nodeType() == NodeGroup )
49  {
50  QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >( node );
51  if ( groupNode && groupNode->id() == groupId )
52  return groupNode;
53  }
54  }
55  return nullptr;
56 }
57 
58 void QgsProcessingToolboxModelNode::addChildNode( QgsProcessingToolboxModelNode *node )
59 {
60  if ( !node )
61  return;
62 
63  Q_ASSERT( !node->mParent );
64  node->mParent = this;
65 
66  mChildren.append( node );
67 }
68 
69 void QgsProcessingToolboxModelNode::deleteChildren()
70 {
71  qDeleteAll( mChildren );
72  mChildren.clear();
73 }
74 
75 //
76 // QgsProcessingToolboxModelProviderNode
77 //
78 
79 QgsProcessingToolboxModelProviderNode::QgsProcessingToolboxModelProviderNode( QgsProcessingProvider *provider )
80  : mProviderId( provider->id() )
81  , mProvider( provider )
82 {}
83 
84 QgsProcessingProvider *QgsProcessingToolboxModelProviderNode::provider()
85 {
86  return mProvider;
87 }
88 
89 //
90 // QgsProcessingToolboxModelGroupNode
91 //
92 
93 QgsProcessingToolboxModelGroupNode::QgsProcessingToolboxModelGroupNode( const QString &id, const QString &name )
94  : mId( id )
95  , mName( name )
96 {}
97 
98 //
99 // QgsProcessingToolboxModelAlgorithmNode
100 //
101 
102 QgsProcessingToolboxModelAlgorithmNode::QgsProcessingToolboxModelAlgorithmNode( const QgsProcessingAlgorithm *algorithm )
103  : mAlgorithm( algorithm )
104 {}
105 
107 {
108  return mAlgorithm;
109 }
110 
112 
113 //
114 // QgsProcessingToolboxModel
115 //
116 
117 QgsProcessingToolboxModel::QgsProcessingToolboxModel( QObject *parent, QgsProcessingRegistry *registry, QgsProcessingRecentAlgorithmLog *recentLog )
118  : QAbstractItemModel( parent )
119  , mRegistry( registry ? registry : QgsApplication::processingRegistry() )
120  , mRecentLog( recentLog )
121  , mRootNode( qgis::make_unique< QgsProcessingToolboxModelGroupNode >( QString(), QString() ) )
122 {
123  rebuild();
124 
125  if ( mRecentLog )
126  connect( mRecentLog, &QgsProcessingRecentAlgorithmLog::changed, this, [ = ] { repopulateRecentAlgorithms(); } );
127 
128  connect( mRegistry, &QgsProcessingRegistry::providerAdded, this, &QgsProcessingToolboxModel::rebuild );
129  connect( mRegistry, &QgsProcessingRegistry::providerRemoved, this, &QgsProcessingToolboxModel::providerRemoved );
130 }
131 
132 void QgsProcessingToolboxModel::rebuild()
133 {
134  beginResetModel();
135 
136  mRootNode->deleteChildren();
137  mRecentNode = nullptr;
138 
139  if ( mRecentLog )
140  {
141  std::unique_ptr< QgsProcessingToolboxModelRecentNode > recentNode = qgis::make_unique< QgsProcessingToolboxModelRecentNode >();
142  mRecentNode = recentNode.get();
143  mRootNode->addChildNode( recentNode.release() );
144  repopulateRecentAlgorithms( true );
145  }
146 
147  if ( mRegistry )
148  {
149  const QList< QgsProcessingProvider * > providers = mRegistry->providers();
150  for ( QgsProcessingProvider *provider : providers )
151  {
152  addProvider( provider );
153  }
154  }
155  endResetModel();
156 }
157 
158 void QgsProcessingToolboxModel::repopulateRecentAlgorithms( bool resetting )
159 {
160  if ( !mRecentNode || !mRecentLog )
161  return;
162 
163  QModelIndex recentIndex = index( 0, 0 );
164  const int prevCount = rowCount( recentIndex );
165  if ( !resetting && prevCount > 0 )
166  {
167  beginRemoveRows( recentIndex, 0, prevCount - 1 );
168  mRecentNode->deleteChildren();
169  endRemoveRows();
170  }
171 
172  if ( !mRegistry )
173  {
174  if ( !resetting )
175  emit recentAlgorithmAdded();
176  return;
177  }
178 
179  const QStringList recentAlgIds = mRecentLog->recentAlgorithmIds();
180  QList< const QgsProcessingAlgorithm * > recentAlgorithms;
181  recentAlgorithms.reserve( recentAlgIds.count() );
182  for ( const QString &id : recentAlgIds )
183  {
184  const QgsProcessingAlgorithm *algorithm = mRegistry->algorithmById( id );
185  if ( algorithm )
186  recentAlgorithms << algorithm;
187  }
188 
189  if ( recentAlgorithms.empty() )
190  {
191  if ( !resetting )
192  emit recentAlgorithmAdded();
193  return;
194  }
195 
196  if ( !resetting )
197  {
198  beginInsertRows( recentIndex, 0, recentAlgorithms.count() - 1 );
199  }
200 
201  for ( const QgsProcessingAlgorithm *algorithm : qgis::as_const( recentAlgorithms ) )
202  {
203  std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = qgis::make_unique< QgsProcessingToolboxModelAlgorithmNode >( algorithm );
204  mRecentNode->addChildNode( algorithmNode.release() );
205  }
206 
207  if ( !resetting )
208  {
209  endInsertRows();
210  emit recentAlgorithmAdded();
211  }
212 }
213 
214 void QgsProcessingToolboxModel::providerAdded( const QString &id )
215 {
216  if ( !mRegistry )
217  return;
218 
219  QgsProcessingProvider *provider = mRegistry->providerById( id );
220  if ( !provider )
221  return;
222 
223  if ( !isTopLevelProvider( id ) )
224  {
225  int previousRowCount = rowCount();
226  beginInsertRows( QModelIndex(), previousRowCount, previousRowCount );
227  addProvider( provider );
228  endInsertRows();
229  }
230  else
231  {
232  // native providers use top level groups - that's too hard for us to
233  // work out exactly what's going to change, so just reset the model
234  beginResetModel();
235  addProvider( provider );
236  endResetModel();
237  }
238 }
239 
240 void QgsProcessingToolboxModel::providerRemoved( const QString & )
241 {
242  // native providers use top level groups - so we can't
243  // work out what to remove. Just rebuild the whole model instead.
244  rebuild();
245 }
246 
247 QgsProcessingToolboxModelNode *QgsProcessingToolboxModel::index2node( const QModelIndex &index ) const
248 {
249  if ( !index.isValid() )
250  return mRootNode.get();
251 
252  QObject *obj = reinterpret_cast<QObject *>( index.internalPointer() );
253  return qobject_cast<QgsProcessingToolboxModelNode *>( obj );
254 }
255 
256 QModelIndex QgsProcessingToolboxModel::node2index( QgsProcessingToolboxModelNode *node ) const
257 {
258  if ( !node || !node->parent() )
259  return QModelIndex(); // this is the only root item -> invalid index
260 
261  QModelIndex parentIndex = node2index( node->parent() );
262 
263  int row = node->parent()->children().indexOf( node );
264  Q_ASSERT( row >= 0 );
265  return index( row, 0, parentIndex );
266 }
267 
268 void QgsProcessingToolboxModel::addProvider( QgsProcessingProvider *provider )
269 {
270  if ( !provider )
271  return;
272 
273  connect( provider, &QgsProcessingProvider::algorithmsLoaded, this, &QgsProcessingToolboxModel::rebuild, Qt::UniqueConnection );
274 
275  QgsProcessingToolboxModelNode *parentNode = nullptr;
276  if ( !isTopLevelProvider( provider->id() ) )
277  {
278  std::unique_ptr< QgsProcessingToolboxModelProviderNode > node = qgis::make_unique< QgsProcessingToolboxModelProviderNode >( provider );
279  parentNode = node.get();
280  mRootNode->addChildNode( node.release() );
281  }
282  else
283  {
284  parentNode = mRootNode.get();
285  }
286 
287  const QList< const QgsProcessingAlgorithm * > algorithms = provider->algorithms();
288  for ( const QgsProcessingAlgorithm *algorithm : algorithms )
289  {
290  std::unique_ptr< QgsProcessingToolboxModelAlgorithmNode > algorithmNode = qgis::make_unique< QgsProcessingToolboxModelAlgorithmNode >( algorithm );
291 
292  const QString groupId = algorithm->groupId();
293  if ( !groupId.isEmpty() )
294  {
295  QgsProcessingToolboxModelGroupNode *groupNode = parentNode->getChildGroupNode( groupId );
296  if ( !groupNode )
297  {
298  groupNode = new QgsProcessingToolboxModelGroupNode( algorithm->groupId(), algorithm->group() );
299  parentNode->addChildNode( groupNode );
300  }
301  groupNode->addChildNode( algorithmNode.release() );
302  }
303  else
304  {
305  // "top level" algorithm - no group
306  parentNode->addChildNode( algorithmNode.release() );
307  }
308  }
309 }
310 
311 bool QgsProcessingToolboxModel::isTopLevelProvider( const QString &providerId )
312 {
313  return providerId == QLatin1String( "qgis" ) ||
314  providerId == QLatin1String( "native" ) ||
315  providerId == QLatin1String( "3d" );
316 }
317 
318 QString QgsProcessingToolboxModel::toolTipForAlgorithm( const QgsProcessingAlgorithm *algorithm )
319 {
320  return QStringLiteral( "<p><b>%1</b></p>%2<p>%3</p>%4" ).arg(
322  !algorithm->shortDescription().isEmpty() ? QStringLiteral( "<p>%1</p>" ).arg( algorithm->shortDescription() ) : QString(),
323  QObject::tr( "Algorithm ID: ‘%1’" ).arg( QStringLiteral( "<i>%1</i>" ).arg( algorithm->id() ) ),
324  ( algorithm->flags() & QgsProcessingAlgorithm::FlagKnownIssues ) ? QStringLiteral( "<b style=\"color:red\">%1</b>" ).arg( QObject::tr( "Warning: Algorithm has known issues" ) ) : QString()
325  );
326 }
327 
328 Qt::ItemFlags QgsProcessingToolboxModel::flags( const QModelIndex &index ) const
329 {
330  if ( !index.isValid() )
331  return Qt::ItemFlags();
332 
333  return QAbstractItemModel::flags( index );
334 }
335 
336 QVariant QgsProcessingToolboxModel::data( const QModelIndex &index, int role ) const
337 {
338  if ( !index.isValid() )
339  return QVariant();
340 
341  if ( role == RoleNodeType )
342  {
343  if ( QgsProcessingToolboxModelNode *node = index2node( index ) )
344  return node->nodeType();
345  else
346  return QVariant();
347  }
348 
349  bool isRecentNode = false;
350  if ( QgsProcessingToolboxModelNode *node = index2node( index ) )
351  isRecentNode = node->nodeType() == QgsProcessingToolboxModelNode::NodeRecent;
352 
354  QgsProcessingToolboxModelGroupNode *groupNode = qobject_cast< QgsProcessingToolboxModelGroupNode * >( index2node( index ) );
356 
357  switch ( role )
358  {
359  case Qt::DisplayRole:
360  {
361  switch ( index.column() )
362  {
363  case 0:
364  if ( provider )
365  return provider->name();
366  else if ( algorithm )
367  return algorithm->displayName();
368  else if ( groupNode )
369  return groupNode->name();
370  else if ( isRecentNode )
371  return tr( "Recently used" );
372  else
373  return QVariant();
374 
375  default:
376  return QVariant();
377  }
378  break;
379  }
380 
381  case Qt::ToolTipRole:
382  {
383  if ( provider )
384  return provider->longName();
385  else if ( algorithm )
386  return toolTipForAlgorithm( algorithm );
387  else if ( groupNode )
388  return groupNode->name();
389  else
390  return QVariant();
391  }
392 
393  case Qt::ForegroundRole:
394  {
396  return QBrush( QColor( Qt::red ) );
397  else
398  return QVariant();
399  }
400 
401  case Qt::DecorationRole:
402  {
403  switch ( index.column() )
404  {
405  case 0:
406  {
407  if ( provider )
408  return provider->icon();
409  else if ( algorithm )
410  {
412  return QgsApplication::getThemeIcon( QStringLiteral( "mIconWarning.svg" ) );
413  return algorithm->icon();
414  }
415  else if ( isRecentNode )
416  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconHistory.svg" ) );
417  else if ( !index.parent().isValid() )
418  // top level groups get the QGIS icon
419  return QgsApplication::getThemeIcon( QStringLiteral( "/providerQgis.svg" ) );
420  else
421  return QVariant();
422  }
423 
424  default:
425  return QVariant();
426  }
427  break;
428  }
429 
430  case RoleAlgorithmFlags:
431  switch ( index.column() )
432  {
433  case 0:
434  {
435  if ( algorithm )
436  return static_cast< int >( algorithm->flags() );
437  else
438  return QVariant();
439  }
440 
441  default:
442  return QVariant();
443  }
444  break;
445 
446  case RoleProviderFlags:
447  switch ( index.column() )
448  {
449  case 0:
450  {
451  if ( provider )
452  return static_cast< int >( provider->flags() );
453  else if ( algorithm && algorithm->provider() )
454  return static_cast< int >( algorithm->provider()->flags() );
455  else if ( index.parent().data( RoleProviderFlags ).isValid() ) // group node
456  return static_cast< int >( index.parent().data( RoleProviderFlags ).toInt() );
457  else
458  return QVariant();
459  }
460 
461  default:
462  return QVariant();
463  }
464  break;
465 
466  case RoleAlgorithmId:
467  switch ( index.column() )
468  {
469  case 0:
470  {
471  if ( algorithm )
472  return algorithm->id();
473  else
474  return QVariant();
475  }
476 
477  default:
478  return QVariant();
479  }
480  break;
481 
482  case RoleAlgorithmName:
483  switch ( index.column() )
484  {
485  case 0:
486  {
487  if ( algorithm )
488  return algorithm->name();
489  else
490  return QVariant();
491  }
492 
493  default:
494  return QVariant();
495  }
496  break;
497 
498  case RoleAlgorithmTags:
499  switch ( index.column() )
500  {
501  case 0:
502  {
503  if ( algorithm )
504  return algorithm->tags();
505  else
506  return QVariant();
507  }
508 
509  default:
510  return QVariant();
511  }
512  break;
513 
515  switch ( index.column() )
516  {
517  case 0:
518  {
519  if ( algorithm )
520  return algorithm->shortDescription();
521  else
522  return QVariant();
523  }
524 
525  default:
526  return QVariant();
527  }
528  break;
529 
530  default:
531  return QVariant();
532  }
533 #ifndef _MSC_VER // avoid warning
534  return QVariant();
535 #endif
536 }
537 
538 int QgsProcessingToolboxModel::rowCount( const QModelIndex &parent ) const
539 {
540  QgsProcessingToolboxModelNode *n = index2node( parent );
541  if ( !n )
542  return 0;
543 
544  return n->children().count();
545 }
546 
547 int QgsProcessingToolboxModel::columnCount( const QModelIndex & ) const
548 {
549  return 1;
550 }
551 
552 QModelIndex QgsProcessingToolboxModel::index( int row, int column, const QModelIndex &parent ) const
553 {
554  if ( !hasIndex( row, column, parent ) )
555  return QModelIndex();
556 
557  QgsProcessingToolboxModelNode *n = index2node( parent );
558  if ( !n )
559  return QModelIndex(); // have no children
560 
561  return createIndex( row, column, static_cast<QObject *>( n->children().at( row ) ) );
562 }
563 
564 QModelIndex QgsProcessingToolboxModel::parent( const QModelIndex &child ) const
565 {
566  if ( !child.isValid() )
567  return QModelIndex();
568 
569  if ( QgsProcessingToolboxModelNode *n = index2node( child ) )
570  {
571  return indexOfParentTreeNode( n->parent() ); // must not be null
572  }
573  else
574  {
575  Q_ASSERT( false ); // no other node types!
576  return QModelIndex();
577  }
578 }
579 
580 QMimeData *QgsProcessingToolboxModel::mimeData( const QModelIndexList &indexes ) const
581 {
582  if ( !indexes.isEmpty() && isAlgorithm( indexes.at( 0 ) ) )
583  {
584  QByteArray encodedData;
585  QDataStream stream( &encodedData, QIODevice::WriteOnly | QIODevice::Truncate );
586 
587  std::unique_ptr< QMimeData > mimeData = qgis::make_unique< QMimeData >();
588  const QgsProcessingAlgorithm *algorithm = algorithmForIndex( indexes.at( 0 ) );
589  if ( algorithm )
590  {
591  stream << algorithm->id();
592  }
593  mimeData->setData( QStringLiteral( "application/x-vnd.qgis.qgis.algorithmid" ), encodedData );
594  return mimeData.release();
595  }
596  return nullptr;
597 }
598 
600 {
601  QgsProcessingToolboxModelNode *n = index2node( index );
602  if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
603  return nullptr;
604 
605  return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->provider();
606 }
607 
608 QString QgsProcessingToolboxModel::providerIdForIndex( const QModelIndex &index ) const
609 {
610  QgsProcessingToolboxModelNode *n = index2node( index );
611  if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeProvider )
612  return nullptr;
613 
614  return qobject_cast< QgsProcessingToolboxModelProviderNode * >( n )->providerId();
615 }
616 
618 {
619  QgsProcessingToolboxModelNode *n = index2node( index );
620  if ( !n || n->nodeType() != QgsProcessingToolboxModelNode::NodeAlgorithm )
621  return nullptr;
622 
623  return qobject_cast< QgsProcessingToolboxModelAlgorithmNode * >( n )->algorithm();
624 }
625 
626 bool QgsProcessingToolboxModel::isAlgorithm( const QModelIndex &index ) const
627 {
628  QgsProcessingToolboxModelNode *n = index2node( index );
629  return ( n && n->nodeType() == QgsProcessingToolboxModelNode::NodeAlgorithm );
630 }
631 
632 QModelIndex QgsProcessingToolboxModel::indexForProvider( const QString &providerId ) const
633 {
634  std::function< QModelIndex( const QModelIndex &parent, const QString &providerId ) > findIndex = [&]( const QModelIndex & parent, const QString & providerId )->QModelIndex
635  {
636  for ( int row = 0; row < rowCount( parent ); ++row )
637  {
638  QModelIndex current = index( row, 0, parent );
639  const QString currentProviderId = providerIdForIndex( current );
640  if ( !currentProviderId.isEmpty() && currentProviderId == providerId )
641  return current;
642 
643  QModelIndex checkChildren = findIndex( current, providerId );
644  if ( checkChildren.isValid() )
645  return checkChildren;
646  }
647  return QModelIndex();
648  };
649 
650  return findIndex( QModelIndex(), providerId );
651 }
652 
653 QModelIndex QgsProcessingToolboxModel::indexOfParentTreeNode( QgsProcessingToolboxModelNode *parentNode ) const
654 {
655  Q_ASSERT( parentNode );
656 
657  QgsProcessingToolboxModelNode *grandParentNode = parentNode->parent();
658  if ( !grandParentNode )
659  return QModelIndex(); // root node -> invalid index
660 
661  int row = grandParentNode->children().indexOf( parentNode );
662  Q_ASSERT( row >= 0 );
663 
664  return createIndex( row, 0, static_cast<QObject *>( parentNode ) );
665 }
666 
667 //
668 // QgsProcessingToolboxProxyModel
669 //
670 
672  QgsProcessingRecentAlgorithmLog *recentLog )
673  : QSortFilterProxyModel( parent )
674  , mModel( new QgsProcessingToolboxModel( this, registry, recentLog ) )
675 {
676  setSourceModel( mModel );
677  setDynamicSortFilter( true );
678  setSortLocaleAware( true );
679  setFilterCaseSensitivity( Qt::CaseInsensitive );
680  sort( 0 );
681 
682  connect( mModel, &QgsProcessingToolboxModel::recentAlgorithmAdded, this, [ = ] { invalidateFilter(); } );
683 }
684 
686 {
687  return mModel;
688 }
689 
691 {
692  return mModel;
693 }
694 
695 void QgsProcessingToolboxProxyModel::setFilters( QgsProcessingToolboxProxyModel::Filters filters )
696 {
697  mFilters = filters;
698  invalidateFilter();
699 }
700 
702 {
703  mInPlaceLayer = layer;
704  invalidateFilter();
705 }
706 
707 
709 {
710  mFilterString = filter;
711  invalidateFilter();
712 }
713 
714 bool QgsProcessingToolboxProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
715 {
716  QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
717  if ( mModel->isAlgorithm( sourceIndex ) )
718  {
719  const bool hasKnownIssues = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmFlags ).toInt() & QgsProcessingAlgorithm::FlagKnownIssues;
720  if ( hasKnownIssues && !( mFilters & FilterShowKnownIssues ) )
721  return false;
722 
723  if ( !mFilterString.trimmed().isEmpty() )
724  {
725  const QString algId = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmId ).toString();
726  const QString algName = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmName ).toString();
727  const QStringList algTags = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmTags ).toStringList();
728  const QString shortDesc = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmShortDescription ).toString();
729 
730  QStringList parentText;
731  QModelIndex parent = sourceIndex.parent();
732  while ( parent.isValid() )
733  {
734  const QStringList parentParts = sourceModel()->data( parent, Qt::DisplayRole ).toString().split( ' ' );
735  if ( !parentParts.empty() )
736  parentText.append( parentParts );
737  parent = parent.parent();
738  }
739 
740  const QStringList partsToMatch = mFilterString.trimmed().split( ' ' );
741 
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 );
748 
749  for ( const QString &part : partsToMatch )
750  {
751  bool found = false;
752  for ( const QString &partToSearch : qgis::as_const( partsToSearch ) )
753  {
754  if ( partToSearch.contains( part, Qt::CaseInsensitive ) )
755  {
756  found = true;
757  break;
758  }
759  }
760  if ( !found )
761  return false; // couldn't find a match for this word, so hide algorithm
762  }
763  }
764 
765  if ( mFilters & FilterInPlace )
766  {
767  const bool supportsInPlace = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmFlags ).toInt() & QgsProcessingAlgorithm::FlagSupportsInPlaceEdits;
768  if ( !supportsInPlace )
769  return false;
770 
771  const QgsProcessingAlgorithm *alg = mModel->algorithmForIndex( sourceIndex );
772  if ( !( mInPlaceLayer && alg && alg->supportInPlaceEdit( mInPlaceLayer ) ) )
773  {
774  return false;
775  }
776  }
777  if ( mFilters & FilterModeler )
778  {
779  bool isHiddenFromModeler = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmFlags ).toInt() & QgsProcessingAlgorithm::FlagHideFromModeler;
780  return !isHiddenFromModeler;
781  }
782  if ( mFilters & FilterToolbox )
783  {
784  bool isHiddenFromToolbox = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmFlags ).toInt() & QgsProcessingAlgorithm::FlagHideFromToolbox;
785  return !isHiddenFromToolbox;
786  }
787  return true;
788  }
789 
790  bool hasChildren = false;
791  // groups/providers are shown only if they have visible children
792  int count = sourceModel()->rowCount( sourceIndex );
793  for ( int i = 0; i < count; ++i )
794  {
795  if ( filterAcceptsRow( i, sourceIndex ) )
796  {
797  hasChildren = true;
798  break;
799  }
800  }
801 
802  return hasChildren;
803 }
804 
805 bool QgsProcessingToolboxProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
806 {
807  QgsProcessingToolboxModelNode::NodeType leftType = static_cast< QgsProcessingToolboxModelNode::NodeType >( sourceModel()->data( left, QgsProcessingToolboxModel::RoleNodeType ).toInt() );
808  QgsProcessingToolboxModelNode::NodeType rightType = static_cast< QgsProcessingToolboxModelNode::NodeType >( sourceModel()->data( right, QgsProcessingToolboxModel::RoleNodeType ).toInt() );
809 
810  if ( leftType == QgsProcessingToolboxModelNode::NodeRecent )
811  return true;
812  else if ( rightType == QgsProcessingToolboxModelNode::NodeRecent )
813  return false;
814  else if ( leftType != rightType )
815  {
816  if ( leftType == QgsProcessingToolboxModelNode::NodeProvider )
817  return false;
818  else if ( rightType == QgsProcessingToolboxModelNode::NodeProvider )
819  return true;
820  else if ( leftType == QgsProcessingToolboxModelNode::NodeGroup )
821  return false;
822  else
823  return true;
824  }
825 
826  // if node represents a recent algorithm, it's not sorted at all
827  bool isRecentNode = false;
828  QModelIndex parent = left.parent();
829  while ( parent.isValid() )
830  {
831  if ( mModel->data( parent, QgsProcessingToolboxModel::RoleNodeType ).toInt() == QgsProcessingToolboxModelNode::NodeRecent )
832  {
833  isRecentNode = true;
834  break;
835  }
836  parent = parent.parent();
837  }
838  if ( isRecentNode )
839  {
840  return left.row() < right.row();
841  }
842 
843 
844  // default mode is alphabetical order
845  QString leftStr = sourceModel()->data( left ).toString();
846  QString rightStr = sourceModel()->data( right ).toString();
847  return QString::localeAwareCompare( leftStr, rightStr ) < 0;
848 }
849 
850 QVariant QgsProcessingToolboxProxyModel::data( const QModelIndex &index, int role ) const
851 {
852  if ( role == Qt::ForegroundRole && !mFilterString.isEmpty() )
853  {
854  QModelIndex sourceIndex = mapToSource( index );
855  const QVariant flags = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleProviderFlags );
856  if ( flags.isValid() && flags.toInt() & QgsProcessingProvider::FlagDeemphasiseSearchResults )
857  {
858  QBrush brush( qApp->palette().color( QPalette::Text ), Qt::SolidPattern );
859  QColor fadedTextColor = brush.color();
860  fadedTextColor.setAlpha( 100 );
861  brush.setColor( fadedTextColor );
862  return brush;
863  }
864  }
865  return QSortFilterProxyModel::data( index, role );
866 }
QgsProcessingAlgorithm::shortDescription
virtual QString shortDescription() const
Returns an optional translated short description of the algorithm.
Definition: qgsprocessingalgorithm.cpp:58
qgsprocessingtoolboxmodel.h
QgsProcessingProvider::FlagDeemphasiseSearchResults
@ FlagDeemphasiseSearchResults
Algorithms should be de-emphasised in the search results when searching for algorithms....
Definition: qgsprocessingprovider.h:46
QgsProcessingToolboxProxyModel::setFilterString
void setFilterString(const QString &filter)
Sets a filter string, such that only algorithms matching the specified string will be shown.
Definition: qgsprocessingtoolboxmodel.cpp:708
QgsProcessingToolboxModel::RoleAlgorithmName
@ RoleAlgorithmName
Untranslated algorithm name, for algorithm nodes.
Definition: qgsprocessingtoolboxmodel.h:286
QgsProcessingRegistry::providerRemoved
void providerRemoved(const QString &id)
Emitted when a provider is removed from the registry.
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
QgsProcessingToolboxModel::RoleProviderFlags
@ RoleProviderFlags
Returns the node's provider flags.
Definition: qgsprocessingtoolboxmodel.h:289
QgsProcessingAlgorithm::displayName
virtual QString displayName() const =0
Returns the translated algorithm name, which should be used for any user-visible display of the algor...
QgsProcessingProvider::id
virtual QString id() const =0
Returns the unique provider id, used for identifying the provider.
QgsProcessingToolboxModel::RoleAlgorithmFlags
@ RoleAlgorithmFlags
Returns the node's algorithm flags, for algorithm nodes.
Definition: qgsprocessingtoolboxmodel.h:284
QgsProcessingToolboxModel::index2node
QgsProcessingToolboxModelNode * index2node(const QModelIndex &index) const
Returns the model node corresponding to the given index.
Definition: qgsprocessingtoolboxmodel.cpp:247
QgsProcessingToolboxModel::indexOfParentTreeNode
QModelIndex indexOfParentTreeNode(QgsProcessingToolboxModelNode *parentNode) const
Returns the index corresponding to the parent of a given node.
Definition: qgsprocessingtoolboxmodel.cpp:653
algorithm
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
QgsProcessingToolboxProxyModel::toolboxModel
QgsProcessingToolboxModel * toolboxModel()
Returns the underlying source Processing toolbox model.
Definition: qgsprocessingtoolboxmodel.cpp:685
QgsProcessingProvider
Abstract base class for processing providers.
Definition: qgsprocessingprovider.h:35
QgsProcessingToolboxModel::flags
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: qgsprocessingtoolboxmodel.cpp:328
QgsProcessingToolboxProxyModel::FilterInPlace
@ FilterInPlace
Only show algorithms which support in-place edits.
Definition: qgsprocessingtoolboxmodel.h:428
QgsProcessingToolboxModel::index
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: qgsprocessingtoolboxmodel.cpp:552
QgsProcessingAlgorithm::groupId
virtual QString groupId() const
Returns the unique ID of the group this algorithm belongs to.
Definition: qgsprocessingalgorithm.h:233
QgsProcessingProvider::icon
virtual QIcon icon() const
Returns an icon for the provider.
Definition: qgsprocessingprovider.cpp:34
QgsProcessingToolboxModel::providerForIndex
QgsProcessingProvider * providerForIndex(const QModelIndex &index) const
Returns the provider which corresponds to a given index, or nullptr if the index does not represent a...
Definition: qgsprocessingtoolboxmodel.cpp:599
QgsProcessingProvider::flags
virtual Flags flags() const
Returns the flags indicating how and when the provider operates and should be exposed to users.
Definition: qgsprocessingprovider.cpp:44
QgsProcessingToolboxModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition: qgsprocessingtoolboxmodel.cpp:538
QgsProcessingToolboxModel::isAlgorithm
bool isAlgorithm(const QModelIndex &index) const
Returns true if index corresponds to an algorithm.
Definition: qgsprocessingtoolboxmodel.cpp:626
QgsProcessingToolboxModel::indexForProvider
QModelIndex indexForProvider(const QString &providerId) const
Returns the index corresponding to the specified providerId.
Definition: qgsprocessingtoolboxmodel.cpp:632
qgsapplication.h
QgsProcessingToolboxProxyModel::setInPlaceLayer
void setInPlaceLayer(QgsVectorLayer *layer)
Sets the vector layer for in-place algorithm filter.
Definition: qgsprocessingtoolboxmodel.cpp:701
QgsProcessingToolboxProxyModel::filterAcceptsRow
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
Definition: qgsprocessingtoolboxmodel.cpp:714
QgsProcessingProvider::longName
virtual QString longName() const
Returns the longer version of the provider name, which can include extra details such as version numb...
Definition: qgsprocessingprovider.cpp:54
QgsProcessingProvider::name
virtual QString name() const =0
Returns the provider name, which is used to describe the provider within the GUI.
QgsProcessingToolboxModel::providerIdForIndex
QString providerIdForIndex(const QModelIndex &index) const
Returns the provider ID which corresponds to a given index, or an empty string if the index does not ...
Definition: qgsprocessingtoolboxmodel.cpp:608
QgsProcessingAlgorithm::name
virtual QString name() const =0
Returns the algorithm name, used for identifying the algorithm.
QgsProcessingAlgorithm::id
QString id() const
Returns the unique ID for the algorithm, which is a combination of the algorithm provider's ID and th...
Definition: qgsprocessingalgorithm.cpp:50
QgsProcessingRegistry::providerAdded
void providerAdded(const QString &id)
Emitted when a provider has been added to the registry.
QgsProcessingToolboxProxyModel::FilterModeler
@ FilterModeler
Filters out any algorithms and content which should not be shown in the modeler.
Definition: qgsprocessingtoolboxmodel.h:427
QgsProcessingToolboxProxyModel::filters
Filters filters() const
Returns any filters that affect how toolbox content is filtered.
Definition: qgsprocessingtoolboxmodel.h:470
QgsProcessingFeatureBasedAlgorithm::flags
QgsProcessingAlgorithm::Flags flags() const override
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Definition: qgsprocessingalgorithm.cpp:903
QgsProcessingToolboxProxyModel::lessThan
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
Definition: qgsprocessingtoolboxmodel.cpp:805
QgsProcessingToolboxModel::mimeData
QMimeData * mimeData(const QModelIndexList &indexes) const override
Definition: qgsprocessingtoolboxmodel.cpp:580
QgsProcessingToolboxProxyModel::setFilters
void setFilters(QgsProcessingToolboxProxyModel::Filters filters)
Set filters that affect how toolbox content is filtered.
Definition: qgsprocessingtoolboxmodel.cpp:695
QgsProcessingAlgorithm::FlagHideFromToolbox
@ FlagHideFromToolbox
Algorithm should be hidden from the toolbox.
Definition: qgsprocessingalgorithm.h:70
QgsProcessingToolboxModel::RoleAlgorithmTags
@ RoleAlgorithmTags
List of algorithm tags, for algorithm nodes.
Definition: qgsprocessingtoolboxmodel.h:288
QgsProcessingToolboxProxyModel::FilterShowKnownIssues
@ FilterShowKnownIssues
Show algorithms with known issues (hidden by default)
Definition: qgsprocessingtoolboxmodel.h:429
QgsProcessingAlgorithm::FlagHideFromModeler
@ FlagHideFromModeler
Algorithm should be hidden from the modeler.
Definition: qgsprocessingalgorithm.h:71
QgsProcessingAlgorithm::supportInPlaceEdit
virtual bool supportInPlaceEdit(const QgsMapLayer *layer) const
Checks whether this algorithm supports in-place editing on the given layer Default implementation ret...
Definition: qgsprocessingalgorithm.cpp:869
QgsApplication
Extends QApplication to provide access to QGIS specific resources such as theme paths,...
Definition: qgsapplication.h:83
QgsProcessingToolboxModel::recentAlgorithmAdded
void recentAlgorithmAdded()
Emitted whenever recent algorithms are added to the model.
QgsProcessingToolboxModel
A model for providers and algorithms shown within the Processing toolbox.
Definition: qgsprocessingtoolboxmodel.h:275
qgsvectorlayer.h
QgsProcessingToolboxProxyModel::QgsProcessingToolboxProxyModel
QgsProcessingToolboxProxyModel(QObject *parent=nullptr, QgsProcessingRegistry *registry=nullptr, QgsProcessingRecentAlgorithmLog *recentLog=nullptr)
Constructor for QgsProcessingToolboxProxyModel, with the given parent object.
Definition: qgsprocessingtoolboxmodel.cpp:671
QgsProcessingToolboxModel::algorithmForIndex
const QgsProcessingAlgorithm * algorithmForIndex(const QModelIndex &index) const
Returns the algorithm which corresponds to a given index, or nullptr if the index does not represent ...
Definition: qgsprocessingtoolboxmodel.cpp:617
QgsProcessingToolboxModel::columnCount
int columnCount(const QModelIndex &=QModelIndex()) const override
Definition: qgsprocessingtoolboxmodel.cpp:547
QgsProcessingToolboxProxyModel::data
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Definition: qgsprocessingtoolboxmodel.cpp:850
QgsProcessingAlgorithm
Abstract base class for processing algorithms.
Definition: qgsprocessingalgorithm.h:52
QgsProcessingAlgorithm::icon
virtual QIcon icon() const
Returns an icon for the algorithm.
Definition: qgsprocessingalgorithm.cpp:78
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsProcessingProvider::algorithms
QList< const QgsProcessingAlgorithm * > algorithms() const
Returns a list of algorithms supplied by this provider.
Definition: qgsprocessingprovider.cpp:80
QgsProcessingToolboxModel::RoleAlgorithmId
@ RoleAlgorithmId
Algorithm ID, for algorithm nodes.
Definition: qgsprocessingtoolboxmodel.h:285
QgsProcessingToolboxModel::RoleNodeType
@ RoleNodeType
Corresponds to the node's type.
Definition: qgsprocessingtoolboxmodel.h:283
qgsprocessingrecentalgorithmlog.h
QgsProcessingAlgorithm::group
virtual QString group() const
Returns the name of the group this algorithm belongs to.
Definition: qgsprocessingalgorithm.h:224
QgsProcessingRegistry
Registry for various processing components, including providers, algorithms and various parameters an...
Definition: qgsprocessingregistry.h:40
QgsProcessingToolboxModel::QgsProcessingToolboxModel
QgsProcessingToolboxModel(QObject *parent=nullptr, QgsProcessingRegistry *registry=nullptr, QgsProcessingRecentAlgorithmLog *recentLog=nullptr)
Constructor for QgsProcessingToolboxModel, with the given parent object.
Definition: qgsprocessingtoolboxmodel.cpp:117
QgsProcessingProvider::algorithmsLoaded
void algorithmsLoaded()
Emitted when the provider has loaded (or refreshed) its list of available algorithms.
QgsProcessingAlgorithm::FlagKnownIssues
@ FlagKnownIssues
Algorithm has known issues.
Definition: qgsprocessingalgorithm.h:78
QgsProcessingAlgorithm::provider
QgsProcessingProvider * provider() const
Returns the provider to which this algorithm belongs.
Definition: qgsprocessingalgorithm.cpp:128
QgsProcessingToolboxModel::data
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Definition: qgsprocessingtoolboxmodel.cpp:336
QgsProcessingToolboxProxyModel::FilterToolbox
@ FilterToolbox
Filters out any algorithms and content which should not be shown in the toolbox.
Definition: qgsprocessingtoolboxmodel.h:426
qgsprocessingregistry.h
QgsProcessingToolboxModel::RoleAlgorithmShortDescription
@ RoleAlgorithmShortDescription
Short algorithm description, for algorithm nodes.
Definition: qgsprocessingtoolboxmodel.h:287
QgsProcessingAlgorithm::tags
virtual QStringList tags() const
Returns a list of tags which relate to the algorithm, and are used to assist users in searching for s...
Definition: qgsprocessingalgorithm.h:180
QgsProcessingAlgorithm::FlagSupportsInPlaceEdits
@ FlagSupportsInPlaceEdits
Algorithm supports in-place editing.
Definition: qgsprocessingalgorithm.h:77
QgsProcessingToolboxModel::node2index
QModelIndex node2index(QgsProcessingToolboxModelNode *node) const
Returns the model index corresponding to the given node.
Definition: qgsprocessingtoolboxmodel.cpp:256
QgsProcessingToolboxModel::parent
QModelIndex parent(const QModelIndex &index) const override
Definition: qgsprocessingtoolboxmodel.cpp:564