Как установить папку FileDialog из пути UNC в QML?

Я хочу сохранить последнюю использованную папку в диалоговом окне файла в qml (используя Qt версии 5.6). Я делаю это с помощью QSettings, у которого есть свойство url lastUsedFolder как таковое:

/////////////
/// 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;
}

Это достаточно хорошо работает при работе с локальными файлами, но не работает при использовании файлов на удаленных компьютерах, адреса которых указываются в пути в формате UNC, например \\myRemotePC.somewhere.com\myData\.

Если я перейду к этому адресу и приму диалог, папка будет сохранена благодаря методу onAccepted, и консоль напечатает saving folder: file://myRemotePC.somewhere.com/myData. Затем, когда я снова открываю диалоговое окно, срабатывает onVisibleChanged. Метод doesFolderStillExists видит папку - QUrl.toLocalFile, кажется, работает, - а также сохраненный путь в settings.lastUsedFolder остается тем же самым, что был сохранен. Но затем приложение вылетает в строке, которая присваивается свойству folder со следующей ошибкой (Windows 7; последний вывод консоли - это просто «папка настроек диалогового окна»):

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

Другими словами, он вылетает, когда я пытаюсь установить свойство папки диалогового окна, используя то же самое значение, которое я читал из него раньше ... и это меня смущает.

Не уверен, имеет ли это значение, но я заметил одну странную вещь: в сообщении об ошибке есть три косых черты после file:, в то время как путь, который я устанавливаю в качестве папки, имеет только два. Я пытался изменить путь разными способами:

  • если file: полностью опущен, диалоговое окно открывается в местоположении по умолчанию, вероятно, не удается проанализировать адрес значимым образом - что отчасти ожидаемо
  • независимо от того, сколько косых черт я добавляю или удаляю после file:, появляется одно и то же сообщение об ошибке, всегда с тремя косыми чертами в указанном пути

Я был бы признателен за любой совет, который позволил бы мне сохранить и повторно использовать последнюю использованную папку в FileDialog таким образом, чтобы это можно было использовать как для «локальных», так и для UNC-путей, даже если это было сделано иначе, чем мы в настоящее время используем.


person tomj    schedule 10.10.2017    source источник


Ответы (1)


Вроде ошибка Qt. QFileDialog пытается «исправить» ваш URI плохим способом, потому что если вы конвертируете UNC-путь, такой как «\ myRemotePC.somewhere.com \ myData \» в URI, он даст вам »file: //myRemotePC.somewhere.com/ myData ", эта часть верна, но с точки зрения QFileDialog вы пытаетесь получить локальную папку.

Я пытаюсь передать QFileDialog необработанной строкой или URL-адресом, но QFileDialog продолжает преобразовывать путь.

Если вам нужен один обходной путь, вызовите QFileDialog из C ++, он работает со строковым путем, таким как путь UNC.

Другой обходной путь - подключите внешнюю папку как сетевой диск.

Извините за мой плохой английский ^^

Если кто-то хочет быстро попробовать.

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;
}
}
person Bastien Thonnat    schedule 11.10.2017
comment
Выполнение диалога со стороны C ++, вероятно, является вариантом, хотя и довольно уродливым, я надеюсь, что есть способ лучше, но спасибо. Подключение удаленного места в качестве диска работает, но не решает проблему сбоя - люди будут продолжать писать в нашу поддержку, что программное обеспечение дает сбой, когда они используют сетевые диски (а в моей области люди часто используют сетевые диски). Я мог бы проверить, является ли путь UNC, и не запомнить его, если это так, но это требует некоторого удобства от пользователей. - person tomj; 11.10.2017
comment
Но в остальном я согласен с вашими выводами - похоже, что FileDialog выполняет какое-то преобразование / исправление пути во время onFolderChanged, но не принимает во внимание пути UNC :( - person tomj; 11.10.2017
comment
Вызов QFileDialog из C ++ не обязательно является уродливым вариантом, QML очень хорош для графических целей, но в случае обработки больших данных или определенного поведения лучше кодировать на C ++, Qt говорит, что в первой строке этой документации doc.qt.io/qt-5/qtqml-cppintegration-topic.html - person Bastien Thonnat; 11.10.2017