Simple QML File Browser

qt-logoJust 4 fun. It takes a ListView, a FolderListModel and QQuickImageProvider to build a simple list file browser. First things First. The custom Icon Provider will answer QML requests for file icons.

[code lang=”cpp”]
// ***** IconProvider.h ******
#ifndef IMAGEPROVIDER_H
#define IMAGEPROVIDER_H
#include <QQuickImageProvider>
#include <QFileIconProvider>
#include <QMimeDatabase>
class IconProvider : public QQuickImageProvider
{
public:
IconProvider();
QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);
protected:
QFileIconProvider m_provider;
QMimeDatabase m_mimeDB;
signals:
public slots:
};
#endif // IMAGEPROVIDER_H
// ***** IconProvider.cpp ****
#include "IconProvider.h"
IconProvider::IconProvider():QQuickImageProvider(QQuickImageProvider::Pixmap)
{ }
QPixmap IconProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
{
int width = requestedSize.width() > 0 ? requestedSize.width() : 64;
int height = width;
if (size) *size = QSize(width, height);
if (QFileInfo(id).isDir()) return m_provider.icon(QFileIconProvider::Folder).pixmap(width,height);
else {
QMimeType mime = m_mimeDB.mimeTypeForFile(id);
if (QIcon::hasThemeIcon(mime.iconName())) return QIcon::fromTheme(mime.iconName()).pixmap(width,height);
return m_provider.icon(QFileIconProvider::File).pixmap(width,height);
}
}
[/code]

In the Main we must inform the QML Engine of this IconProvider

[code lang=”cpp”]
// ***** main.cpp *****
#include <QApplication>
#include <QQmlApplicationEngine>
#include "IconProvider.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
engine.addImageProvider(QLatin1String("iconProvider"), new IconProvider());
return app.exec();
}
[/code]

The main window is built in QML with just a FileBrowser object

[code lang=”css”]
// ***** main.qml *****
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import Qt.labs.folderlistmodel 2.1

ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Browse")
FileBrowser {
anchors.fill: parent
path: "file:///home/" // let’s start with the Home folder
}
}
[/code]

The FileBrowser use ListView with a FolderListModel to read data from filesystem and a simple delegate showing icon and filename. Header shows current path and a back button

[code lang=”css”]
// ***** FileBrowser.qml *****
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import Qt.labs.folderlistmodel 2.1
Item {
id: browser
property alias path: view.path
width: 300
height: 200
ListView {
id: view
property var colors: ["white","#E0FFE0","white","#EEEEFF" ]
property string path

anchors.fill: parent
model: FolderListModel {
id: folder
folder: view.path
}
delegate: FileDelegate { }
headerPositioning: ListView.OverlayHeader
header: Rectangle {
width: browser.width
height: 34
color: "yellow"
z:2
Row {
anchors.fill: parent
Button {
width:32
height :32
text: "<<<"
onClicked: view.path = folder.parentFolder
}
Text {
text: view.path
anchors.verticalCenter: parent.verticalCenter
}
}
}
footerPositioning: ListView.OverlayHeader
footer: Rectangle {
width: browser.width
height: 34
color: "yellow"
z:2
Row {
anchors.fill: parent
Text {
text: "["+folder.count+" Files]"
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
[/code]

Delegate is quite simple; it shows information about the file; A click on the row traverse the filesystem tree or launch the associated application.

[code lang=”css”]
// ***** FileDelegate.qml *****
import QtQuick 2.0
Rectangle {
id:delegate
width: view.width
height:34
color: view.colors[index & 3]
Row { anchors.fill: parent
Image {
id: icon
width: delegate.height – 2
height:width
source: "image://iconProvider/"+filePath
}
Text {
text: fileName
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id:mouseArea
anchors.fill: parent
onClicked: fileIsDir ? view.path = fileURL : Qt.openUrlExternally(fileURL)
}
}

[/code]