[QGIS-Developer] How to access QgisApp::instance() from a core class

Nyall Dawson nyall.dawson at gmail.com
Mon Mar 7 14:52:19 PST 2022


On Tue, 8 Mar 2022 at 07:23, Schmetzer, Tobias
<Tobias.Schmetzer at zae-bayern.de> wrote:
>
> > Again, none of the core classes are allowed any GUI component, and the correct approach to handle this particular situation is to move that code from the provider level up to app level, specifically via the QgsDataItemGuiProvider class.
>
>
> I had a look into it. If I understood it correctly the class provides a framework for functions to be registered and called by other functions placed in the gui.
>
> But what to do when a progress dialog needs to be raised or an application state needs to be read? (see description below)
>
>
> > So my question would be: why do you need to raise a user-facing message from QgsOgrProvider::extent?
>
>
> - One idea was is to inform the user via a simple progress dialog in cases of very time-consuming extent calculations for large layers (I observed calc time ranges from 10 min to hours) of what's going on and that QGIS hasn't crashed yet. The design would practically allow this to be implemented in the provider . If that's also not how it is intended to be then I'd appreciate a quick hint of how it is intended to be.

Offhand, there's a couple of ways to approach something like this:

1. You add appropriate signals in the core classes which are emitted
at useful stages, e.g. "aboutToCalculateExtent",
"extentCalculationProgressChanged", "extentCalculationComplete". And
then the app/gui classes can listen out for these signals and respond
to them appropriately, i.e. by showing a progress bar somewhere.

2. You could add a QgsFeedback* argument to the costly method, and use
that to report progress and support early cancellation.

(2 is a more flexible, "better" approach, but depending on the method
you may not be able to add this to an existing method without breaking
stable API.

> and I also saw the use of QProgressDialog in other parts of the core components code

That's likely just outdated code which hasn't been removed yet.

>
>
> - The second idea was to display an additional message dependant on the current QGIS instance's project state (whether it's loading/loaded/saving/closed) for which I had planned to introduce an enum QgisApp::ProjectState alongside with a private variable mProjectState and a public function QgisApp::getProjectState(). So would I make this accessible to the provider?

That property sounds potentially useful! (Just a note that QGIS code
convention is to name a getter "projectState()", not
"getProjectState(). We follow Qt conventions for naming as much as
possible).

But... (there's always a catch!) You can't (well, shouldn't) access
QgsProject from a data provider*.  So you'd need to change the
behaviour at a higher level based on the project state instead. (e.g.
by not calling some expensive method which can be deferred from the
app level code)

Nyall

* the virtual data provider does this, but it's special, and really
shouldn't anyway.

>
>
> Best regards
>
> Tobias
>
> --
>
> ZAE Bayern
> Dipl.-Ing. Tobias Schmetzer
> Systementwicklung | Systems Engineering
> Bereich Energiespeicherung | Division Energy Storage
> Walther-Meißner-Straße 6
> 85748 Garching
>
> Tel.: +49 89 329442-65
> Fax: +49 89 329442-12
> Mobil | Cell: +49 151 56964756
> tobias.schmetzer at zae-bayern.de
> https://www.zae-bayern.de
>
> ZAE Bayern
> Bayerisches Zentrum für Angewandte Energieforschung e. V. | Bavarian Center for Applied Energy Research
> Vorstand | Board: Dr. Andreas Hauer (Vorsitzender | Chairman), Dr. Hans-Peter Ebert
> Sitz | Registered Office: Würzburg
> Registergericht | Register Court: Amtsgericht Würzburg
> Registernummer | Register Number: VR 1386
>
> Hinweise zum Datenschutz unter https://www.zae-bayern.de/datenschutz
>
>
>
> ________________________________
> Von: Nyall Dawson <nyall.dawson at gmail.com>
> Gesendet: Montag, 7. März 2022 00:03
> An: Schmetzer, Tobias
> Cc: qgis-developer at lists.osgeo.org
> Betreff: Re: [QGIS-Developer] How to access QgisApp::instance() from a core class
>
> On Sun, 6 Mar 2022 at 00:16, Schmetzer, Tobias via QGIS-Developer
> <qgis-developer at lists.osgeo.org> wrote:
> >
> > Hello everyone,
> >
> >
> > I would like to access QgisApp::instance() (src/app/qgisapp.cpp) from a provider like QgsOgrProvider::extent() (src/core/providers/ogr/qgsogrprovider.cpp.
>
> You can't, by design.
>
> CORE classes must be completely non-gui, so that they work without
> issue on non-gui platforms like QGIS server (also for clients which
> have their own GUI, such as QFIeld/Input).
>
> Just to be super-blunt: There is 100% no way this will EVER change! ;)
>
>
> > When looking for this information I found some inactivating preprocessor code block comments like this one (qgswfsdataitems.cpp):
> >
> > #if 0
> >
> >     // TODO: how to emit message from provider (which does not know about QgisApp)
> >     QgisApp::instance()->messageBar()->pushMessage( tr( "Cannot copy style" ),
> >         errorMsg,
> >         Qgis::MessageLevel::Critical, messageTimeout() );
> > #endif
>
> This is very old code (hence why it's disabled). Again, none of the
> core classes are allowed any GUI component, and the correct approach
> to handle this particular situation is to move that code from the
> provider level up to app level, specifically via the
> QgsDataItemGuiProvider class.
>
> So my question would be: why do you need to raise a user-facing
> message from QgsOgrProvider::extent?
>
> Nyall


More information about the QGIS-Developer mailing list