Bug report #19311

setCrs() works incorrectly during Python plugin loading

Added by Igor Evdokimov over 5 years ago. Updated over 5 years ago.

Status:Open
Priority:Normal
Assignee:-
Category:Python plugins
Affected QGIS version:3.2 Regression?:No
Operating System:Windows 7 x64 Easy fix?:No
Pull Request or Patch supplied:No Resolution:
Crashes QGIS or corrupts data:No Copied to github as #:27139

Description

I have this code at the end of plugin loading (Python 3.6):

for data_dict in __DATA:
....
vlayer = QgsVectorLayer(uri.uri(), _v_layer0, _v_layer1)
QgsProject.instance().addMapLayer(vlayer)
QgsMapCanvas().setExtent(vlayer.extent())
QgsMapCanvas().setLayers([vlayer])
....
crs_dest = QgsCoordinateReferenceSystem(3857, QgsCoordinateReferenceSystem.PostgisCrsId)
QgsProject.instance().setCrs(crs_dest)

The destination CS is not set in QgsMapCanvas after that.
But QgsProject.instance().crs() shows correct CRS number at this moment (just after setCrs() ).

If this code is run in thread, setCrs() works in some situations.
Setting the CRS manually (by button, etc.) after loading also works.

I think <QGis> changes some QgsMapSettings after plugin loading and resets CRS settings.

In 2.18 version similar code (based on mapRenderer) worked here.

What should I do to run setCrs() at the start of plugin automatically?

History

#1 Updated by Igor Evdokimov over 5 years ago

I found that finally (after plugin loading) QGis sets Project CRS to the source CRS of loaded layers.

Maybe it's because constructor
QgsLayerTreeMapCanvasBridge::QgsLayerTreeMapCanvasBridge(...)
makes mAutoSetupOnFirstLayer(true) by default,
and then in QgsLayerTreeMapCanvasBridge::setCanvasLayers()
the call of QgsProject::instance()->setCrs( mFirstCRS ) sets layer's CRS to all Project?

#2 Updated by Igor Evdokimov over 5 years ago

Found solution/workaround:
https://gis.stackexchange.com/questions/273252/qgis-changing-canvas-crs-defaults-to-imported-layer

My working code:

from PyQt5.QtWidgets import QApplication
...
for data_dict in __DATA:
....
vlayer = QgsVectorLayer(uri.uri(), _v_layer0, _v_layer1)
QgsProject.instance().addMapLayer(vlayer)
QgsMapCanvas().setExtent(vlayer.extent())
QgsMapCanvas().setLayers([vlayer])
....
QApplication.instance().processEvents() #this operation solves this problem
crs_dest = QgsCoordinateReferenceSystem(3857, QgsCoordinateReferenceSystem.PostgisCrsId)
QgsProject.instance().setCrs(crs_dest)

Is it a bug nevertheless?

#3 Updated by Nyall Dawson over 5 years ago

QApplication.instance().processEvents()

^ is VERY dangerous to call, especially in places like this. It'll likely result in crashes.

What's the use case here? Why are you forcing a particular crs on startup?

#4 Updated by Igor Evdokimov over 5 years ago

Layers data are in 4236 crs, we need to set 3857 destination crs on startup.

#5 Updated by Matthew Baker over 5 years ago

All our source PostGIS data is stored in SRID:4326.

We make all our maps in State Plane SRID:2877

This feature is handy so that every time we start a map in QGIS, we don't have to set the 'on the fly' reprojection, and takes the guesswork out for new users who don't know about coordinate systems and get them going with a good looking map right away.

Nyall Dawson wrote:

QApplication.instance().processEvents()

^ is VERY dangerous to call, especially in places like this. It'll likely result in crashes.

What's the use case here? Why are you forcing a particular crs on startup?

Also available in: Atom PDF