[QGIS-Developer] QgsLayout.itemById returns wrong object

Nyall Dawson nyall.dawson at gmail.com
Tue Jan 23 23:09:14 PST 2018


On 23 January 2018 at 22:34, Enrico Ferreguti <enricofer at gmail.com> wrote:
> I'm trying to programmatically set a QgsLayoutPicture content in QGIS3.0:
>
> 1) I create a new print composition and I name it 'test'
> 2) I create a picture frame in the composition and I call it 'picture'
> 3) I run the following code:
>
> from qgis.core import QgsProject
> myLayout = QgsProject.instance().layoutManager().layoutByName('test')
> myLayoutPicture = myLayout.itemById("picture")
> myLayoutPicture.setPicturePath("path to an image")
>
> and I get the following Exception:
> AttributeError: 'QgsLayoutItem' object has no attribute 'setPicturePath'
>
> If I inspect myLayoutPicture object I found it is a qgis._core.QgsLayoutItem
> not a QgsLayoutPicture
>
> Is this a correct behaviour or is it an issue? How can I get the right
> Layout object?

This became an issue after a certain sip version. It affects QGIS 2.x
also, and seems to be caused by sip being unable to automatically cast
classes which use multiple inheritance (like QgsComposerItem,
QgsLayoutItem). The consequence is that Python is only aware of the
base class, not the actual item subclass.

I can't find anyway to fix this properly. So I hack around by forcing
sip to manually cast to the correct item type, e.g. by inserting two
lines* which look like this:

        # screw you sip, I'll just manually cast
        real_item = sip.cast(item, QgsLayoutItemPicture)

It's not pretty, but it works...

Nyall

* the first line is critical for the fix to work correctly


More information about the QGIS-Developer mailing list