Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run QgsProcessingAlgorithm with explicitely defined QgsProcessingContext and QgisInterfaces. #60805

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

jakimowb
Copy link
Contributor

@jakimowb jakimowb commented Feb 28, 2025

Description

This PR addresses #60764 and enables the processing plugin to execute QgsProcessingAlgorithms with none-standard QgsProcessingContext and QgisInterface.

It is now possible use the algorithm dialogs with a set of map layers that differs from layers inside the QgsProject.instance().
This allows plugin developers to focus on layers relevant for their QGIS plugin, or to avoid messing up with layers inside the global project QgsProject.instance(). Developers can now provide a QgsProcessingContext object (with its own context.project()).

Some algorithms callers of processing algorithms may want to add processing results back to a QgsMapCanvas, or read a mapcanvas extent.
By providing an own QgsInterface aka iface different to that from the main QGIS GUI (from qgis.utils import iface), it becomes possible to provide an explicit mapcanvas and layer handling.

Examples for the new functionality are given by two new unit test in
python/plugins/processing/tests/GuiTest.py:

  1. def testIndividualProcessingContext(self): shows how AlgorithmDialog and BatchAlgorithmDialog can be called with a self-defined context + iface,

  2. def testProcessingPlugin_executeAlgorithm(self): shows how ProcessingPlugin.executeAlgorithm(...) can be called with an explicitly defined context and iface. As this test creates a blocking dialogs it is disable for running in a CI.

@github-actions github-actions bot added this to the 3.44.0 milestone Feb 28, 2025
Copy link

github-actions bot commented Feb 28, 2025

🪟 Windows builds

Download Windows builds of this PR for testing.
Debug symbols for this build are available here.
(Built from commit f25a515)

🪟 Windows Qt6 builds

Download Windows Qt6 builds of this PR for testing.
(Built from commit f25a515)

@nyalldawson
Copy link
Collaborator

Some algorithms may want to add processing results back to a QgsMapCanvas, or read a mapcanvas extent.
By providing an own QgsInterface aka iface different to that from the main QGIS GUI (from qgis.utils import iface), it becomes possible to provide an explicit mapcanvas and layer handling.

Is this just theoretical? None of the built-in algorithms do this. And if an algorithm does try this, it still won't have access to the iface object as that's not part of the context passed to algorithms anyway.

@jakimowb
Copy link
Contributor Author

jakimowb commented Mar 1, 2025

Sorry, I actually mean the callers of QgsProcessingAlgorithms and have corrected my description above.

The ProcessingPanel uses the iface to create the QgsWidgetContext for parameter widgets, and Postprocessing.py handleAlgorithmResults calls iface.setActiveLayer(<produced layer>). If both were enabled to use a different context.project() and iface, then a much more flexible use of the processing framework would be possible.

For example, the EnMAP-Box and the EO TimeSeriesViewer plugins extend QGIS by additional QMainWindows, e.g. to be used on a 2nd screen, and visualize map layers in multiple QgsMapCanvases side by side.

grafik

Both implement a QgisInterface and have their own QgsLayerTreeView and QgsProject to not mess-up the standard QGIS layer tree and QgsProject.instance():

class EnMAPBox(QgisInterface, QObject, QgsExpressionContextGenerator, QgsProcessingContextGenerator):
   
class EOTimeSeriesViewer(QgisInterface, QObject):

If QgsProcessingAlgorithms like Create Layer from extent (native:extenttolayer) are started from them, users expect that parameterization dialogs also use one of the EnMAP-Box/EO Time Series map canvases instead of the main QGIS map canvas, e.g. to get the canvas extent. If there is an "open after running" option, user expect that produced layers are added to the EnMAP-Box/EO Time Series Viewer GUI (as now they are added to the QGIS layer tree and different steps are required to get them into the EnMAP-Box).

grafik

To comply with the QgisInterface, some of the QgisInterface functions can be implemented as (pseudo-code):

    def mapCanvas(self) -> QgsMapCanvas:
        return <last map canvas that was used / touched by a user>
    def activeLayer(self) -> QgsMapCanvas:
        return <last layer selected in a layer tree>
    def mainWindow(self) -> QWidget:
        return <main EnMAP-Box / EO Time Series Viewer window or other widget>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants