Displaying thumbnails in a GridView

The next step is to display these thumbnails. Create a new QML file named AlbumPage.qml:

import QtQuick 2.6 
import QtQuick.Layouts 1.3 
import QtQuick.Controls 2.0 
import "." 
 
PageTheme { 
 
    property string albumName 
    property int albumRowIndex 
 
    toolbarTitle: albumName 
 
    GridView { 
        id: thumbnailList 
        model: pictureModel 
        anchors.fill: parent 
        anchors.leftMargin: 10 
        anchors.rightMargin: 10 
        cellWidth : thumbnailSize 
        cellHeight: thumbnailSize 
 
        delegate: Rectangle { 
            width: thumbnailList.cellWidth - 10 
            height: thumbnailList.cellHeight - 10 
            color: "transparent" 
 
            Image { 
                id: thumbnail 
                anchors.fill: parent 
                fillMode: Image.PreserveAspectFit 
                cache: false 
                source: "image://pictures/" + index + "/thumbnail" 
            } 
        } 
    } 
} 

This new PageTheme element defines two properties: albumName and albumRowIndex. The albumName property is used to update the title in toolbarTitlealbumRowIndex will be used to interact with AlbumModel in order to rename or delete the album from the current page.

To display thumbnails, we rely on a GridView element which will layout the thumbnails in a grid of cells. This thumbnailList item uses the pictureModel to request its data. The delegate is simply a Rectangle element with a single Image inside. This Rectangle element is slightly smaller than the thumbnailList.cellWidth or thumbnailList.cellHeight. The GridView element does not provide a spacing property (like ListView) for some room between each item. Thus, we simulate it by using a smaller area to display the content.

The Image item will try to take all the available space with anchors.fill: parent but will still keep the aspect ratio of the provided picture with fillMode: Image.PreserveAspectFit. You recognize the source attribute where the current delegate index is provided to retrieve the thumbnail. Finally, the cache: false attribute ensures that the PictureImageProvider class will not try to use the native cache.

To display AlbumPage.qml, we have to update the stackView (located in main.qml). Remember that stackView has been declared as a property (pageStack), it is thus accessible from any QML file.

The AlbumPage element will be displayed when the user clicks on the MouseArea element for a given Album value in AlbumListPage.qml.

We will now give the ability to the user to add a new picture. To do this, we will rely on a QtQuick Dialog: FileDialog. Here is the updated version of AlbumPage.qml:

import QtQuick 2.6 
import QtQuick.Layouts 1.3 
import QtQuick.Controls 2.0 
import QtQuick.Dialogs 1.2 
import "." 
 
PageTheme { 
 
    property string albumName 
    property int albumRowIndex 
 
    toolbarTitle: albumName 
    toolbarButtons: RowLayout { 
        ToolButton { 
            background: Image { 
                source: "qrc:/res/icons/photo-add.svg" 
            } 
            onClicked: { 
                dialog.open() 
            } 
        } 
    } 
 
    FileDialog { 
        id: dialog 
        title: "Open file" 
        folder: shortcuts.pictures 
        onAccepted: { 
            var pictureUrl = dialog.fileUrl 
            pictureModel.addPictureFromUrl(pictureUrl) 
            dialog.close() 
        } 
    } 
 
    GridView { 
        ... 
} 

The FileDialog element is straightforward to implement. By using the folder: shortcuts.pictures property, QtQuick will automatically position the FileDialog element in the platform-specific pictures directory. Even better, on iOS it will open the native photo application where you can pick your own picture.

When the user validates his picture choice, the path is available in the onAccepted()function with the dialog.fileUrl field, which we stored in the pictureUrl variable. This pictureUrl variable is then passed to a new wrapper function of PictureModel: addPictureFromUrl(). The pattern used is exactly the same as we did for AlbumModel::addAlbumFromName(): a Q_INVOKABLE wrapper function around PictureModel::addPicture().

The only missing parts of AlbumPage are the delete album and rename album features. They follow patterns we already covered. The deletion will be done using a wrapper function in AlbumModel, and the rename reuses the InputDialog we created for AlbumListPage.qml. Please refer to the source code of the chapter to see the implementation for these features. This is how the thumbnails will look on an Android device: