Enginio QML Examples - Image Gallery

The user interface is a list of images with their meta-information and a button to upload more images.

Backend Configuration

The Enginio backend needs to be set up to get this example working.

Go to the Enginio Dashboard and create a new backend with the Image Gallery template.

The template will construct a new custom backend by executing the following steps:

  • Create a new object type objects.image (on the Object Types page).

    Add two properties to the image object: name:"name", type: "String" and name: "file", type: "Ref" with target "files".

  • Add a file processor by clicking the file property. Choose Image processor, and in Variants enter:
    
      {
          "thumbnail": { "crop":"100x100" }
      }
    
    

    This JSON snippet triggers the server to generate thumbnails for all uploaded images. In the image gallery the thumbnails will be used in the list view. The full image will be shown when the thumbnail is clicked.

Copy the backend id from the Enginio dashboard. They need to be entered into the example when it is executed for the first time.

The Example Code

The first step is to set up the Enginio client.


  EnginioClient {
      id: client
      backendId: backendHelper.backendId
      onError: console.log("Enginio error: " + reply.errorCode + ": " + reply.errorString)
  }

Then the model is initialized with that client.


  EnginioModel {
      id: enginioModel
      client: client
      query: { // query for all objects of type "objects.image" and include not null references to files
          "objectType": "objects.image",
          "include": {"file": {}},
          "query" : { "file": { "$ne": null } }
      }
  }

A delegate is needed to present the images nicely. The model is used to get the list of image objects, but the images are only attached to the objects as file references. Thus the image's thumbnail is fetched by each delegate.

Note: In a real application it might be necessary to cache the images.

The Component.onCompleted function is used to fetch the image. When the delegate is created, it has the JSON image object data. The information needed is the file.id reference. The file property was introduced in the backend setup section. Every object (files are just objects) contains an ID that uniquely identifies the image file. The thumbnail url of the image is retrieved using the ID ("variant": "thumbnail").


  Image {
      id: image
      x: 10
      width: 100
      height: 100
      anchors.verticalCenter: parent.verticalCenter
      opacity: image.status == Image.Ready ? 1 : 0
      Behavior on opacity { NumberAnimation { duration: 100 } }
      Component.onCompleted: {
          if (id in imagesUrl) {
              image.source = imagesUrl[id]
          } else {
              var data = { "id": file.id,
                  "variant": "thumbnail"}
              var reply = client.downloadUrl(data)
              reply.finished.connect(function() {
                  imagesUrl[id] = reply.data.expiringUrl
                  if (image && reply.data.expiringUrl) // It may be deleted as it is delegate
                      image.source = reply.data.expiringUrl
              })
          }
      }
  }
  Rectangle {
      color: "transparent"
      anchors.fill: image
      border.color: "#aaa"
      Rectangle {
          id: progressBar
          property real value:  image.progress
          anchors.bottom: parent.bottom
          width: image.width * value
          height: 4
          color: "#49f"
          opacity: image.status != Image.Ready ? 1 : 0
          Behavior on opacity {NumberAnimation {duration: 100}}
      }
  }

The meta-information about each image is displayed in simple Text elements. For the filename, it is possible to directly reference the name property as defined in the JSON.


  Text { text: name }

Files: