Skip to content

Commit 81da209

Browse files
committed
Use a QgsProject pointer instead of bool loadIntoProject
Allows potential future use case of loading results into a different open project
1 parent 72be86d commit 81da209

File tree

8 files changed

+106
-52
lines changed

8 files changed

+106
-52
lines changed

python/core/processing/qgsprocessingcontext.sip

+27-7
Original file line numberDiff line numberDiff line change
@@ -83,25 +83,45 @@ class QgsProcessingContext
8383
:rtype: QgsMapLayerStore
8484
%End
8585

86-
QgsStringMap layersToLoadOnCompletion() const;
86+
struct LayerDetails
87+
{
88+
89+
LayerDetails( const QString &name, QgsProject *project );
90+
%Docstring
91+
Constructor for LayerDetails.
92+
%End
93+
94+
QString name;
95+
%Docstring
96+
Friendly name for layer, to use when loading layer into project.
97+
%End
98+
99+
QgsProject *project;
100+
%Docstring
101+
Destination project
102+
%End
103+
104+
};
105+
106+
QMap< QString, QgsProcessingContext::LayerDetails > layersToLoadOnCompletion() const;
87107
%Docstring
88-
Returns a map of layers (by ID or datasource) to friendly layer name, to load into the canvas upon completion of the algorithm or model.
108+
Returns a map of layers (by ID or datasource) to LayerDetails, to load into the canvas upon completion of the algorithm or model.
89109
.. seealso:: setLayersToLoadOnCompletion()
90110
.. seealso:: addLayerToLoadOnCompletion()
91-
:rtype: QgsStringMap
111+
:rtype: QMap< str, QgsProcessingContext.LayerDetails >
92112
%End
93113

94-
void setLayersToLoadOnCompletion( const QgsStringMap &layers );
114+
void setLayersToLoadOnCompletion( const QMap< QString, QgsProcessingContext::LayerDetails > &layers );
95115
%Docstring
96-
Sets the map of ``layers`` (by ID or datasource) to friendly layer name, to load into the canvas upon completion of the algorithm or model.
116+
Sets the map of ``layers`` (by ID or datasource) to LayerDetails, to load into the canvas upon completion of the algorithm or model.
97117
.. seealso:: addLayerToLoadOnCompletion()
98118
.. seealso:: layersToLoadOnCompletion()
99119
%End
100120

101-
void addLayerToLoadOnCompletion( const QString &layer, const QString &name );
121+
void addLayerToLoadOnCompletion( const QString &layer, const QgsProcessingContext::LayerDetails &details );
102122
%Docstring
103123
Adds a ``layer`` to load (by ID or datasource) into the canvas upon completion of the algorithm or model.
104-
The ``name`` parameter dictates a friendly display name for the layer.
124+
The ``details`` parameter dictates the LayerDetails.
105125
.. seealso:: setLayersToLoadOnCompletion()
106126
.. seealso:: layersToLoadOnCompletion()
107127
%End

python/core/processing/qgsprocessingparameters.sip

+10-4
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,30 @@ class QgsProcessingFeatureSink
7070
%End
7171
public:
7272

73-
QgsProcessingFeatureSink( const QString &sink = QString(), bool loadIntoProject = false );
73+
QgsProcessingFeatureSink( const QString &sink = QString(), QgsProject *destinationProject = 0 );
7474
%Docstring
7575
Constructor for QgsProcessingFeatureSink, accepting a static string sink.
76+
The ``destinationProject`` parameter can be set to a QgsProject instance in which
77+
to automatically load the resulting sink after completing processing.
7678
%End
7779

78-
QgsProcessingFeatureSink( const QgsProperty &sink, bool loadIntoProject = false );
80+
QgsProcessingFeatureSink( const QgsProperty &sink, QgsProject *destinationProject = 0 );
7981
%Docstring
8082
Constructor for QgsProcessingFeatureSink, accepting a QgsProperty sink.
83+
The ``destinationProject`` parameter can be set to a QgsProject instance in which
84+
to automatically load the resulting sink after completing processing.
8185
%End
8286

8387
QgsProperty sink;
8488
%Docstring
8589
Sink definition. Usually a static property set to the destination file name for the sink's layer.
8690
%End
8791

88-
bool loadIntoProject;
92+
QgsProject *destinationProject;
8993
%Docstring
90-
True if sink should be loaded into the current project when the algorithm completes.
94+
Destination project. Can be set to a QgsProject instance in which
95+
to automatically load the resulting sink after completing processing.
96+
The default behavior is not to load the result into any project (None).
9197
%End
9298

9399
QVariantMap createOptions;

python/plugins/processing/gui/AlgorithmDialog.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,13 @@ def getParamValues(self):
110110
if not param.checkValueIsAcceptable(value):
111111
raise AlgorithmDialogBase.InvalidParameterValue(param, wrapper.widget)
112112
else:
113-
open_after_run = False
113+
dest_project = None
114114
if not param.flags() & QgsProcessingParameterDefinition.FlagHidden and \
115115
isinstance(param, (OutputRaster, QgsProcessingParameterFeatureSink, OutputTable)):
116116
if self.mainWidget.checkBoxes[param.name()].isChecked():
117-
open_after_run = True
117+
dest_project = QgsProject.instance()
118118

119-
parameters[param.name()] = QgsProcessingFeatureSink(self.mainWidget.outputWidgets[param.name()].getValue(), open_after_run)
119+
parameters[param.name()] = QgsProcessingFeatureSink(self.mainWidget.outputWidgets[param.name()].getValue(), dest_project)
120120

121121
return parameters
122122

python/plugins/processing/gui/Postprocessing.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,15 @@ def handleAlgorithmResults(alg, context, feedback=None, showResults=True):
5555
feedback = QgsProcessingFeedback()
5656
feedback.setProgressText(QCoreApplication.translate('Postprocessing', 'Loading resulting layers'))
5757
i = 0
58-
for l, name in context.layersToLoadOnCompletion().items():
58+
for l, details in context.layersToLoadOnCompletion().items():
5959
feedback.setProgress(100 * i / float(len(context.layersToLoadOnCompletion())))
6060
try:
6161
layer = QgsProcessingUtils.mapLayerFromString(l, context)
6262
if layer:
63-
layer.setName(name)
64-
QgsProject.instance().addMapLayer(context.temporaryLayerStore().takeMapLayer(layer))
63+
layer.setName(details.name)
64+
details.project.addMapLayer(context.temporaryLayerStore().takeMapLayer(layer))
6565
else:
66+
name = details.name
6667
if ProcessingConfig.getSetting(
6768
ProcessingConfig.USE_FILENAME_AS_LAYER_NAME):
6869
name = os.path.basename(l)

src/core/processing/qgsprocessingcontext.h

+28-8
Original file line numberDiff line numberDiff line change
@@ -101,35 +101,55 @@ class CORE_EXPORT QgsProcessingContext
101101
*/
102102
QgsMapLayerStore *temporaryLayerStore() { return &tempLayerStore; }
103103

104+
//! Details for layers to load into projects.
105+
struct LayerDetails
106+
{
107+
108+
/**
109+
* Constructor for LayerDetails.
110+
*/
111+
LayerDetails( const QString &name, QgsProject *project )
112+
: name( name )
113+
, project( project )
114+
{}
115+
116+
//! Friendly name for layer, to use when loading layer into project.
117+
QString name;
118+
119+
//! Destination project
120+
QgsProject *project;
121+
122+
};
123+
104124
/**
105-
* Returns a map of layers (by ID or datasource) to friendly layer name, to load into the canvas upon completion of the algorithm or model.
125+
* Returns a map of layers (by ID or datasource) to LayerDetails, to load into the canvas upon completion of the algorithm or model.
106126
* \see setLayersToLoadOnCompletion()
107127
* \see addLayerToLoadOnCompletion()
108128
*/
109-
QgsStringMap layersToLoadOnCompletion() const
129+
QMap< QString, QgsProcessingContext::LayerDetails > layersToLoadOnCompletion() const
110130
{
111131
return mLayersToLoadOnCompletion;
112132
}
113133

114134
/**
115-
* Sets the map of \a layers (by ID or datasource) to friendly layer name, to load into the canvas upon completion of the algorithm or model.
135+
* Sets the map of \a layers (by ID or datasource) to LayerDetails, to load into the canvas upon completion of the algorithm or model.
116136
* \see addLayerToLoadOnCompletion()
117137
* \see layersToLoadOnCompletion()
118138
*/
119-
void setLayersToLoadOnCompletion( const QgsStringMap &layers )
139+
void setLayersToLoadOnCompletion( const QMap< QString, QgsProcessingContext::LayerDetails > &layers )
120140
{
121141
mLayersToLoadOnCompletion = layers;
122142
}
123143

124144
/**
125145
* Adds a \a layer to load (by ID or datasource) into the canvas upon completion of the algorithm or model.
126-
* The \a name parameter dictates a friendly display name for the layer.
146+
* The \a details parameter dictates the LayerDetails.
127147
* \see setLayersToLoadOnCompletion()
128148
* \see layersToLoadOnCompletion()
129149
*/
130-
void addLayerToLoadOnCompletion( const QString &layer, const QString &name )
150+
void addLayerToLoadOnCompletion( const QString &layer, const QgsProcessingContext::LayerDetails &details )
131151
{
132-
mLayersToLoadOnCompletion.insert( layer, name );
152+
mLayersToLoadOnCompletion.insert( layer, details );
133153
}
134154

135155
/**
@@ -209,7 +229,7 @@ class CORE_EXPORT QgsProcessingContext
209229
QgsFeatureRequest::InvalidGeometryCheck mInvalidGeometryCheck = QgsFeatureRequest::GeometryNoCheck;
210230
std::function< void( const QgsFeature & ) > mInvalidGeometryCallback;
211231
QString mDefaultEncoding;
212-
QgsStringMap mLayersToLoadOnCompletion;
232+
QMap< QString, LayerDetails > mLayersToLoadOnCompletion;
213233

214234
#ifdef SIP_RUN
215235
QgsProcessingContext( const QgsProcessingContext &other );

src/core/processing/qgsprocessingparameters.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,13 @@ QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingPar
213213
val = parameters.value( definition->name() );
214214
}
215215

216-
bool loadIntoProject = false;
216+
QgsProject *destinationProject = nullptr;
217217
QVariantMap createOptions;
218218
if ( val.canConvert<QgsProcessingFeatureSink>() )
219219
{
220220
// input is a QgsProcessingFeatureSink - get extra properties from it
221221
QgsProcessingFeatureSink fromVar = qvariant_cast<QgsProcessingFeatureSink>( val );
222-
loadIntoProject = fromVar.loadIntoProject;
222+
destinationProject = fromVar.destinationProject;
223223
createOptions = fromVar.createOptions;
224224
val = fromVar.sink;
225225
}
@@ -242,8 +242,8 @@ QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingPar
242242
std::unique_ptr< QgsFeatureSink > sink( QgsProcessingUtils::createFeatureSink( dest, context, fields, geometryType, crs, createOptions ) );
243243
destinationIdentifier = dest;
244244

245-
if ( loadIntoProject )
246-
context.addLayerToLoadOnCompletion( destinationIdentifier, definition ? definition->description() : QString() );
245+
if ( destinationProject )
246+
context.addLayerToLoadOnCompletion( destinationIdentifier, QgsProcessingContext::LayerDetails( definition ? definition->description() : QString(), destinationProject ) );
247247

248248
return sink.release();
249249
}

src/core/processing/qgsprocessingparameters.h

+12-6
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,22 @@ class CORE_EXPORT QgsProcessingFeatureSink
9797

9898
/**
9999
* Constructor for QgsProcessingFeatureSink, accepting a static string sink.
100+
* The \a destinationProject parameter can be set to a QgsProject instance in which
101+
* to automatically load the resulting sink after completing processing.
100102
*/
101-
QgsProcessingFeatureSink( const QString &sink = QString(), bool loadIntoProject = false )
103+
QgsProcessingFeatureSink( const QString &sink = QString(), QgsProject *destinationProject = nullptr )
102104
: sink( QgsProperty::fromValue( sink ) )
103-
, loadIntoProject( loadIntoProject )
105+
, destinationProject( destinationProject )
104106
{}
105107

106108
/**
107109
* Constructor for QgsProcessingFeatureSink, accepting a QgsProperty sink.
110+
* The \a destinationProject parameter can be set to a QgsProject instance in which
111+
* to automatically load the resulting sink after completing processing.
108112
*/
109-
QgsProcessingFeatureSink( const QgsProperty &sink, bool loadIntoProject = false )
113+
QgsProcessingFeatureSink( const QgsProperty &sink, QgsProject *destinationProject = nullptr )
110114
: sink( sink )
111-
, loadIntoProject( loadIntoProject )
115+
, destinationProject( destinationProject )
112116
{}
113117

114118
/**
@@ -117,9 +121,11 @@ class CORE_EXPORT QgsProcessingFeatureSink
117121
QgsProperty sink;
118122

119123
/**
120-
* True if sink should be loaded into the current project when the algorithm completes.
124+
* Destination project. Can be set to a QgsProject instance in which
125+
* to automatically load the resulting sink after completing processing.
126+
* The default behavior is not to load the result into any project (nullptr).
121127
*/
122-
bool loadIntoProject;
128+
QgsProject *destinationProject;
123129

124130
/**
125131
* Map of optional sink creation options, which

tests/src/core/testqgsprocessing.cpp

+18-17
Original file line numberDiff line numberDiff line change
@@ -467,25 +467,25 @@ void TestQgsProcessing::context()
467467
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon", "V1", "memory" );
468468
QgsVectorLayer *v2 = new QgsVectorLayer( "Polygon", "V2", "memory" );
469469
QVERIFY( context.layersToLoadOnCompletion().isEmpty() );
470-
QgsStringMap layers;
471-
layers.insert( v1->id(), QStringLiteral( "v1" ) );
470+
QMap< QString, QgsProcessingContext::LayerDetails > layers;
471+
layers.insert( v1->id(), QgsProcessingContext::LayerDetails( QStringLiteral( "v1" ), &p ) );
472472
context.setLayersToLoadOnCompletion( layers );
473473
QCOMPARE( context.layersToLoadOnCompletion().count(), 1 );
474474
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), v1->id() );
475-
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ), QStringLiteral( "v1" ) );
476-
context.addLayerToLoadOnCompletion( v2->id(), QStringLiteral( "v2" ) );
475+
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "v1" ) );
476+
context.addLayerToLoadOnCompletion( v2->id(), QgsProcessingContext::LayerDetails( QStringLiteral( "v2" ), &p ) );
477477
QCOMPARE( context.layersToLoadOnCompletion().count(), 2 );
478478
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), v1->id() );
479-
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ), QStringLiteral( "v1" ) );
479+
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "v1" ) );
480480
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 1 ), v2->id() );
481-
QCOMPARE( context.layersToLoadOnCompletion().values().at( 1 ), QStringLiteral( "v2" ) );
481+
QCOMPARE( context.layersToLoadOnCompletion().values().at( 1 ).name, QStringLiteral( "v2" ) );
482482
layers.clear();
483-
layers.insert( v2->id(), QStringLiteral( "v2" ) );
483+
layers.insert( v2->id(), QgsProcessingContext::LayerDetails( QStringLiteral( "v2" ), &p ) );
484484
context.setLayersToLoadOnCompletion( layers );
485485
QCOMPARE( context.layersToLoadOnCompletion().count(), 1 );
486486
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), v2->id() );
487-
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ), QStringLiteral( "v2" ) );
488-
context.addLayerToLoadOnCompletion( v1->id(), QString() );
487+
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "v2" ) );
488+
context.addLayerToLoadOnCompletion( v1->id(), QgsProcessingContext::LayerDetails( QString(), &p ) );
489489
QCOMPARE( context.layersToLoadOnCompletion().count(), 2 );
490490
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), v1->id() );
491491
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 1 ), v2->id() );
@@ -1148,8 +1148,9 @@ void TestQgsProcessing::parameters()
11481148
QCOMPARE( layer->crs(), crs );
11491149

11501150
// QgsProcessingFeatureSink as parameter
1151+
QgsProject p;
11511152
QgsProcessingFeatureSink fs( QStringLiteral( "test.shp" ) );
1152-
fs.loadIntoProject = true;
1153+
fs.destinationProject = &p;
11531154
QVERIFY( context.layersToLoadOnCompletion().isEmpty() );
11541155
params.insert( QStringLiteral( "fs" ), QVariant::fromValue( fs ) );
11551156
def->setName( QStringLiteral( "fs" ) );
@@ -1167,7 +1168,7 @@ void TestQgsProcessing::parameters()
11671168
// make sure layer was automatically added to list to load on completion
11681169
QCOMPARE( context.layersToLoadOnCompletion().size(), 1 );
11691170
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), destId );
1170-
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ), QStringLiteral( "desc" ) );
1171+
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "desc" ) );
11711172

11721173
delete def;
11731174
}
@@ -2376,27 +2377,27 @@ void TestQgsProcessing::processingFeatureSource()
23762377
void TestQgsProcessing::processingFeatureSink()
23772378
{
23782379
QString sinkString( QStringLiteral( "test.shp" ) );
2379-
QgsProcessingFeatureSink fs( sinkString, true );
2380+
QgsProject p;
2381+
QgsProcessingFeatureSink fs( sinkString, &p );
23802382
QCOMPARE( fs.sink.staticValue().toString(), sinkString );
2381-
QVERIFY( fs.loadIntoProject );
2383+
QCOMPARE( fs.destinationProject, &p );
23822384

23832385
// test storing QgsProcessingFeatureSink in variant and retrieving
23842386
QVariant fsInVariant = QVariant::fromValue( fs );
23852387
QVERIFY( fsInVariant.isValid() );
23862388

23872389
QgsProcessingFeatureSink fromVar = qvariant_cast<QgsProcessingFeatureSink>( fsInVariant );
23882390
QCOMPARE( fromVar.sink.staticValue().toString(), sinkString );
2389-
QVERIFY( fromVar.loadIntoProject );
2391+
QCOMPARE( fromVar.destinationProject, &p );
23902392

23912393
// test evaluating parameter as sink
2392-
QgsProject p;
23932394
QgsProcessingContext context;
23942395
context.setProject( &p );
23952396

23962397
// first using static string definition
23972398
QgsProcessingParameterDefinition *def = new QgsProcessingParameterString( QStringLiteral( "layer" ) );
23982399
QVariantMap params;
2399-
params.insert( QStringLiteral( "layer" ), QgsProcessingFeatureSink( "memory:test", false ) );
2400+
params.insert( QStringLiteral( "layer" ), QgsProcessingFeatureSink( "memory:test", nullptr ) );
24002401
QString dest;
24012402
std::unique_ptr< QgsFeatureSink > sink( QgsProcessingParameters::parameterAsSink( def, params, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem( "EPSG:3111" ), context, dest ) );
24022403
QVERIFY( sink.get() );
@@ -2405,7 +2406,7 @@ void TestQgsProcessing::processingFeatureSink()
24052406
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
24062407

24072408
// next using property based definition
2408-
params.insert( QStringLiteral( "layer" ), QgsProcessingFeatureSink( QgsProperty::fromExpression( QStringLiteral( "trim('memory' + ':test2')" ) ), false ) );
2409+
params.insert( QStringLiteral( "layer" ), QgsProcessingFeatureSink( QgsProperty::fromExpression( QStringLiteral( "trim('memory' + ':test2')" ) ), nullptr ) );
24092410
sink.reset( QgsProcessingParameters::parameterAsSink( def, params, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem( "EPSG:3113" ), context, dest ) );
24102411
QVERIFY( sink.get() );
24112412
QgsVectorLayer *layer2 = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( dest, context, false ) );

0 commit comments

Comments
 (0)