Skip to content

Commit 5350483

Browse files
committed
Add method to take results from another processing context and
add to the current context With appropriate note and tests to ensure that both the current context and that which the results being taken from share the same thread affinity
1 parent d20c68d commit 5350483

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

python/core/processing/qgsprocessingcontext.sip

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,15 @@ Destination project
237237
.. seealso:: thread()
238238
%End
239239

240+
void takeResultsFrom( QgsProcessingContext &context );
241+
%Docstring
242+
Takes the results from another ``context`` and merges them with the results currently
243+
stored in this context. This includes settings like any layers loaded in the temporaryLayerStore()
244+
and layersToLoadOnCompletion().
245+
This is only safe to call when both this context and the other ``context`` share the same
246+
thread() affinity, and that thread is the current thread.
247+
%End
248+
240249
private:
241250
QgsProcessingContext( const QgsProcessingContext &other );
242251
};

src/core/processing/qgsprocessingcontext.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,29 @@ class CORE_EXPORT QgsProcessingContext
340340
*/
341341
void pushToThread( QThread *thread )
342342
{
343-
Q_ASSERTX( QThread::currentThread() == thread(), "QgsProcessingContext::pushToThread", "Cannot push context to another thread unless the current thread matches the existing context thread affinity" );
343+
Q_ASSERT_X( QThread::currentThread() == QgsProcessingContext::thread(), "QgsProcessingContext::pushToThread", "Cannot push context to another thread unless the current thread matches the existing context thread affinity" );
344344
tempLayerStore.moveToThread( thread );
345345
}
346346

347+
/**
348+
* Takes the results from another \a context and merges them with the results currently
349+
* stored in this context. This includes settings like any layers loaded in the temporaryLayerStore()
350+
* and layersToLoadOnCompletion().
351+
* This is only safe to call when both this context and the other \a context share the same
352+
* thread() affinity, and that thread is the current thread.
353+
*/
354+
void takeResultsFrom( QgsProcessingContext &context )
355+
{
356+
QMap< QString, LayerDetails > loadOnCompletion = context.layersToLoadOnCompletion();
357+
QMap< QString, LayerDetails >::const_iterator llIt = loadOnCompletion.constBegin();
358+
for ( ; llIt != loadOnCompletion.constEnd(); ++llIt )
359+
{
360+
mLayersToLoadOnCompletion.insert( llIt.key(), llIt.value() );
361+
}
362+
context.setLayersToLoadOnCompletion( QMap< QString, LayerDetails >() );
363+
tempLayerStore.transferLayersFromStore( context.temporaryLayerStore() );
364+
}
365+
347366
private:
348367

349368
QgsProcessingContext::Flags mFlags = 0;

tests/src/core/testqgsprocessing.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,12 +583,18 @@ void TestQgsProcessing::context()
583583
context.setInvalidGeometryCheck( QgsFeatureRequest::GeometrySkipInvalid );
584584
QCOMPARE( context.invalidGeometryCheck(), QgsFeatureRequest::GeometrySkipInvalid );
585585

586+
QgsVectorLayer *vector = new QgsVectorLayer( "Polygon", "vector", "memory" );
587+
context.temporaryLayerStore()->addMapLayer( vector );
588+
QCOMPARE( context.temporaryLayerStore()->mapLayer( vector->id() ), vector );
589+
586590
QgsProcessingContext context2;
587591
context2.copyThreadSafeSettings( context );
588592
QCOMPARE( context2.defaultEncoding(), context.defaultEncoding() );
589593
QCOMPARE( context2.invalidGeometryCheck(), context.invalidGeometryCheck() );
590594
QCOMPARE( context2.flags(), context.flags() );
591595
QCOMPARE( context2.project(), context.project() );
596+
// layers from temporaryLayerStore must not be copied by copyThreadSafeSettings
597+
QVERIFY( context2.temporaryLayerStore()->mapLayers().isEmpty() );
592598

593599
// layers to load on completion
594600
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon", "V1", "memory" );
@@ -606,6 +612,11 @@ void TestQgsProcessing::context()
606612
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "v1" ) );
607613
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 1 ), v2->id() );
608614
QCOMPARE( context.layersToLoadOnCompletion().values().at( 1 ).name, QStringLiteral( "v2" ) );
615+
616+
// ensure that copyThreadSafeSettings doesn't copy layersToLoadOnCompletion()
617+
context2.copyThreadSafeSettings( context );
618+
QVERIFY( context2.layersToLoadOnCompletion().isEmpty() );
619+
609620
layers.clear();
610621
layers.insert( v2->id(), QgsProcessingContext::LayerDetails( QStringLiteral( "v2" ), &p ) );
611622
context.setLayersToLoadOnCompletion( layers );
@@ -616,8 +627,20 @@ void TestQgsProcessing::context()
616627
QCOMPARE( context.layersToLoadOnCompletion().count(), 2 );
617628
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), v1->id() );
618629
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 1 ), v2->id() );
619-
delete v1;
620-
delete v2;
630+
631+
context.temporaryLayerStore()->addMapLayer( v1 );
632+
context.temporaryLayerStore()->addMapLayer( v2 );
633+
634+
// test takeResultsFrom
635+
context2.takeResultsFrom( context );
636+
QVERIFY( context.temporaryLayerStore()->mapLayers().isEmpty() );
637+
QVERIFY( context.layersToLoadOnCompletion().isEmpty() );
638+
// should now be in context2
639+
QCOMPARE( context2.temporaryLayerStore()->mapLayer( v1->id() ), v1 );
640+
QCOMPARE( context2.temporaryLayerStore()->mapLayer( v2->id() ), v2 );
641+
QCOMPARE( context2.layersToLoadOnCompletion().count(), 2 );
642+
QCOMPARE( context2.layersToLoadOnCompletion().keys().at( 0 ), v1->id() );
643+
QCOMPARE( context2.layersToLoadOnCompletion().keys().at( 1 ), v2->id() );
621644
}
622645

623646
void TestQgsProcessing::mapLayers()

0 commit comments

Comments
 (0)