Skip to content

Commit 237c745

Browse files
committedMar 7, 2019
[processing][needs-docs] By default, hide algorithms with known issues from toolbox
And add a Processing setting to allow these to be shown. When shown, they are highlighted in red with a tooltip explaining that the algorithm has known issues (cherry picked from commit 63d6487) (cherry picked from commit 0b41216)
1 parent 3f71df6 commit 237c745

11 files changed

+120
-7
lines changed
 

‎python/gui/auto_generated/processing/qgsprocessingtoolboxmodel.sip.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ the results.
380380
FilterToolbox,
381381
FilterModeler,
382382
FilterInPlace,
383+
FilterShowKnownIssues,
383384
};
384385
typedef QFlags<QgsProcessingToolboxProxyModel::Filter> Filters;
385386

‎python/gui/auto_generated/processing/qgsprocessingtoolboxtreeview.sip.in

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,18 @@ if no algorithm is currently selected.
7171
void setFilters( QgsProcessingToolboxProxyModel::Filters filters );
7272
%Docstring
7373
Sets ``filters`` controlling the view's contents.
74+
75+
.. seealso:: :py:func:`filters`
7476
%End
7577

78+
QgsProcessingToolboxProxyModel::Filters filters() const;
79+
%Docstring
80+
Returns the current filters controlling the view's contents.
81+
82+
.. seealso:: :py:func:`setFilters`
83+
84+
.. versionadded:: 3.8
85+
%End
7686

7787
void setInPlaceLayer( QgsVectorLayer *layer );
7888
%Docstring

‎python/plugins/processing/core/ProcessingConfig.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class ProcessingConfig:
5959
SHOW_CRS_DEF = 'SHOW_CRS_DEF'
6060
WARN_UNMATCHING_CRS = 'WARN_UNMATCHING_CRS'
6161
SHOW_PROVIDERS_TOOLTIP = 'SHOW_PROVIDERS_TOOLTIP'
62+
SHOW_ALGORITHMS_KNOWN_ISSUES = 'SHOW_ALGORITHMS_KNOWN_ISSUES'
6263

6364
settings = {}
6465
settingIcons = {}
@@ -92,6 +93,10 @@ def initialize():
9293
ProcessingConfig.tr('General'),
9394
ProcessingConfig.WARN_UNMATCHING_CRS,
9495
ProcessingConfig.tr("Warn before executing if parameter CRS's do not match"), True))
96+
ProcessingConfig.addSetting(Setting(
97+
ProcessingConfig.tr('General'),
98+
ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES,
99+
ProcessingConfig.tr("Show algorithms with known issues"), False))
95100
ProcessingConfig.addSetting(Setting(
96101
ProcessingConfig.tr('General'),
97102
ProcessingConfig.RASTER_STYLE,

‎python/plugins/processing/gui/AlgorithmLocatorFilter.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
from processing.gui.AlgorithmDialog import AlgorithmDialog
4141
from processing.gui.AlgorithmExecutor import execute_in_place
4242
from qgis.utils import iface
43+
from processing.core.ProcessingConfig import ProcessingConfig
4344

4445

4546
class AlgorithmLocatorFilter(QgsLocatorFilter):
@@ -71,6 +72,9 @@ def fetchResults(self, string, context, feedback):
7172
for a in QgsApplication.processingRegistry().algorithms():
7273
if a.flags() & QgsProcessingAlgorithm.FlagHideFromToolbox:
7374
continue
75+
if not ProcessingConfig.getSetting(ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES) and \
76+
a.flags() & QgsProcessingAlgorithm.FlagKnownIssues:
77+
continue
7478

7579
if QgsLocatorFilter.stringMatches(a.displayName(), string) or [t for t in a.tags() if QgsLocatorFilter.stringMatches(t, string)] or \
7680
(context.usingPrefix and not string):

‎python/plugins/processing/gui/ProcessingToolbox.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,14 @@ def __init__(self):
8181

8282
self.algorithmTree.setRegistry(QgsApplication.processingRegistry(),
8383
QgsGui.instance().processingRecentAlgorithmLog())
84-
self.algorithmTree.setFilters(QgsProcessingToolboxProxyModel.FilterToolbox)
84+
filters = QgsProcessingToolboxProxyModel.Filters(QgsProcessingToolboxProxyModel.FilterToolbox)
85+
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES):
86+
filters |= QgsProcessingToolboxProxyModel.FilterShowKnownIssues
87+
self.algorithmTree.setFilters(filters)
8588

8689
self.searchBox.setShowSearchIcon(True)
8790

88-
self.searchBox.textChanged.connect(self.algorithmTree.setFilterString)
91+
self.searchBox.textChanged.connect(self.set_filter_string)
8992
self.searchBox.returnPressed.connect(self.activateCurrent)
9093
self.algorithmTree.customContextMenuRequested.connect(
9194
self.showPopupMenu)
@@ -114,11 +117,24 @@ def openSettings(url):
114117

115118
iface.currentLayerChanged.connect(self.layer_changed)
116119

120+
def set_filter_string(self, string):
121+
filters = self.algorithmTree.filters()
122+
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES):
123+
filters |= QgsProcessingToolboxProxyModel.FilterShowKnownIssues
124+
else:
125+
filters &= ~QgsProcessingToolboxProxyModel.FilterShowKnownIssues
126+
self.algorithmTree.setFilters(filters)
127+
self.algorithmTree.setFilterString(string)
128+
117129
def set_in_place_edit_mode(self, enabled):
130+
filters = QgsProcessingToolboxProxyModel.Filters(QgsProcessingToolboxProxyModel.FilterToolbox)
131+
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES):
132+
filters |= QgsProcessingToolboxProxyModel.FilterShowKnownIssues
133+
118134
if enabled:
119-
self.algorithmTree.setFilters(QgsProcessingToolboxProxyModel.Filters(QgsProcessingToolboxProxyModel.FilterToolbox | QgsProcessingToolboxProxyModel.FilterInPlace))
135+
self.algorithmTree.setFilters(filters | QgsProcessingToolboxProxyModel.FilterInPlace)
120136
else:
121-
self.algorithmTree.setFilters(QgsProcessingToolboxProxyModel.FilterToolbox)
137+
self.algorithmTree.setFilters(filters)
122138
self.in_place_mode = enabled
123139

124140
def layer_changed(self, layer):

‎python/plugins/processing/modeler/ModelerDialog.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
from processing.modeler.ModelerUtils import ModelerUtils
9494
from processing.modeler.ModelerScene import ModelerScene
9595
from processing.modeler.ProjectProvider import PROJECT_PROVIDER_ID
96+
from processing.core.ProcessingConfig import ProcessingConfig
9697
from qgis.utils import iface
9798

9899

@@ -409,7 +410,10 @@ def _mimeDataInput(items):
409410
self.algorithmTree.setDragDropMode(QTreeWidget.DragOnly)
410411
self.algorithmTree.setDropIndicatorShown(True)
411412

412-
self.algorithmTree.setFilters(QgsProcessingToolboxProxyModel.FilterModeler)
413+
filters = QgsProcessingToolboxProxyModel.Filters(QgsProcessingToolboxProxyModel.FilterModeler)
414+
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES):
415+
filters |= QgsProcessingToolboxProxyModel.FilterShowKnownIssues
416+
self.algorithmTree.setFilters(filters)
413417

414418
if hasattr(self.searchBox, 'setPlaceholderText'):
415419
self.searchBox.setPlaceholderText(QCoreApplication.translate('ModelerDialog', 'Search…'))

‎src/gui/processing/qgsprocessingtoolboxmodel.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,11 @@ bool QgsProcessingToolboxModel::isTopLevelProvider( const QString &providerId )
316316

317317
QString QgsProcessingToolboxModel::toolTipForAlgorithm( const QgsProcessingAlgorithm *algorithm )
318318
{
319-
return QStringLiteral( "<p><b>%1</b></p>%2<p>%3</p>" ).arg(
319+
return QStringLiteral( "<p><b>%1</b></p>%2<p>%3</p>%4" ).arg(
320320
algorithm->displayName(),
321321
!algorithm->shortDescription().isEmpty() ? QStringLiteral( "<p>%1</p>" ).arg( algorithm->shortDescription() ) : QString(),
322-
QObject::tr( "Algorithm ID: ‘%1’" ).arg( QStringLiteral( "<i>%1</i>" ).arg( algorithm->id() ) )
322+
QObject::tr( "Algorithm ID: ‘%1’" ).arg( QStringLiteral( "<i>%1</i>" ).arg( algorithm->id() ) ),
323+
algorithm->flags() & QgsProcessingAlgorithm::FlagKnownIssues ? QStringLiteral( "<b style=\"color:red\">%1</b>" ).arg( QObject::tr( "Warning: Algorithm has known issues" ) ) : QString()
323324
);
324325
}
325326

@@ -388,15 +389,28 @@ QVariant QgsProcessingToolboxModel::data( const QModelIndex &index, int role ) c
388389
return QVariant();
389390
}
390391

392+
case Qt::ForegroundRole:
393+
{
394+
if ( algorithm && algorithm->flags() & QgsProcessingAlgorithm::FlagKnownIssues )
395+
return QBrush( QColor( Qt::red ) );
396+
else
397+
return QVariant();
398+
}
399+
391400
case Qt::DecorationRole:
401+
{
392402
switch ( index.column() )
393403
{
394404
case 0:
395405
{
396406
if ( provider )
397407
return provider->icon();
398408
else if ( algorithm )
409+
{
410+
if ( algorithm->flags() & QgsProcessingAlgorithm::FlagKnownIssues )
411+
return QgsApplication::getThemeIcon( QStringLiteral( "mIconWarning.svg" ) );
399412
return algorithm->icon();
413+
}
400414
else if ( isRecentNode )
401415
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconHistory.svg" ) );
402416
else if ( !index.parent().isValid() )
@@ -410,6 +424,7 @@ QVariant QgsProcessingToolboxModel::data( const QModelIndex &index, int role ) c
410424
return QVariant();
411425
}
412426
break;
427+
}
413428

414429
case RoleAlgorithmFlags:
415430
switch ( index.column() )
@@ -674,6 +689,10 @@ bool QgsProcessingToolboxProxyModel::filterAcceptsRow( int sourceRow, const QMod
674689
QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
675690
if ( mModel->isAlgorithm( sourceIndex ) )
676691
{
692+
const bool hasKnownIssues = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmFlags ).toInt() & QgsProcessingAlgorithm::FlagKnownIssues;
693+
if ( hasKnownIssues && !( mFilters & FilterShowKnownIssues ) )
694+
return false;
695+
677696
if ( !mFilterString.trimmed().isEmpty() )
678697
{
679698
const QString algId = sourceModel()->data( sourceIndex, QgsProcessingToolboxModel::RoleAlgorithmId ).toString();

‎src/gui/processing/qgsprocessingtoolboxmodel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ class GUI_EXPORT QgsProcessingToolboxProxyModel: public QSortFilterProxyModel
425425
FilterToolbox = 1 << 1, //!< Filters out any algorithms and content which should not be shown in the toolbox
426426
FilterModeler = 1 << 2, //!< Filters out any algorithms and content which should not be shown in the modeler
427427
FilterInPlace = 1 << 3, //!< Only show algorithms which support in-place edits
428+
FilterShowKnownIssues = 1 << 4, //!< Show algorithms with known issues (hidden by default)
428429
};
429430
Q_DECLARE_FLAGS( Filters, Filter )
430431
Q_FLAG( Filters )

‎src/gui/processing/qgsprocessingtoolboxtreeview.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ void QgsProcessingToolboxTreeView::setFilters( QgsProcessingToolboxProxyModel::F
9393
mModel->setFilters( filters );
9494
}
9595

96+
QgsProcessingToolboxProxyModel::Filters QgsProcessingToolboxTreeView::filters() const
97+
{
98+
return mModel->filters();
99+
}
100+
96101
void QgsProcessingToolboxTreeView::setInPlaceLayer( QgsVectorLayer *layer )
97102
{
98103
mModel->setInPlaceLayer( layer );

‎src/gui/processing/qgsprocessingtoolboxtreeview.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,16 @@ class GUI_EXPORT QgsProcessingToolboxTreeView : public QTreeView
8282

8383
/**
8484
* Sets \a filters controlling the view's contents.
85+
* \see filters()
8586
*/
8687
void setFilters( QgsProcessingToolboxProxyModel::Filters filters );
8788

89+
/**
90+
* Returns the current filters controlling the view's contents.
91+
* \see setFilters()
92+
* \since QGIS 3.8
93+
*/
94+
QgsProcessingToolboxProxyModel::Filters filters() const;
8895

8996
/**
9097
* Sets the vector \a layer for the in-place algorithms

‎tests/src/gui/testqgsprocessingmodel.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class TestQgsProcessingModel: public QObject
113113
void init() {} // will be called before each testfunction is executed.
114114
void cleanup() {} // will be called after every testfunction.
115115
void testModel();
116+
void testKnownIssues();
116117
void testProxyModel();
117118
void testView();
118119
};
@@ -597,6 +598,7 @@ void TestQgsProcessingModel::testView()
597598

598599
// empty providers/groups should not be shown
599600
view.setFilters( QgsProcessingToolboxProxyModel::FilterModeler );
601+
QCOMPARE( view.filters(), QgsProcessingToolboxProxyModel::FilterModeler );
600602
QCOMPARE( view.model()->rowCount(), 1 );
601603
provider2Index = view.model()->index( 0, 0, QModelIndex() );
602604
QCOMPARE( view.model()->data( provider2Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
@@ -614,6 +616,7 @@ void TestQgsProcessingModel::testView()
614616
QCOMPARE( view.algorithmForIndex( view.model()->index( 0, 0, group2Index ) )->id(), QStringLiteral( "p1:a2" ) );
615617

616618
view.setFilters( nullptr );
619+
QCOMPARE( view.filters(), QgsProcessingToolboxProxyModel::Filters() );
617620
// test filter strings
618621
view.setFilterString( "a1" );
619622
provider2Index = view.model()->index( 0, 0, QModelIndex() );
@@ -651,6 +654,44 @@ void TestQgsProcessingModel::testView()
651654
QVERIFY( view.mModel );
652655
QVERIFY( view.mToolboxModel );
653656
QCOMPARE( view.mModel->toolboxModel(), view.mToolboxModel );
657+
}
658+
659+
void TestQgsProcessingModel::testKnownIssues()
660+
{
661+
QgsProcessingRegistry registry;
662+
QgsProcessingRecentAlgorithmLog recentLog;
663+
QgsProcessingToolboxModel model( nullptr, &registry, &recentLog );
664+
DummyAlgorithm *a1 = new DummyAlgorithm( "a1", "group1", QgsProcessingAlgorithm::FlagKnownIssues, QStringLiteral( "tag1,tag2" ), QStringLiteral( "short desc a" ) );
665+
DummyAlgorithm *a2 = new DummyAlgorithm( "b1", "group1", nullptr, QStringLiteral( "tag1,tag2" ), QStringLiteral( "short desc b" ) );
666+
DummyProvider *p = new DummyProvider( "p3", "provider3", QList< QgsProcessingAlgorithm * >() << a1 << a2 );
667+
registry.addProvider( p );
668+
669+
QModelIndex providerIndex = model.index( 1, 0, QModelIndex() );
670+
QModelIndex group1Index = model.index( 0, 0, providerIndex );
671+
QCOMPARE( model.data( model.index( 0, 0, group1Index ), Qt::DisplayRole ).toString(), QStringLiteral( "a1" ) );
672+
QVERIFY( model.data( model.index( 0, 0, group1Index ), Qt::ToolTipRole ).toString().contains( QStringLiteral( "known issues" ) ) );
673+
QCOMPARE( model.data( model.index( 0, 0, group1Index ), Qt::ForegroundRole ).value< QBrush >().color().name(), QStringLiteral( "#ff0000" ) );
674+
QCOMPARE( model.data( model.index( 1, 0, group1Index ), Qt::DisplayRole ).toString(), QStringLiteral( "b1" ) );
675+
QVERIFY( !model.data( model.index( 1, 0, group1Index ), Qt::ToolTipRole ).toString().contains( QStringLiteral( "known issues" ) ) );
676+
QCOMPARE( model.data( model.index( 1, 0, group1Index ), Qt::ForegroundRole ).value< QBrush >().color().name(), QStringLiteral( "#000000" ) );
677+
678+
QgsProcessingToolboxProxyModel proxyModel( nullptr, &registry, &recentLog );
679+
providerIndex = proxyModel.index( 0, 0, QModelIndex() );
680+
group1Index = proxyModel.index( 0, 0, providerIndex );
681+
// by default known issues are filtered out
682+
QCOMPARE( proxyModel.rowCount( group1Index ), 1 );
683+
QCOMPARE( proxyModel.data( proxyModel.index( 0, 0, group1Index ), Qt::DisplayRole ).toString(), QStringLiteral( "b1" ) );
684+
QVERIFY( !proxyModel.data( proxyModel.index( 0, 0, group1Index ), Qt::ToolTipRole ).toString().contains( QStringLiteral( "known issues" ) ) );
685+
QCOMPARE( proxyModel.data( proxyModel.index( 0, 0, group1Index ), Qt::ForegroundRole ).value< QBrush >().color().name(), QStringLiteral( "#000000" ) );
686+
proxyModel.setFilters( QgsProcessingToolboxProxyModel::Filters( QgsProcessingToolboxProxyModel::FilterToolbox | QgsProcessingToolboxProxyModel::FilterShowKnownIssues ) );
687+
QCOMPARE( proxyModel.rowCount( group1Index ), 2 );
688+
QCOMPARE( proxyModel.data( proxyModel.index( 0, 0, group1Index ), Qt::DisplayRole ).toString(), QStringLiteral( "a1" ) );
689+
QVERIFY( proxyModel.data( proxyModel.index( 0, 0, group1Index ), Qt::ToolTipRole ).toString().contains( QStringLiteral( "known issues" ) ) );
690+
QCOMPARE( proxyModel.data( proxyModel.index( 0, 0, group1Index ), Qt::ForegroundRole ).value< QBrush >().color().name(), QStringLiteral( "#ff0000" ) );
691+
QCOMPARE( proxyModel.data( proxyModel.index( 1, 0, group1Index ), Qt::DisplayRole ).toString(), QStringLiteral( "b1" ) );
692+
QVERIFY( !proxyModel.data( proxyModel.index( 1, 0, group1Index ), Qt::ToolTipRole ).toString().contains( QStringLiteral( "known issues" ) ) );
693+
QCOMPARE( proxyModel.data( proxyModel.index( 1, 0, group1Index ), Qt::ForegroundRole ).value< QBrush >().color().name(), QStringLiteral( "#000000" ) );
694+
654695

655696
}
656697

0 commit comments

Comments
 (0)
Please sign in to comment.