mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
Add API framework to handle temporary layers generated by previous runs
We need special handling to transfer temporary layers generated by a model execution when running a partial model from a previous state
This commit is contained in:
parent
20d9657f19
commit
83c7ec07d6
42
src/core/processing/models/qgsprocessingmodelconfig.cpp
Normal file
42
src/core/processing/models/qgsprocessingmodelconfig.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/***************************************************************************
|
||||
qgsprocessingmodelconfig.cpp
|
||||
----------------------
|
||||
begin : April 2024
|
||||
copyright : (C) 2024 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsprocessingmodelconfig.h"
|
||||
#include "qgsmaplayerstore.h"
|
||||
|
||||
QgsProcessingModelInitialRunConfig::QgsProcessingModelInitialRunConfig() = default;
|
||||
|
||||
QgsProcessingModelInitialRunConfig::~QgsProcessingModelInitialRunConfig() = default;
|
||||
|
||||
QgsMapLayerStore *QgsProcessingModelInitialRunConfig::previousLayerStore()
|
||||
{
|
||||
return mModelInitialLayerStore.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<QgsMapLayerStore> QgsProcessingModelInitialRunConfig::takePreviousLayerStore()
|
||||
{
|
||||
return std::move( mModelInitialLayerStore );
|
||||
}
|
||||
|
||||
void QgsProcessingModelInitialRunConfig::setPreviousLayerStore( std::unique_ptr<QgsMapLayerStore> store )
|
||||
{
|
||||
if ( store )
|
||||
{
|
||||
Q_ASSERT_X( !store->thread(), "QgsProcessingModelInitialRunConfig::setPreviousLayerStore", "store must have been pushed to a nullptr thread prior to calling this method" );
|
||||
}
|
||||
mModelInitialLayerStore = std::move( store );
|
||||
}
|
160
src/core/processing/models/qgsprocessingmodelconfig.h
Normal file
160
src/core/processing/models/qgsprocessingmodelconfig.h
Normal file
@ -0,0 +1,160 @@
|
||||
/***************************************************************************
|
||||
qgsprocessingmodelconfig.h
|
||||
----------------------
|
||||
begin : April 2024
|
||||
copyright : (C) 2024 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSPROCESSINGMODELCONFIG_H
|
||||
#define QGSPROCESSINGMODELCONFIG_H
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgis.h"
|
||||
#include <QSet>
|
||||
|
||||
#define SIP_NO_FILE
|
||||
|
||||
class QgsMapLayerStore;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* \brief Configuration settings which control how a Processing model is executed.
|
||||
*
|
||||
* \note Not available in Python bindings.
|
||||
*
|
||||
* \since QGIS 3.38
|
||||
*/
|
||||
class CORE_EXPORT QgsProcessingModelInitialRunConfig
|
||||
{
|
||||
public:
|
||||
|
||||
QgsProcessingModelInitialRunConfig();
|
||||
~QgsProcessingModelInitialRunConfig();
|
||||
|
||||
/**
|
||||
* Returns the subset of child algorithms to run (by child ID).
|
||||
*
|
||||
* An empty set indicates the entire model should be run.
|
||||
*
|
||||
* \see setChildAlgorithmSubset()
|
||||
*/
|
||||
QSet<QString> childAlgorithmSubset() const { return mChildAlgorithmSubset; }
|
||||
|
||||
/**
|
||||
* Sets the \a subset of child algorithms to run (by child ID).
|
||||
*
|
||||
* An empty set indicates the entire model should be run.
|
||||
*
|
||||
* \see childAlgorithmSubset()
|
||||
*/
|
||||
void setChildAlgorithmSubset( const QSet<QString> &subset ) { mChildAlgorithmSubset = subset; }
|
||||
|
||||
/**
|
||||
* Returns the map of child algorithm inputs to use as the initial state when running the model.
|
||||
*
|
||||
* Map keys refer to the child algorithm IDs.
|
||||
*
|
||||
* \see setInitialChildInputs()
|
||||
*/
|
||||
QVariantMap initialChildInputs() { return mInitialChildInputs; }
|
||||
|
||||
/**
|
||||
* Sets the map of child algorithm \a inputs to use as the initial state when running the model.
|
||||
*
|
||||
* Map keys refer to the child algorithm IDs.
|
||||
*
|
||||
* \see initialChildInputs()
|
||||
*/
|
||||
void setInitialChildInputs( const QVariantMap &inputs ) { mInitialChildInputs = inputs; }
|
||||
|
||||
/**
|
||||
* Returns the map of child algorithm outputs to use as the initial state when running the model.
|
||||
*
|
||||
* Map keys refer to the child algorithm IDs.
|
||||
*
|
||||
* \see setInitialChildOutputs()
|
||||
*/
|
||||
QVariantMap initialChildOutputs() { return mInitialChildOutputs; }
|
||||
|
||||
/**
|
||||
* Sets the map of child algorithm \a outputs to use as the initial state when running the model.
|
||||
*
|
||||
* Map keys refer to the child algorithm IDs.
|
||||
*
|
||||
* \see initialChildOutputs()
|
||||
*/
|
||||
void setInitialChildOutputs( const QVariantMap &outputs ) { mInitialChildOutputs = outputs; }
|
||||
|
||||
/**
|
||||
* Returns the set of previously executed child algorithm IDs to use as the initial state
|
||||
* when running the model.
|
||||
*
|
||||
* \see setPreviouslyExecutedChildAlgorithms()
|
||||
*/
|
||||
QSet< QString > previouslyExecutedChildAlgorithms() const { return mPreviouslyExecutedChildren; }
|
||||
|
||||
/**
|
||||
* Sets the previously executed child algorithm IDs to use as the initial state
|
||||
* when running the model.
|
||||
*
|
||||
* \see previouslyExecutedChildAlgorithms()
|
||||
*/
|
||||
void setPreviouslyExecutedChildAlgorithms( const QSet< QString > &children ) { mPreviouslyExecutedChildren = children; }
|
||||
|
||||
/**
|
||||
* Returns a reference to a map store containing copies of temporary layers generated
|
||||
* during previous model executions.
|
||||
*
|
||||
* This may be NULLPTR.
|
||||
*
|
||||
* \see setPreviousLayerStore()
|
||||
* \see takePreviousLayerStore()
|
||||
*/
|
||||
QgsMapLayerStore *previousLayerStore();
|
||||
|
||||
/**
|
||||
* Takes the map store containing copies of temporary layers generated
|
||||
* during previous model executions.
|
||||
*
|
||||
* May return NULLPTR if this is not available.
|
||||
*
|
||||
* \see previousLayerStore()
|
||||
* \see setPreviousLayerStore()
|
||||
*/
|
||||
std::unique_ptr< QgsMapLayerStore > takePreviousLayerStore();
|
||||
|
||||
/**
|
||||
* Sets the map store containing copies of temporary layers generated
|
||||
* during previous model executions.
|
||||
*
|
||||
* \warning \a store must have previous been moved to a NULLPTR thread via a call
|
||||
* to QObject::moveToThread. An assert will be triggered if this condition is not met.
|
||||
*
|
||||
* \see previousLayerStore()
|
||||
* \see takePreviousLayerStore()
|
||||
*/
|
||||
void setPreviousLayerStore( std::unique_ptr< QgsMapLayerStore > store );
|
||||
|
||||
private:
|
||||
|
||||
QSet<QString> mChildAlgorithmSubset;
|
||||
QVariantMap mInitialChildInputs;
|
||||
QVariantMap mInitialChildOutputs;
|
||||
QSet< QString > mPreviouslyExecutedChildren;
|
||||
|
||||
std::unique_ptr< QgsMapLayerStore > mModelInitialLayerStore;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSPROCESSINGMODELCONFIG_H
|
@ -616,6 +616,14 @@ QVariantMap QgsProcessingAlgorithm::runPrepared( const QVariantMap ¶meters,
|
||||
std::unique_ptr< QgsProcessingModelInitialRunConfig > modelConfig = context.takeModelInitialRunConfig();
|
||||
if ( modelConfig )
|
||||
{
|
||||
std::unique_ptr< QgsMapLayerStore > modelPreviousLayerStore = modelConfig->takePreviousLayerStore();
|
||||
if ( modelPreviousLayerStore )
|
||||
{
|
||||
// move layers from previous layer store to context's temporary layer store, in a thread-safe way
|
||||
Q_ASSERT_X( !modelPreviousLayerStore->thread(), "QgsProcessingAlgorithm::runPrepared", "QgsProcessingModelConfig::modelPreviousLayerStore must have been pushed to a nullptr thread" );
|
||||
modelPreviousLayerStore->moveToThread( QThread::currentThread() );
|
||||
runContext->temporaryLayerStore()->transferLayersFromStore( modelPreviousLayerStore.get() );
|
||||
}
|
||||
runContext->setModelInitialRunConfig( std::move( modelConfig ) );
|
||||
}
|
||||
|
||||
|
@ -2475,6 +2475,24 @@ void TestQgsProcessingModelAlgorithm::modelExecuteWithPreviousState()
|
||||
QCOMPARE( firstResult.childResults().value( "calculate2" ).outputs().value( "OUTPUT" ).toString(), QStringLiteral( "a different string_2" ) );
|
||||
QCOMPARE( firstResult.rawChildInputs().value( "calculate2" ).toMap().value( "INPUT" ).toString(), QStringLiteral( "a different string_2" ) );
|
||||
QCOMPARE( firstResult.rawChildOutputs().value( "calculate2" ).toMap().value( "OUTPUT" ).toString(), QStringLiteral( "a different string_2" ) );
|
||||
|
||||
QCOMPARE( context.temporaryLayerStore()->count(), 0 );
|
||||
|
||||
// test handling of temporary layers generated during earlier runs
|
||||
modelConfig = std::make_unique< QgsProcessingModelInitialRunConfig >();
|
||||
|
||||
std::unique_ptr < QgsMapLayerStore > previousStore = std::make_unique< QgsMapLayerStore >();
|
||||
QgsVectorLayer *layer = new QgsVectorLayer( "Point?crs=epsg:3111", "v1", "memory" );
|
||||
previousStore->addMapLayer( layer );
|
||||
previousStore->moveToThread( nullptr );
|
||||
modelConfig->setPreviousLayerStore( std::move( previousStore ) );
|
||||
|
||||
context.setModelInitialRunConfig( std::move( modelConfig ) );
|
||||
m.run( params, context, &feedback, &ok );
|
||||
QVERIFY( ok );
|
||||
// layer should have been transferred to context's temporary layer store as part of model execution
|
||||
QCOMPARE( context.temporaryLayerStore()->count(), 1 );
|
||||
QCOMPARE( context.temporaryLayerStore()->mapLayersByName( QStringLiteral( "v1" ) ).at( 0 ), layer );
|
||||
}
|
||||
|
||||
void TestQgsProcessingModelAlgorithm::modelDependencies()
|
||||
|
Loading…
x
Reference in New Issue
Block a user