【问题标题】:How to set FileDialog's folder from a UNC path in QML?如何从 QML 中的 UNC 路径设置 FileDialog 的文件夹?
【发布时间】:2018-03-22 05:02:39
【问题描述】:

我想将上次使用的文件夹存储在 qml 的文件对话框中(使用 Qt 5.6 版)。我这样做的方式是通过具有 url 属性 lastUsedFolder 的 QSettings :

/////////////
/// 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: 之后添加或删除多少个正斜杠,都会出现相同的错误消息,显示路径中始终包含三个斜杠

如果有任何建议可以使我能够以适用于“本地”和 UNC 路径的方式存储和重新使用 FileDialog 中最后使用的文件夹,我将不胜感激,即使它是在与我们目前使用的方式不同。

【问题讨论】:

    标签: qt qml unc qt5.6


    【解决方案1】:

    这似乎是来自 Qt 的错误。 QFileDialog 尝试以一种不好的方式“更正”您的 URI,因为如果您将“\myRemotePC.somewhere.com\myData\”之类的 UNC 路径转换为 ​​URI,它将为您提供“file://myRemotePC.somewhere.com/ myData”,这部分是正确的,但是从 QFileDialog 的角度来看,您尝试获取本地文件夹。

    我尝试向 QFileDialog 提供原始字符串或 url,但 QFileDialog 坚持转换路径。

    如果您需要一种解决方法,请从 C++ 调用 QFileDialog,它适用于字符串路径,如 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;
    }
    }
    

    【讨论】:

    • 从 C++ 端执行对话框可能是一种选择,虽然很丑,但我希望有更好的方法,但是谢谢。将远程位置连接为驱动器有效,但不能解决崩溃问题——人们会继续写信给我们的支持,说软件在使用网络驱动器时会崩溃(在我的领域,人们经常使用网络驱动器)。我可以检查路径是否为 UNC,如果是则不要“记住”它,但这会给用户带来一些便利。
    • 但除此之外我同意你的发现 - 看起来 FileDialog 在 onFolderChanged 期间正在对路径进行某种转换/更正,但没有考虑 UNC 路径:(
    • 从 C++ 调用 QFileDialog 不一定是丑陋的选择,QML 对于图形用途非常强大,但是在大数据处理或特定行为的情况下,最好用 C++ 编写代码,Qt 说在本文档的第一行 doc.qt.io/qt-5/qtqml-cppintegration-topic.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    相关资源
    最近更新 更多