SR_
SR_

Reputation: 917

How to select multiple files and directories with QML FileDialog

I'm begining with Qt 5.5.
I want to use QML as much as possible for UI matters.
I need a file and directory picker that can select multiple objects, either files or directories.
QFileDialog is able to do so, and according to this solution, the QFileDialog needs to be set to non native.
According to QML FileDialog documentation, there's no way for the programmer to force the QML FileDialog object to be non native.

Must I use C++ to handle this or is there a way to access the properties of the QML FileDialog in order to force the instanciation of an underlying QFileDialog, and then a way to access to this instance properties from QML in order to implement the solution in QML ?

Upvotes: 1

Views: 2987

Answers (1)

Tarod
Tarod

Reputation: 7170

Edit #1: see comments below. @SR_ is right. I think it's necessary to implement some code in C++ to get the expected behaviour.

Edit #2: my previous answer was wrong. Setting selectMultiple property as true is not a solution. So I've updated the answer to show a new proposal. See the comments below for more info about the discussion about this issue.

The next code is based on the Qt example File System Browser and the code is uploaded to GitHub.

main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include <QFileSystemModel>
#include "filemanagement.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    FileManagement fileManagement;
    QQmlApplicationEngine engine;
    QFileSystemModel *fsm = new QFileSystemModel(&engine);
    fsm->setRootPath(QDir::homePath());
    fsm->setResolveSymlinks(true);
    engine.rootContext()->setContextProperty("fileManagement", &fileManagement);
    engine.rootContext()->setContextProperty("fileSystemModel", fsm);
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    return app.exec();
}

main.qml

import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQml.Models 2.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("File System")

    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
    }

    Row {
        id: row
        anchors.top: parent.top
        anchors.topMargin: 12
        anchors.horizontalCenter: parent.horizontalCenter

        ExclusiveGroup {
            id: eg
        }

        Repeater {
            model: [ "None", "Single", "Extended", "Multi", "Contig."]
            Button {
                text: modelData
                exclusiveGroup: eg
                checkable: true
                checked: index === 1
                onClicked: view.selectionMode = index
            }
        }
    }

    ItemSelectionModel {
        id: sel
        model: fileSystemModel
        onSelectionChanged: {
            console.log("selected", selected)
            console.log("deselected", deselected)
            fileManagement.printFileNames(model, selectedIndexes)
        }
        onCurrentChanged: console.log("current", current)
    }

    TreeView {
        id: view
        anchors.fill: parent
        anchors.margins: 2 * 12 + row.height
        model: fileSystemModel
        selection: sel

        onCurrentIndexChanged: console.log("current index", currentIndex)

        TableViewColumn {
            title: "Name"
            role: "fileName"
            resizable: true
        }

        TableViewColumn {
            title: "Permissions"
            role: "filePermissions"
            resizable: true
        }

        onClicked: {
            console.log("clicked", index)            
            fileManagement.printPath(index.model, index)
        }
        onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index)
    }

    Component.onCompleted: fileManagement.test()
}

filemanagement.h

#ifndef FILEMANAGEMENT_H
#define FILEMANAGEMENT_H

#include <QObject>
#include <QDebug>
#include <QFileSystemModel>

class FileManagement : public QObject
{
    Q_OBJECT
public:
    explicit FileManagement(QObject *parent = 0);

    Q_INVOKABLE bool printPath(QFileSystemModel* fileSystemModel,
                               const QModelIndex &modelIndex);

    Q_INVOKABLE bool printFileNames(QFileSystemModel* fileSystemModel,
                                    QList<QModelIndex> modelIndexList);

signals:

public slots:

    void test() {
        qDebug() << "Called the C++ slot";
    }
};

#endif // FILEMANAGEMENT_H

filemanagement.cpp

#include "filemanagement.h"

FileManagement::FileManagement(QObject *parent) : QObject(parent)
{

}

bool FileManagement::printPath(QFileSystemModel* fileSystemModel,
                       const QModelIndex &modelIndex) {
    qDebug() << "+ File path: " << fileSystemModel->filePath(modelIndex);
    return true;
}

bool FileManagement::printFileNames(QFileSystemModel* fileSystemModel,
                            QList<QModelIndex> modelIndexList) {
    qDebug() << "+ " << modelIndexList.size() << " items selected: ";
    QList<QModelIndex>::iterator i;
    for (i = modelIndexList.begin(); i != modelIndexList.end(); ++i) {
        qDebug() << "++ File name: " << fileSystemModel->fileName(*i);
    }

    return true;
}

Upvotes: 1

Related Questions