Better QGIS forms, part two🔗

Posted by Médéric Ribreux 🗓 In blog/ Qgis/

Introduction

This article is the next of my serie of articles about QGIS forms. You can read the previous one here. Today we will focus on photo form controls. In QGis, they are dedicated to image viewing. Change your Edit Widget to Photo. You can then edit the size of the photo display (seems to be required if you want to effectively display the photo on the form).

Image of Photo widget configuration
Image of Photo widget configuration

Nice widget, isn't it ? Be we can go further…

Custom UI

With this configuration, QGis is able to render photos on your Widget by its own means. You do not need to code anything. But you perhaps want to go further and display url links for documents that are not photos or images but other things (think about a photo inside a PDF file or a video) ? Or perhaps, you would like to use a Photo widget into a custom UI ? Let's see how it can be achieved.

The first thing to do is to build a custom form with qtcreator (designer-qt4 in Debian Jessie). You'll have to create a QWidget. It will be named with the field you have used to store the path to the photo in the data layer. This QWidget will hold a QGridLayout. Inside this layout, put a QLabel and name it PhotoLabel (required name). It will be used to display the photo. Then, add a QLineEdit named lineEdit (required name). It will be used to display the path of the photo. You also need to add a QPushButton named FileChooserButton in the layout.

If you want to display a URL, add a QLabel and name it with the name of your choice. You'll have to be careful to add two properties for this QLabel:

Image of Qt4 Designer for custom Photo form
Image of Qt4 Designer for custom Photo form

With this form, QGIS will be able to display the photo in the fields and the widget will work as if it was auto-generated by QGIS.

Code

Time to dive into Python… We want to display a URL to open an external document. This document will be our image (that is presently displayed on screen) or any another type of document (PDF/video/sound/etc.).

def manageIll(dialog, layerid, featureid):
    """
    Handle link for files in Illustration
    """
    # Find file value:
    child = dialog.findChild(QLineEdit, u"lineEdit")
    if child:
        child.textChanged.connect(partial(modifyPhoto, dialog))
        modifyPhoto(dialog)

def modifyPhoto(dialog):
    """
    Function to build link for files in Illustration form
    """
    # Find the fie path value
    lineEdit = dialog.findChild(QLineEdit, u"lineEdit")
    if lineEdit:
        fileValue = lineEdit.text()
        nullValue = QSettings().value("qgis/nullValue" , u"NULL")
        if fileValue == nullValue or fileValue is None:
            return False

    basename = os.path.basename(fileValue)
    filename = u"<a href=\"file:///{0}\">{1}</a>".format(fileValue,basename)

    # Affect the value to the URL QLabel
    urlLabel = dialog.findChild(QLabel, u"ILLURL_L")
    if urlLabel and fileValue is not None:
        urlLabel.setText(filename)

    # Determine if we can produce a QPixmap from the file
    if not QPixmap().load(fileValue):
        photoLabel = dialog.findChild(QLabel, u"PhotoLabel")
        if photoLabel:
            photoLabel.setText(u"This file is not a photo !")

The manageIll function will connect the signal textChanged of the QLineEdit named "lineEdit" (remember the UI part) to a dedicated function named modifyPhoto.

modifyPhoto will take the value of "lineEdit" and will transform it into an "URL" that will be shown into a QLabel named ILLURL_L (see UI part). At the end, we try to find if the filepath from "lineEdit" is a valid image and if it is not the case, we display a text inside the dedicated photo QLabel (named PhotoLabel).

You'll need to change the objectName property to reflect the widgets names found in your form (and in your layer of course).

Conclusion

This article illustrate an easy way to add a QGis photo form control inside a custom form. You can also add code to change the default behaviour of your photo control with Python. Without doubt, I am sure that one day, the QGIS developpers will implement a better external documents behaviour in QGIS…