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 toolbarTitle; albumRowIndex 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: