1

I want to store the last used folder in a file dialog in qml (using Qt version 5.6). The way I do it is through QSettings that has a url property lastUsedFolder as such:

/////////////
/// myApp.qml
/////////////

import QtQuick 2.3
import QtQuick.Dialogs 1.1
import Qt.labs.settings 1.0

Settings {
    id: settings
    property url lastUsedFolder;
}

FileDialog {
    id: openDialog
    onVisibleChanged:
    {
        if(visible && myApp.doesFolderStillExist(settings.lastUsedFolder))
        {
            console.log("setting folder of dialog")
            folder = settings.lastUsedFolder
            console.log(folder)
        }
    }
    onAccepted:
    {
        console.log("saving folder: " + folder)
        settings.lastUsedFolder = folder;
    }
}

/////////////
/// myApp.cpp
/////////////
bool myApp::doesFolderStillExist(QUrl folderUrl)
{
    QFileInfo folder(folderUrl.toLocalFile());
    if (folder.exists())
        return true;
    return false;
}

This works well enough when working with local files, but does not when using files on remote computers addressed by a UNC-format path such as \\myRemotePC.somewhere.com\myData\.

If I navigate to this address and accept the dialog, the folder is stored thanks to the onAccepted method and the console prints saving folder: file://myRemotePC.somewhere.com/myData. Then when I open the dialog again, the onVisibleChanged triggers. The doesFolderStillExists method sees the folder - the QUrl.toLocalFile seems to work - and also the stored path in settings.lastUsedFolder is still the same that was stored. But then the app crashes on the line that assigns to the folder property with the following error (Windows 7; the last console print is just the "setting folder of dialog"):

QWindowsNativeFileDialogBase::shellItem: SHCreateItemFromParsingName(file:///myRemotePC.somewhere.com/myData) failed ()

In other words, it crashes when I try to set the folder property of the dialog using the exact same value I read from it before...and that confuses me.

Not sure if it matters, but one strange thing I noticed is that the error message has three forward slashes after the file:, while the path that I am setting as the folder has only two. I tried to modify the path in various ways:

  • if the file: is omitted entirely, the dialog opens in the default location, probably failing to parse the address in a meaningful way - which is kind of expected
  • no matter how many forward slashes I add or remove after the file:, the same error message appears, always with three slashes in the shown path

I would appreciate any advice that would lead me to being able to store and re-use the last used folder in a FileDialog in a way that is usable for both "local" and UNC paths, even if it was done in a different way than we are currently using.

tomj
  • 1,089
  • 7
  • 17

1 Answers1

3

It seem to be an error from Qt. QFileDialog try to "correct" your URI in a bad way, cause if you convert an UNC path like "\myRemotePC.somewhere.com\myData\" into an URI it will give you "file://myRemotePC.somewhere.com/myData", this part is correct, but from QFileDialog point of view, you try to get a local folder.

I try to feed the QFileDialog with raw string or url but QFileDialog persist to convert the path.

If you need one workaround, call QFileDialog from C++, it work with string path like UNC path.

Another workaround, connect your external folder as network drive.

Sorry for my poor English ^^

If someone want a fast try.

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import Qt.labs.settings 1.0

Window {
Component.onCompleted: {
    openDialog.open();
}

FileDialog {
    id: openDialog
    selectFolder: true
    Component.onCompleted:  folder = settings.lastFolderURL;
    onVisibleChanged:
    {
        console.log("lastFolder as string " + settings.lastFolderString);
        console.log("lastFolder as URL " + settings.lastFolderURL);
    }
    onAccepted:
    {
        console.log("Selected folder : " + folder)
        settings.lastFolderString = folder;
        settings.lastFolderURL = folder;
    }
}

Settings {
    id: settings
    property string lastFolderString ;
    property url lastFolderURL;
}
}
Bastien Thonnat
  • 563
  • 4
  • 9
  • Executing the dialog from the C++ side is probably an option, though a pretty ugly one, I hope there is a better way, but thanks.Connecting the remote location as a drive works, but does not solve the crashing problem - people will keep writing to our support that the software crashes when they use network drives (and in my field, people use network drives a lot). I could check if the path is an UNC and don't "remeber" it if it is, but that's taking a bit of convenience from the users. – tomj Oct 11 '17 at 11:35
  • But otherwise I agree with your findings - it looks like the FileDialog is doing some kind of conversion/correction of the path during onFolderChanged, but does not take into account UNC paths :( – tomj Oct 11 '17 at 11:37
  • Calling QFileDialog from C++ is not necessarily an ugly option, QML is very strong for graphic purpose, but in case of large data processing or specific behavior, it's better to code in C++, Qt say that in the first line of this documentation http://doc.qt.io/qt-5/qtqml-cppintegration-topic.html – Bastien Thonnat Oct 11 '17 at 11:57