5

I'm trying to create a simple ListView that I can use to browse the file system, using QFileSystem.

First, I tried to use code I've found that worked for QDirModel:

main.qml:

    ListView {
        id: list
        width: 300
        height: 500

        model: DelegateModel {
            model: myFileModel

            delegate: Text{
                id: txt
                text: fileName

                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        //Switch directory when clicked
                        list.model.rootIndex = list.model.modelIndex(index);
                    }

                }
            }
        }

main.cpp:

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

    QQmlApplicationEngine engine;


    QFileSystemModel qdm;
    qdm.setFilter( QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files );

    qdm.setRootPath("/");
    engine.rootContext()->setContextProperty("myFileModel", &qdm);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

However, this code resets the ListView every time the QFileSystemModel loads another piece of the filesystem. Video here - you can see how clicking on a new folder for the first time resets the view to the model's root. At the second attempt, you can also see that the correct folder's contents are shown for a fraction of a second before the view is reset.

My thinking was that, since QFileSystemModel loads its data asynchronously, maybe the model index is invalidated once the model is updated, thus resetting the views. So I tried to re-assign the rootIndex every time the model's directoryLoaded signal is emitted.

main.qml:

ListView {
        id: list
        width: 300
        height: 500

        model: DelegateModel {
            model: myFileModel

            property var ind: myModelIndex

            onIndChanged: {
                rootIndex = myModelIndex //manually reassign root
            }

            delegate: Text{
                id: txt
                text: fileName

                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        list.model.rootIndex = list.model.modelIndex(index);
                    }

                }
            }
        }

main.cpp:

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

    QQmlApplicationEngine engine;

    QFileSystemModel qdm;
    qdm.setFilter( QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files );

    QObject::connect(&qdm, &QFileSystemModel::directoryLoaded, [&](const QString& path){
        //Update model index after directory completely loaded
        engine.rootContext()->setContextProperty("myModelIndex", qdm.index(path));
    });

    qdm.setRootPath("/");
    engine.rootContext()->setContextProperty("myModelIndex", qdm.index(""));
    engine.rootContext()->setContextProperty("myFileModel", &qdm);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

However, the outcome is the exact same. I've added debugging code and it seems the model properly loads all new directory data, then the view's rootIndex is changed. Still, however, the view is reset every time.

To add to that, I've also set up a separate TreeView that also uses myFileModel and model as myRootIndex as root index. And that one works perfectly. It's just ListView (and GridView as well) that don't work.

There is virtually no info on using QFileSystemModel with anything other than TreeView, as far as I can see. I'd love some input on what is happening.

s3rius
  • 1,442
  • 1
  • 14
  • 26
  • `FolderListModel` is not a valid option? it is still in "labs" limbo but I'd say it works like a charm. See [here](http://stackoverflow.com/questions/31736997/how-to-use-folderlistmodel) for instance or look up in the documentation. It should also be used for Qt examples such us the shader effect example. – BaCaRoZzo Jul 04 '16 at 11:02
  • @BaCaRoZzo I've looked at `FolderListModel` but it doesn't play nice with `TreeView` since the model doesn't contain more than the files/folders in the target directory. That would be okay but I've also had some other issues with it, such as not being able to set "/" as the target folder. Instead of displaying root, it would display the Qt project directory. Also, it seems like the underlying C++ class isn't inheritable because it's not exposed in Qt Creator. It seems like it's meant purely for use within QML. – s3rius Jul 04 '16 at 14:00
  • 1
    You want to use `ListView`, don't you? QML is meant for `QAbstractListModel`-derived classes. You can surely setup it to work with `QAbstractItemModel`s (see for instance my answer on a similar topic [here](http://stackoverflow.com/a/27655785/2538363)). That said, the built-in example has a file browser written in QML, as I've said above. You can find it [here](http://doc.qt.io/qt-5/qtmultimedia-multimedia-video-qmlvideofx-qml-qmlvideofx-filebrowser-qml.html). Anyhow, also solving the issues here is of interest. Can't look to your code in detail. Hope someone can help. – BaCaRoZzo Jul 04 '16 at 14:18
  • 2
    I want to use `GridView` but used `ListView` for the sake of the example. I have the same problems with both. I want to create something of a browser as well so right now I'm looking into how to represent the filesystem, and unfortunately all of Qt's solutions have some problem or limitation that makes it difficult to use for me. `QFileSystemModel` would be great if I could get it to actually work. Anyways, you've still helped me even if you can't answer my question directly. I'm new to Qt5 and I'm soaking up lots of info to learn. I'll look at your links and maybe I can figure things out. – s3rius Jul 04 '16 at 15:03

0 Answers0