1 /***************************************************************************
2 testqgsprocessingmodel.cpp
3 --------------------------
4 begin : July 2018
5 copyright : (C) 2018 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "qgsprocessingregistry.h"
19 #include "qgsprocessingtoolboxmodel.h"
20 #include "qgsprocessingrecentalgorithmlog.h"
21 #include "qgsprocessingtoolboxtreeview.h"
22 #include "qgssettings.h"
23
24 #include <QtTest/QSignalSpy>
25 #include "qgstest.h"
26
27 #ifdef ENABLE_MODELTEST
28 #include "modeltest.h"
29 #endif
30
31
32 class DummyAlgorithm : public QgsProcessingAlgorithm
33 {
34 public:
35
DummyAlgorithm(const QString & name,const QString & group,QgsProcessingAlgorithm::Flags flags=QgsProcessingAlgorithm::Flags (),const QString & tags=QString (),const QString & shortDescription=QString (),const QString & displayName=QString ())36 DummyAlgorithm( const QString &name, const QString &group,
37 QgsProcessingAlgorithm::Flags flags = QgsProcessingAlgorithm::Flags(),
38 const QString &tags = QString(),
39 const QString &shortDescription = QString(),
40 const QString &displayName = QString() )
41 : mName( name )
42 , mDisplayName( displayName )
43 , mGroup( group )
44 , mFlags( flags )
45 , mTags( tags.split( ',' ) )
46 , mShortDescription( shortDescription )
47 {}
48
initAlgorithm(const QVariantMap &=QVariantMap ())49 void initAlgorithm( const QVariantMap & = QVariantMap() ) override {}
flags() const50 QgsProcessingAlgorithm::Flags flags() const override { return mFlags; }
name() const51 QString name() const override { return mName; }
displayName() const52 QString displayName() const override { return mDisplayName.isEmpty() ? mName : mDisplayName; }
group() const53 QString group() const override { return mGroup; }
groupId() const54 QString groupId() const override { return mGroup; }
shortDescription() const55 QString shortDescription() const override { return mShortDescription; }
tags() const56 QStringList tags() const override { return mTags; }
processAlgorithm(const QVariantMap &,QgsProcessingContext &,QgsProcessingFeedback *)57 QVariantMap processAlgorithm( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * ) override { return QVariantMap(); }
58
createInstance() const59 DummyAlgorithm *createInstance() const override { return new DummyAlgorithm( mName, mGroup, mFlags, mTags.join( ',' ), mShortDescription, mDisplayName ); }
60
61 QString mName;
62 QString mDisplayName;
63 QString mGroup;
64 QgsProcessingAlgorithm::Flags mFlags = QgsProcessingAlgorithm::Flags();
65 QStringList mTags;
66 QString mShortDescription;
67
68 };
69 //dummy provider for testing
70 class DummyProvider : public QgsProcessingProvider // clazy:exclude=missing-qobject-macro
71 {
72 public:
73
DummyProvider(const QString & id,const QString & name,const QList<QgsProcessingAlgorithm * > algs=QList<QgsProcessingAlgorithm * > ())74 DummyProvider( const QString &id, const QString &name, const QList< QgsProcessingAlgorithm *> algs = QList< QgsProcessingAlgorithm *>() )
75 : mId( id )
76 , mName( name )
77 , mAlgs( algs )
78 {
79
80 }
~DummyProvider()81 ~DummyProvider() override
82 {
83 qDeleteAll( mAlgs );
84 }
85
id() const86 QString id() const override { return mId; }
isActive() const87 bool isActive() const override { return mActive; }
88
name() const89 QString name() const override { return mName; }
longName() const90 QString longName() const override { return QStringLiteral( "long name %1" ).arg( mName );}
91 bool mActive = true;
92 protected:
loadAlgorithms()93 void loadAlgorithms() override
94 {
95 for ( QgsProcessingAlgorithm *alg : mAlgs )
96 addAlgorithm( alg->create() );
97 }
98 QString mId;
99 QString mName;
100
101 QList< QgsProcessingAlgorithm *> mAlgs;
102
103 };
104
105
106 class TestQgsProcessingModel: public QObject
107 {
108 Q_OBJECT
109
110 private slots:
111 void initTestCase();// will be called before the first testfunction is executed.
112 void cleanupTestCase(); // will be called after the last testfunction was executed.
init()113 void init() {} // will be called before each testfunction is executed.
cleanup()114 void cleanup() {} // will be called after every testfunction.
115 void testModel();
116 void testKnownIssues();
117 void testProxyModel();
118 void testView();
119 };
120
121
initTestCase()122 void TestQgsProcessingModel::initTestCase()
123 {
124 QgsApplication::init();
125 QgsApplication::initQgis();
126
127 // Set up the QgsSettings environment
128 QCoreApplication::setOrganizationName( QStringLiteral( "QGIS" ) );
129 QCoreApplication::setOrganizationDomain( QStringLiteral( "qgis.org" ) );
130 QCoreApplication::setApplicationName( QStringLiteral( "QGIS-TEST" ) );
131
132 QgsSettings().clear();
133 }
134
cleanupTestCase()135 void TestQgsProcessingModel::cleanupTestCase()
136 {
137 QgsApplication::exitQgis();
138 }
139
testModel()140 void TestQgsProcessingModel::testModel()
141 {
142 QgsProcessingRegistry registry;
143 QgsProcessingRecentAlgorithmLog recentLog;
144 QgsProcessingToolboxModel model( nullptr, ®istry, &recentLog );
145
146 #ifdef ENABLE_MODELTEST
147 new ModelTest( &model, this ); // for model validity checking
148 #endif
149
150 QCOMPARE( model.columnCount(), 1 );
151 QCOMPARE( model.rowCount(), 1 );
152 QVERIFY( model.hasChildren() );
153 QCOMPARE( model.data( model.index( 0, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "Recently used" ) );
154 QCOMPARE( model.rowCount( model.index( 0, 0, QModelIndex() ) ), 0 );
155 QVERIFY( !model.providerForIndex( model.index( 0, 0, QModelIndex() ) ) );
156 QVERIFY( !model.providerForIndex( model.index( 1, 0, QModelIndex() ) ) );
157 QVERIFY( !model.indexForProvider( nullptr ).isValid() );
158 QVERIFY( model.index2node( QModelIndex() ) ); // root node
159 QCOMPARE( model.index2node( QModelIndex() )->nodeType(), QgsProcessingToolboxModelNode::NodeGroup );
160 QVERIFY( model.index2node( model.index( -1, 0, QModelIndex() ) ) ); // root node
161 QCOMPARE( model.index2node( QModelIndex() ), model.index2node( model.index( -1, 0, QModelIndex() ) ) );
162
163 // add a provider
164 DummyProvider *p1 = new DummyProvider( "p1", "provider1" );
165 registry.addProvider( p1 );
166 QCOMPARE( model.rowCount(), 2 );
167 QVERIFY( model.hasChildren() );
168
169 QVERIFY( model.index( 0, 0, QModelIndex() ).isValid() );
170 QCOMPARE( model.data( model.index( 0, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "Recently used" ) );
171 QCOMPARE( model.providerForIndex( model.index( 1, 0, QModelIndex() ) ), p1 );
172 QVERIFY( !model.providerForIndex( model.index( 2, 0, QModelIndex() ) ) );
173 QCOMPARE( model.indexForProvider( p1->id() ), model.index( 1, 0, QModelIndex() ) );
174 QVERIFY( !model.indexForProvider( nullptr ).isValid() );
175 QCOMPARE( model.rowCount( model.index( 1, 0, QModelIndex() ) ), 0 );
176 QVERIFY( !model.hasChildren( model.index( 1, 0, QModelIndex() ) ) );
177 QCOMPARE( model.data( model.index( 1, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "provider1" ) );
178 QCOMPARE( model.data( model.index( 1, 0, QModelIndex() ), Qt::ToolTipRole ).toString(), QStringLiteral( "long name provider1" ) );
179 QVERIFY( !model.data( model.index( 2, 0, QModelIndex() ), Qt::DisplayRole ).isValid() );
180 QVERIFY( !model.data( model.index( 2, 0, QModelIndex() ), Qt::ToolTipRole ).isValid() );
181
182 // second provider
183 DummyProvider *p2 = new DummyProvider( "p2", "provider2" );
184 registry.addProvider( p2 );
185 QCOMPARE( model.rowCount(), 3 );
186 QVERIFY( model.hasChildren() );
187
188 QVERIFY( model.index( 2, 0, QModelIndex() ).isValid() );
189 QCOMPARE( model.providerForIndex( model.index( 1, 0, QModelIndex() ) ), p1 );
190 QCOMPARE( model.providerForIndex( model.index( 2, 0, QModelIndex() ) ), p2 );
191 QVERIFY( !model.providerForIndex( model.index( 3, 0, QModelIndex() ) ) );
192 QCOMPARE( model.indexForProvider( p1->id() ), model.index( 1, 0, QModelIndex() ) );
193 QCOMPARE( model.indexForProvider( p2->id() ), model.index( 2, 0, QModelIndex() ) );
194 QVERIFY( !model.indexForProvider( nullptr ).isValid() );
195 QVERIFY( !model.hasChildren( model.index( 2, 0, QModelIndex() ) ) );
196
197 QCOMPARE( model.data( model.index( 1, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "provider1" ) );
198 QCOMPARE( model.data( model.index( 1, 0, QModelIndex() ), Qt::ToolTipRole ).toString(), QStringLiteral( "long name provider1" ) );
199 QCOMPARE( model.data( model.index( 2, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
200 QCOMPARE( model.data( model.index( 2, 0, QModelIndex() ), Qt::ToolTipRole ).toString(), QStringLiteral( "long name provider2" ) );
201 QVERIFY( !model.data( model.index( 3, 0, QModelIndex() ), Qt::DisplayRole ).isValid() );
202 QVERIFY( !model.data( model.index( 3, 0, QModelIndex() ), Qt::ToolTipRole ).isValid() );
203
204 // provider with algs and groups
205 DummyAlgorithm *a1 = new DummyAlgorithm( "a1", "group1", QgsProcessingAlgorithm::FlagHideFromModeler, QStringLiteral( "tag1,tag2" ), QStringLiteral( "short desc a" ) );
206 DummyAlgorithm *a2 = new DummyAlgorithm( "a2", "group2", QgsProcessingAlgorithm::FlagHideFromToolbox );
207 DummyProvider *p3 = new DummyProvider( "p3", "provider3", QList< QgsProcessingAlgorithm * >() << a1 << a2 );
208 registry.addProvider( p3 );
209
210 QCOMPARE( model.rowCount(), 4 );
211 QVERIFY( model.hasChildren() );
212 QVERIFY( model.index( 3, 0, QModelIndex() ).isValid() );
213 QCOMPARE( model.providerForIndex( model.index( 3, 0, QModelIndex() ) ), p3 );
214 QCOMPARE( model.indexForProvider( p1->id() ), model.index( 1, 0, QModelIndex() ) );
215 QCOMPARE( model.indexForProvider( p2->id() ), model.index( 2, 0, QModelIndex() ) );
216 QCOMPARE( model.indexForProvider( p3->id() ), model.index( 3, 0, QModelIndex() ) );
217 QCOMPARE( model.rowCount( model.index( 2, 0, QModelIndex() ) ), 0 );
218 QCOMPARE( model.rowCount( model.index( 3, 0, QModelIndex() ) ), 2 );
219 QVERIFY( !model.hasChildren( model.index( 2, 0, QModelIndex() ) ) );
220 QVERIFY( model.hasChildren( model.index( 3, 0, QModelIndex() ) ) );
221 QModelIndex providerIndex = model.index( 3, 0, QModelIndex() );
222 QVERIFY( !model.providerForIndex( model.index( 1, 0, providerIndex ) ) );
223 QVERIFY( !model.providerForIndex( model.index( 2, 0, providerIndex ) ) );
224
225 QCOMPARE( model.data( model.index( 0, 0, providerIndex ), Qt::DisplayRole ).toString(), QStringLiteral( "group1" ) );
226 QCOMPARE( model.data( model.index( 0, 0, providerIndex ), Qt::ToolTipRole ).toString(), QStringLiteral( "group1" ) );
227 QCOMPARE( model.data( model.index( 1, 0, providerIndex ), Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
228 QCOMPARE( model.data( model.index( 1, 0, providerIndex ), Qt::ToolTipRole ).toString(), QStringLiteral( "group2" ) );
229
230 QModelIndex group1Index = model.index( 0, 0, providerIndex );
231 QVERIFY( !model.providerForIndex( group1Index ) );
232 QVERIFY( !model.algorithmForIndex( group1Index ) );
233 QCOMPARE( model.rowCount( group1Index ), 1 );
234 QVERIFY( model.hasChildren( group1Index ) );
235 QModelIndex alg1Index = model.index( 0, 0, group1Index );
236 QVERIFY( !model.providerForIndex( alg1Index ) );
237 QCOMPARE( model.data( alg1Index, Qt::DisplayRole ).toString(), QStringLiteral( "a1" ) );
238 QCOMPARE( model.data( alg1Index, Qt::ToolTipRole ).toString(), QStringLiteral( u"<p><b>a1</b></p><p>short desc a</p><p>Algorithm ID: \u2018<i>p3:a1</i>\u2019</p>" ) );
239 QCOMPARE( model.data( alg1Index, QgsProcessingToolboxModel::RoleAlgorithmFlags ).toInt(), static_cast< int >( QgsProcessingAlgorithm::FlagHideFromModeler ) );
240 QCOMPARE( model.data( alg1Index, QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p3:a1" ) );
241 QCOMPARE( model.data( alg1Index, QgsProcessingToolboxModel::RoleAlgorithmName ).toString(), QStringLiteral( "a1" ) );
242 QCOMPARE( model.data( alg1Index, QgsProcessingToolboxModel::RoleAlgorithmTags ).toStringList().join( ',' ), QStringLiteral( "tag1,tag2" ) );
243 QCOMPARE( model.data( alg1Index, QgsProcessingToolboxModel::RoleAlgorithmShortDescription ).toString(), QStringLiteral( "short desc a" ) );
244
245 QCOMPARE( model.algorithmForIndex( alg1Index )->id(), QStringLiteral( "p3:a1" ) );
246
247 QModelIndex group2Index = model.index( 1, 0, providerIndex );
248 QCOMPARE( model.rowCount( group2Index ), 1 );
249 QVERIFY( model.hasChildren( group2Index ) );
250 QModelIndex alg2Index = model.index( 0, 0, group2Index );
251 QCOMPARE( model.data( alg2Index, Qt::DisplayRole ).toString(), QStringLiteral( "a2" ) );
252 QCOMPARE( model.data( alg2Index, Qt::ToolTipRole ).toString(), QStringLiteral( u"<p><b>a2</b></p><p>Algorithm ID: \u2018<i>p3:a2</i>\u2019</p>" ) );
253 QCOMPARE( model.data( alg2Index, QgsProcessingToolboxModel::RoleAlgorithmFlags ).toInt(), static_cast< int >( QgsProcessingAlgorithm::FlagHideFromToolbox ) );
254 QCOMPARE( model.data( alg2Index, QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p3:a2" ) );
255 QCOMPARE( model.data( alg2Index, QgsProcessingToolboxModel::RoleAlgorithmName ).toString(), QStringLiteral( "a2" ) );
256 QCOMPARE( model.data( alg2Index, QgsProcessingToolboxModel::RoleAlgorithmTags ).toStringList().join( ',' ), QString() );
257 QCOMPARE( model.data( alg2Index, QgsProcessingToolboxModel::RoleAlgorithmShortDescription ).toString(), QString() );
258 QCOMPARE( model.algorithmForIndex( alg2Index )->id(), QStringLiteral( "p3:a2" ) );
259
260 // combined groups
261 DummyAlgorithm *a3 = new DummyAlgorithm( "a3", "group1" );
262 DummyAlgorithm *a4 = new DummyAlgorithm( "a4", "group1" );
263 DummyProvider *p4 = new DummyProvider( "p4", "provider4", QList< QgsProcessingAlgorithm * >() << a3 << a4 );
264 registry.addProvider( p4 );
265 const QModelIndex p4ProviderIndex = model.indexForProvider( p4->id() );
266 QModelIndex groupIndex = model.index( 0, 0, p4ProviderIndex );
267 QCOMPARE( model.rowCount( groupIndex ), 2 );
268 QCOMPARE( model.algorithmForIndex( model.index( 0, 0, groupIndex ) )->id(), QStringLiteral( "p4:a3" ) );
269 QCOMPARE( model.algorithmForIndex( model.index( 1, 0, groupIndex ) )->id(), QStringLiteral( "p4:a4" ) );
270
271 // provider with algs with no groups
272 DummyAlgorithm *a5 = new DummyAlgorithm( "a5", "group1" );
273 DummyAlgorithm *a6 = new DummyAlgorithm( "a6", QString() );
274 DummyAlgorithm *a7 = new DummyAlgorithm( "a7", "group2" );
275 DummyProvider *p5 = new DummyProvider( "p5", "provider5", QList< QgsProcessingAlgorithm * >() << a5 << a6 << a7 );
276 registry.addProvider( p5 );
277 QCOMPARE( model.rowCount(), 6 );
278 QModelIndex p5ProviderIndex = model.indexForProvider( p5->id() );
279 QCOMPARE( model.rowCount( p5ProviderIndex ), 3 );
280
281 groupIndex = model.index( 0, 0, p5ProviderIndex );
282 QCOMPARE( model.data( groupIndex, Qt::DisplayRole ).toString(), QStringLiteral( "group1" ) );
283 QCOMPARE( model.rowCount( groupIndex ), 1 );
284 QCOMPARE( model.algorithmForIndex( model.index( 0, 0, groupIndex ) )->id(), QStringLiteral( "p5:a5" ) );
285
286 QCOMPARE( model.algorithmForIndex( model.index( 1, 0, p5ProviderIndex ) )->id(), QStringLiteral( "p5:a6" ) );
287
288 groupIndex = model.index( 2, 0, p5ProviderIndex );
289 QCOMPARE( model.data( groupIndex, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
290 QCOMPARE( model.rowCount( groupIndex ), 1 );
291 QCOMPARE( model.algorithmForIndex( model.index( 0, 0, groupIndex ) )->id(), QStringLiteral( "p5:a7" ) );
292
293 // reload provider
294 p5->refreshAlgorithms();
295 QCOMPARE( model.rowCount(), 6 );
296 p5ProviderIndex = model.indexForProvider( p5->id() );
297 QCOMPARE( model.rowCount( p5ProviderIndex ), 3 );
298
299 groupIndex = model.index( 0, 0, p5ProviderIndex );
300 QCOMPARE( model.data( groupIndex, Qt::DisplayRole ).toString(), QStringLiteral( "group1" ) );
301 QCOMPARE( model.rowCount( groupIndex ), 1 );
302 QCOMPARE( model.algorithmForIndex( model.index( 0, 0, groupIndex ) )->id(), QStringLiteral( "p5:a5" ) );
303 QCOMPARE( model.algorithmForIndex( model.index( 1, 0, p5ProviderIndex ) )->id(), QStringLiteral( "p5:a6" ) );
304 groupIndex = model.index( 2, 0, p5ProviderIndex );
305 QCOMPARE( model.data( groupIndex, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
306 QCOMPARE( model.rowCount( groupIndex ), 1 );
307 QCOMPARE( model.algorithmForIndex( model.index( 0, 0, groupIndex ) )->id(), QStringLiteral( "p5:a7" ) );
308
309 p3->refreshAlgorithms();
310 providerIndex = model.indexForProvider( p3->id() );
311 group1Index = model.index( 0, 0, providerIndex );
312 QCOMPARE( model.rowCount( group1Index ), 1 );
313 alg1Index = model.index( 0, 0, group1Index );
314 QCOMPARE( model.algorithmForIndex( alg1Index )->id(), QStringLiteral( "p3:a1" ) );
315 group2Index = model.index( 1, 0, providerIndex );
316 QCOMPARE( model.rowCount( group2Index ), 1 );
317 alg2Index = model.index( 0, 0, group2Index );
318 QCOMPARE( model.algorithmForIndex( alg2Index )->id(), QStringLiteral( "p3:a2" ) );
319
320 // recent algorithms
321 QModelIndex recentIndex = model.index( 0, 0, QModelIndex() );
322 QCOMPARE( model.data( recentIndex, Qt::DisplayRole ).toString(), QStringLiteral( "Recently used" ) );
323 QCOMPARE( model.rowCount( recentIndex ), 0 );
324 recentLog.push( QStringLiteral( "p5:a5" ) );
325 QCOMPARE( model.rowCount( recentIndex ), 1 );
326 QCOMPARE( model.data( model.index( 0, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p5:a5" ) );
327 recentLog.push( QStringLiteral( "not valid" ) );
328 QCOMPARE( model.rowCount( recentIndex ), 1 );
329 QCOMPARE( model.data( model.index( 0, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p5:a5" ) );
330 recentLog.push( QStringLiteral( "p4:a3" ) );
331 QCOMPARE( model.rowCount( recentIndex ), 2 );
332 QCOMPARE( model.data( model.index( 0, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p4:a3" ) );
333 QCOMPARE( model.data( model.index( 1, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p5:a5" ) );
334
335 // remove a provider
336 registry.removeProvider( p1 );
337 QCOMPARE( model.rowCount(), 5 );
338 QVERIFY( model.index( 0, 0, QModelIndex() ).isValid() );
339 QCOMPARE( model.providerForIndex( model.index( 1, 0, QModelIndex() ) ), p2 );
340 QCOMPARE( model.data( model.index( 1, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
341 registry.removeProvider( p5 );
342 QCOMPARE( model.rowCount(), 4 );
343 recentIndex = model.index( 0, 0, QModelIndex() );
344 QCOMPARE( model.rowCount( recentIndex ), 1 );
345 QCOMPARE( model.data( model.index( 0, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p4:a3" ) );
346 registry.removeProvider( p2 );
347 QCOMPARE( model.rowCount(), 3 );
348 registry.removeProvider( p3 );
349 QCOMPARE( model.rowCount(), 2 );
350 recentIndex = model.index( 0, 0, QModelIndex() );
351 QCOMPARE( model.rowCount( recentIndex ), 1 );
352 registry.removeProvider( p4 );
353 recentIndex = model.index( 0, 0, QModelIndex() );
354 QCOMPARE( model.rowCount( recentIndex ), 0 );
355 QCOMPARE( model.rowCount(), 1 );
356 QCOMPARE( model.columnCount(), 1 );
357 QVERIFY( model.hasChildren() );
358 QCOMPARE( model.data( model.index( 0, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "Recently used" ) );
359 QVERIFY( !model.providerForIndex( model.index( 0, 0, QModelIndex() ) ) );
360 QVERIFY( !model.providerForIndex( model.index( 1, 0, QModelIndex() ) ) );
361 QVERIFY( !model.indexForProvider( nullptr ).isValid() );
362
363 // qgis native algorithms put groups at top level
364 QgsProcessingRegistry registry2;
365 const QgsProcessingToolboxModel model2( nullptr, ®istry2 );
366 DummyAlgorithm *qgisA1 = new DummyAlgorithm( "a1", "group1" );
367 DummyAlgorithm *qgisA2 = new DummyAlgorithm( "a2", "group2" );
368 DummyAlgorithm *qgisA3 = new DummyAlgorithm( "a3", "group1" );
369 DummyAlgorithm *qgisA4 = new DummyAlgorithm( "a4", "group3" );
370 DummyProvider *qgisP = new DummyProvider( "qgis", "qgis_provider", QList< QgsProcessingAlgorithm * >() << qgisA1 << qgisA2 << qgisA3 << qgisA4 );
371 registry2.addProvider( qgisP );
372
373 QCOMPARE( model2.rowCount(), 3 );
374 group1Index = model2.index( 0, 0 );
375 group2Index = model2.index( 1, 0 );
376 const QModelIndex group3Index = model2.index( 2, 0 );
377 QCOMPARE( model2.data( group1Index, Qt::DisplayRole ).toString(), QStringLiteral( "group1" ) );
378 QCOMPARE( model2.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
379 QCOMPARE( model2.data( group3Index, Qt::DisplayRole ).toString(), QStringLiteral( "group3" ) );
380
381 QCOMPARE( model2.rowCount( group1Index ), 2 );
382 QCOMPARE( model2.algorithmForIndex( model2.index( 0, 0, group1Index ) )->id(), QStringLiteral( "qgis:a1" ) );
383 QCOMPARE( model2.algorithmForIndex( model2.index( 1, 0, group1Index ) )->id(), QStringLiteral( "qgis:a3" ) );
384 QCOMPARE( model2.rowCount( group2Index ), 1 );
385 QCOMPARE( model2.algorithmForIndex( model2.index( 0, 0, group2Index ) )->id(), QStringLiteral( "qgis:a2" ) );
386 QCOMPARE( model2.rowCount( group3Index ), 1 );
387 QCOMPARE( model2.algorithmForIndex( model2.index( 0, 0, group3Index ) )->id(), QStringLiteral( "qgis:a4" ) );
388 }
389
testProxyModel()390 void TestQgsProcessingModel::testProxyModel()
391 {
392 QgsSettings().clear();
393 QgsProcessingRegistry registry;
394 QgsProcessingRecentAlgorithmLog recentLog;
395 QgsProcessingToolboxProxyModel model( nullptr, ®istry, &recentLog );
396
397 #ifdef ENABLE_MODELTEST
398 new ModelTest( &model, this ); // for model validity checking
399 #endif
400
401 // add a provider
402 DummyAlgorithm *a1 = new DummyAlgorithm( "a1", "group2", QgsProcessingAlgorithm::FlagHideFromModeler );
403 DummyProvider *p1 = new DummyProvider( "p2", "provider2", QList< QgsProcessingAlgorithm * >() << a1 );
404 registry.addProvider( p1 );
405 // second provider
406 DummyAlgorithm *a2 = new DummyAlgorithm( "a2", "group2", QgsProcessingAlgorithm::FlagHideFromModeler,
407 QStringLiteral( "buffer,vector" ), QStringLiteral( "short desc" ), QStringLiteral( "algorithm2" ) );
408 DummyProvider *p2 = new DummyProvider( "p1", "provider1", QList< QgsProcessingAlgorithm * >() << a2 );
409 registry.addProvider( p2 );
410
411 QCOMPARE( model.data( model.index( 0, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "provider1" ) );
412 QCOMPARE( model.data( model.index( 1, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
413
414 // top level groups come first
415 DummyAlgorithm *qgisA1 = new DummyAlgorithm( "a1", "group2", QgsProcessingAlgorithm::FlagHideFromModeler );
416 DummyAlgorithm *qgisA2 = new DummyAlgorithm( "a2", "group1", QgsProcessingAlgorithm::FlagHideFromToolbox );
417 DummyProvider *qgisP = new DummyProvider( "qgis", "qgis_provider", QList< QgsProcessingAlgorithm * >() << qgisA1 << qgisA2 );
418 registry.addProvider( qgisP );
419
420 QModelIndex group1Index = model.index( 0, 0, QModelIndex() );
421 QModelIndex group2Index = model.index( 1, 0, QModelIndex() );
422 QCOMPARE( model.data( group1Index, Qt::DisplayRole ).toString(), QStringLiteral( "group1" ) );
423 QCOMPARE( model.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
424 QCOMPARE( model.data( model.index( 2, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "provider1" ) );
425 QCOMPARE( model.data( model.index( 3, 0, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
426 QCOMPARE( model.rowCount(), 4 );
427
428 QModelIndex alg1Index = model.index( 0, 0, group2Index );
429 QCOMPARE( model.data( alg1Index, Qt::DisplayRole ).toString(), QStringLiteral( "a1" ) );
430 const QModelIndex alg2Index = model.index( 0, 0, group1Index );
431 QCOMPARE( model.data( alg2Index, Qt::DisplayRole ).toString(), QStringLiteral( "a2" ) );
432
433 // empty providers/groups should not be shown
434 model.setFilters( QgsProcessingToolboxProxyModel::FilterModeler );
435 group1Index = model.index( 0, 0, QModelIndex() );
436 QCOMPARE( model.rowCount(), 1 );
437 QCOMPARE( model.rowCount( group1Index ), 1 );
438 QCOMPARE( model.data( group1Index, Qt::DisplayRole ).toString(), QStringLiteral( "group1" ) );
439 QCOMPARE( model.data( model.index( 0, 0, group1Index ), Qt::DisplayRole ).toString(), QStringLiteral( "a2" ) );
440 model.setFilters( QgsProcessingToolboxProxyModel::FilterToolbox );
441 group2Index = model.index( 0, 0, QModelIndex() );
442 QCOMPARE( model.rowCount(), 3 );
443 QCOMPARE( model.rowCount( group2Index ), 1 );
444 QCOMPARE( model.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
445 QCOMPARE( model.rowCount( group2Index ), 1 );
446 QCOMPARE( model.data( model.index( 0, 0, group1Index ), Qt::DisplayRole ).toString(), QStringLiteral( "a1" ) );
447
448 // test filter strings
449 model.setFilters( QgsProcessingToolboxProxyModel::Filters() );
450 // filter by algorithm id
451 model.setFilterString( "a1" );
452 QCOMPARE( model.rowCount(), 2 );
453 group1Index = model.index( 0, 0, QModelIndex() );
454 QModelIndex provider2Index = model.index( 1, 0, QModelIndex() );
455 QCOMPARE( model.rowCount( group1Index ), 1 );
456 QCOMPARE( model.data( group1Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
457 QCOMPARE( model.data( model.index( 0, 0, group1Index ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "qgis:a1" ) );
458 QCOMPARE( model.rowCount( group2Index ), 1 );
459 QCOMPARE( model.data( provider2Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
460 QCOMPARE( model.rowCount( provider2Index ), 1 );
461 group2Index = model.index( 0, 0, provider2Index );
462 QCOMPARE( model.rowCount( group2Index ), 1 );
463 QCOMPARE( model.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
464 QCOMPARE( model.data( model.index( 0, 0, group2Index ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p2:a1" ) );
465
466 // filter by algorithm display name
467 model.setFilterString( QStringLiteral( "ALGOR" ) );
468 QCOMPARE( model.rowCount(), 1 );
469 QModelIndex provider1Index = model.index( 0, 0, QModelIndex() );
470 QCOMPARE( model.rowCount( provider1Index ), 1 );
471 QCOMPARE( model.data( provider1Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider1" ) );
472 QCOMPARE( model.rowCount( provider1Index ), 1 );
473 group2Index = model.index( 0, 0, provider1Index );
474 QCOMPARE( model.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
475 QCOMPARE( model.rowCount( group2Index ), 1 );
476 QCOMPARE( model.data( model.index( 0, 0, group2Index ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p1:a2" ) );
477
478 // filter by algorithm tags
479 model.setFilterString( QStringLiteral( "buff CTOR" ) );
480 QCOMPARE( model.rowCount(), 1 );
481 provider1Index = model.index( 0, 0, QModelIndex() );
482 QCOMPARE( model.rowCount( provider1Index ), 1 );
483 QCOMPARE( model.data( provider1Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider1" ) );
484 QCOMPARE( model.rowCount( provider1Index ), 1 );
485 group2Index = model.index( 0, 0, provider1Index );
486 QCOMPARE( model.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
487 QCOMPARE( model.rowCount( group2Index ), 1 );
488 QCOMPARE( model.data( model.index( 0, 0, group2Index ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p1:a2" ) );
489
490 // filter by algorithm short desc
491 model.setFilterString( QStringLiteral( "buff CTOR desc" ) );
492 QCOMPARE( model.rowCount(), 1 );
493 provider1Index = model.index( 0, 0, QModelIndex() );
494 QCOMPARE( model.rowCount( provider1Index ), 1 );
495 QCOMPARE( model.data( provider1Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider1" ) );
496 QCOMPARE( model.rowCount( provider1Index ), 1 );
497 group2Index = model.index( 0, 0, provider1Index );
498 QCOMPARE( model.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
499 QCOMPARE( model.rowCount( group2Index ), 1 );
500 QCOMPARE( model.data( model.index( 0, 0, group2Index ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p1:a2" ) );
501
502 // filter by group
503 model.setFilterString( QStringLiteral( "group2" ) );
504 QCOMPARE( model.rowCount(), 3 );
505 group2Index = model.index( 0, 0, QModelIndex() );
506 QCOMPARE( model.rowCount( group2Index ), 1 );
507 QCOMPARE( model.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
508 alg1Index = model.index( 0, 0, group2Index );
509 QCOMPARE( model.data( alg1Index, QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "qgis:a1" ) );
510 provider1Index = model.index( 1, 0, QModelIndex() );
511 QCOMPARE( model.rowCount( provider1Index ), 1 );
512 QCOMPARE( model.data( provider1Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider1" ) );
513 QCOMPARE( model.rowCount( provider1Index ), 1 );
514 group2Index = model.index( 0, 0, provider1Index );
515 QCOMPARE( model.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
516 QCOMPARE( model.rowCount( group2Index ), 1 );
517 QCOMPARE( model.data( model.index( 0, 0, group2Index ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p1:a2" ) );
518 provider2Index = model.index( 2, 0, QModelIndex() );
519 QCOMPARE( model.rowCount( provider2Index ), 1 );
520 QCOMPARE( model.data( provider2Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
521 group2Index = model.index( 0, 0, provider2Index );
522 QCOMPARE( model.data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
523 QCOMPARE( model.rowCount( group2Index ), 1 );
524 QCOMPARE( model.data( model.index( 0, 0, group2Index ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p2:a1" ) );
525
526 model.setFilterString( QString() );
527 QCOMPARE( model.rowCount(), 4 );
528
529 // check sort order of recent algorithms
530 recentLog.push( QStringLiteral( "p2:a1" ) );
531 QCOMPARE( model.rowCount(), 5 );
532 const QModelIndex recentIndex = model.index( 0, 0, QModelIndex() );
533 QCOMPARE( model.data( recentIndex, Qt::DisplayRole ).toString(), QStringLiteral( "Recently used" ) );
534 QCOMPARE( model.rowCount( recentIndex ), 1 );
535 QCOMPARE( model.data( model.index( 0, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p2:a1" ) );
536 recentLog.push( QStringLiteral( "p1:a2" ) );
537 QCOMPARE( model.rowCount( recentIndex ), 2 );
538 QCOMPARE( model.data( model.index( 0, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p1:a2" ) );
539 QCOMPARE( model.data( model.index( 1, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p2:a1" ) );
540 recentLog.push( QStringLiteral( "qgis:a1" ) );
541 QCOMPARE( model.rowCount( recentIndex ), 3 );
542 QCOMPARE( model.data( model.index( 0, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "qgis:a1" ) );
543 QCOMPARE( model.data( model.index( 1, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p1:a2" ) );
544 QCOMPARE( model.data( model.index( 2, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p2:a1" ) );
545 recentLog.push( QStringLiteral( "p2:a1" ) );
546 QCOMPARE( model.rowCount( recentIndex ), 3 );
547 QCOMPARE( model.data( model.index( 0, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p2:a1" ) );
548 QCOMPARE( model.data( model.index( 1, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "qgis:a1" ) );
549 QCOMPARE( model.data( model.index( 2, 0, recentIndex ), QgsProcessingToolboxModel::RoleAlgorithmId ).toString(), QStringLiteral( "p1:a2" ) );
550
551 // inactive provider - should not be visible
552 QCOMPARE( model.rowCount(), 5 );
553 DummyAlgorithm *qgisA31 = new DummyAlgorithm( "a3", "group1" );
554 DummyProvider *p3 = new DummyProvider( "p3", "provider3", QList< QgsProcessingAlgorithm * >() << qgisA31 );
555 p3->mActive = false;
556 registry.addProvider( p3 );
557 QCOMPARE( model.rowCount(), 5 );
558 }
559
testView()560 void TestQgsProcessingModel::testView()
561 {
562 QgsSettings().clear();
563 QgsProcessingRegistry registry;
564 QgsProcessingRecentAlgorithmLog recentLog;
565 QgsProcessingToolboxTreeView view( nullptr, ®istry, &recentLog );
566
567 // Check view model consistency
568 QVERIFY( view.mModel );
569 QVERIFY( view.mToolboxModel );
570 QCOMPARE( view.mModel->toolboxModel(), view.mToolboxModel );
571
572 QVERIFY( !view.algorithmForIndex( QModelIndex() ) );
573
574 // add a provider
575 DummyAlgorithm *a1 = new DummyAlgorithm( "a1", "group2", QgsProcessingAlgorithm::FlagHideFromToolbox );
576 DummyProvider *p1 = new DummyProvider( "p2", "provider2", QList< QgsProcessingAlgorithm * >() << a1 );
577 registry.addProvider( p1 );
578 // second provider
579 DummyAlgorithm *a2 = new DummyAlgorithm( "a2", "group2", QgsProcessingAlgorithm::FlagHideFromModeler,
580 QStringLiteral( "buffer,vector" ), QStringLiteral( "short desc" ), QStringLiteral( "algorithm2" ) );
581 DummyProvider *p2 = new DummyProvider( "p1", "provider1", QList< QgsProcessingAlgorithm * >() << a2 );
582 registry.addProvider( p2 );
583
584 QModelIndex provider1Index = view.model()->index( 0, 0, QModelIndex() );
585 QVERIFY( !view.algorithmForIndex( provider1Index ) );
586 QModelIndex group2Index = view.model()->index( 0, 0, provider1Index );
587 QCOMPARE( view.model()->data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
588 QVERIFY( !view.algorithmForIndex( group2Index ) );
589 QModelIndex alg2Index = view.model()->index( 0, 0, group2Index );
590 QCOMPARE( view.algorithmForIndex( alg2Index )->id(), QStringLiteral( "p1:a2" ) );
591 QModelIndex provider2Index = view.model()->index( 1, 0, QModelIndex() );
592 QVERIFY( !view.algorithmForIndex( provider2Index ) );
593 QCOMPARE( view.model()->data( provider2Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
594 group2Index = view.model()->index( 0, 0, provider2Index );
595 QCOMPARE( view.model()->data( group2Index, Qt::DisplayRole ).toString(), QStringLiteral( "group2" ) );
596 const QModelIndex alg1Index = view.model()->index( 0, 0, group2Index );
597 QCOMPARE( view.algorithmForIndex( alg1Index )->id(), QStringLiteral( "p2:a1" ) );
598
599 // empty providers/groups should not be shown
600 view.setFilters( QgsProcessingToolboxProxyModel::FilterModeler );
601 QCOMPARE( view.filters(), QgsProcessingToolboxProxyModel::FilterModeler );
602 QCOMPARE( view.model()->rowCount(), 1 );
603 provider2Index = view.model()->index( 0, 0, QModelIndex() );
604 QCOMPARE( view.model()->data( provider2Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
605 QCOMPARE( view.model()->rowCount( provider2Index ), 1 );
606 group2Index = view.model()->index( 0, 0, provider2Index );
607 QCOMPARE( view.model()->rowCount( group2Index ), 1 );
608 QCOMPARE( view.algorithmForIndex( view.model()->index( 0, 0, group2Index ) )->id(), QStringLiteral( "p2:a1" ) );
609 view.setFilters( QgsProcessingToolboxProxyModel::FilterToolbox );
610 QCOMPARE( view.model()->rowCount(), 1 );
611 provider1Index = view.model()->index( 0, 0, QModelIndex() );
612 QCOMPARE( view.model()->data( provider1Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider1" ) );
613 QCOMPARE( view.model()->rowCount( provider1Index ), 1 );
614 group2Index = view.model()->index( 0, 0, provider1Index );
615 QCOMPARE( view.model()->rowCount( group2Index ), 1 );
616 QCOMPARE( view.algorithmForIndex( view.model()->index( 0, 0, group2Index ) )->id(), QStringLiteral( "p1:a2" ) );
617
618 view.setFilters( QgsProcessingToolboxProxyModel::Filters() );
619 QCOMPARE( view.filters(), QgsProcessingToolboxProxyModel::Filters() );
620 // test filter strings
621 view.setFilterString( "a1" );
622 provider2Index = view.model()->index( 0, 0, QModelIndex() );
623 QCOMPARE( view.model()->data( provider2Index, Qt::DisplayRole ).toString(), QStringLiteral( "provider2" ) );
624 QCOMPARE( view.model()->rowCount(), 1 );
625 QCOMPARE( view.model()->rowCount( provider2Index ), 1 );
626 group2Index = view.model()->index( 0, 0, provider2Index );
627 QCOMPARE( view.model()->rowCount( group2Index ), 1 );
628 QCOMPARE( view.algorithmForIndex( view.model()->index( 0, 0, group2Index ) )->id(), QStringLiteral( "p2:a1" ) );
629
630 view.setFilterString( QString() );
631
632 // selected algorithm
633 provider1Index = view.model()->index( 0, 0, QModelIndex() );
634 view.selectionModel()->clear();
635 QVERIFY( !view.selectedAlgorithm() );
636 view.selectionModel()->select( provider1Index, QItemSelectionModel::ClearAndSelect );
637 QVERIFY( !view.selectedAlgorithm() );
638 group2Index = view.model()->index( 0, 0, provider1Index );
639 view.selectionModel()->select( group2Index, QItemSelectionModel::ClearAndSelect );
640 QVERIFY( !view.selectedAlgorithm() );
641 alg2Index = view.model()->index( 0, 0, group2Index );
642 view.selectionModel()->select( alg2Index, QItemSelectionModel::ClearAndSelect );
643 QCOMPARE( view.selectedAlgorithm()->id(), QStringLiteral( "p1:a2" ) );
644
645 // when a filter string removes the selected algorithm, the next matching algorithm should be auto-selected
646 view.setFilterString( QStringLiteral( "p2:a1" ) );
647 QCOMPARE( view.selectedAlgorithm()->id(), QStringLiteral( "p2:a1" ) );
648 // but if it doesn't remove the selected one, that algorithm should not be deselected
649 view.setFilterString( QStringLiteral( "a" ) );
650 QCOMPARE( view.selectedAlgorithm()->id(), QStringLiteral( "p2:a1" ) );
651
652 // Check view model consistency after resetting registry
653 view.setRegistry( ®istry );
654 QVERIFY( view.mModel );
655 QVERIFY( view.mToolboxModel );
656 QCOMPARE( view.mModel->toolboxModel(), view.mToolboxModel );
657 }
658
testKnownIssues()659 void TestQgsProcessingModel::testKnownIssues()
660 {
661 QgsProcessingRegistry registry;
662 QgsProcessingRecentAlgorithmLog recentLog;
663 const QgsProcessingToolboxModel model( nullptr, ®istry, &recentLog );
664 DummyAlgorithm *a1 = new DummyAlgorithm( "a1", "group1", QgsProcessingAlgorithm::FlagKnownIssues, QStringLiteral( "tag1,tag2" ), QStringLiteral( "short desc a" ) );
665 DummyAlgorithm *a2 = new DummyAlgorithm( "b1", "group1", QgsProcessingAlgorithm::Flags(), 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, ®istry, &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
695
696 }
697
698 QGSTEST_MAIN( TestQgsProcessingModel )
699 #include "testqgsprocessingmodel.moc"
700