【问题标题】:Get the path from a QML url从 QML url 获取路径
【发布时间】:2014-09-15 15:54:03
【问题描述】:

FileDialog 给出 QML url 变量。 theurl.toString() 给出类似file:///c:\foo\bar.txt 的东西。我如何获得c:\foo\bar.txt

我想以跨平台的方式进行,理想情况下不依赖于正则表达式风格的黑客。 QUrl 提供了 path() 方法,但我似乎无法从 QML 访问它。

【问题讨论】:

  • 如果你希望你的应用是跨平台的,这个 URL 正是你所需要的。根据RFC 3986 URL 以协议开头。在您的情况下,它是file://。所有Qt 组件都理解它,更糟糕的是,有时您在传递c:/bar.txt 之类的内容时会出错。如果您仍想以 wrong 的方式获取此 URL,您只想替换协议部分 - theurl.toString().replace("file:///","")
  • 是的,我说过我不想使用正则表达式样式的黑客。我想知道是否有一种方法可以直接给我路径数据(它存储在 QUrl 对象中)。这不是传递给 Qt 组件。
  • 向用户显示文件名。
  • 我深入研究了 Qt 源代码。 QML“url”类型似乎由 C++ QUrl 类支持,它有一个非常好的 toLocalFile() 方法,但遗憾的是,这不是 Q_INVOKABLE 方法。
  • 我认为用 3 个斜线删除 file:/// 对于 Windows 是必要的,但在 Unix 上会中断。

标签: qt url qml filedialog


【解决方案1】:

按照上面 Chris Dolan 的回答,使用 C++ 中的插槽来处理这个问题可能是最巧妙的:

public slots:

void handleFileChosen(const QString &urlString) {
    const QUrl url(urlString);
    if (url.isLocalFile()) {
        setFile(QDir::toNativeSeparators(url.toLocalFile()));
    } else {
        setFile(urlString);
    }
}

【讨论】:

    【解决方案2】:

    在 MS Windows 中,“file:///c:\foo\bar.txt”应转换为“c:\foo\bar.txt”。然而,在 Linux 中,url“file:///Users/data/abcdef”的正确路径为“/Users/data/abcdef”。我创建了一个简单的函数来将 url 转换为路径:

    function urlToPath(urlString) {
        var s
        if (urlString.startsWith("file:///")) {
            var k = urlString.charAt(9) === ':' ? 8 : 7
            s = urlString.substring(k)
        } else {
            s = urlString
        }
        return decodeURIComponent(s);
    }
    

    【讨论】:

      【解决方案3】:

      正如 cmets 已经指出的那样,似乎没有办法(还没有?)在没有正则表达式的情况下获取路径本身。所以这是唯一的方法:

      基本解决方案

      FileDialog {
          onAccepted: {
              var path = myFileDialog.fileUrl.toString();
              // remove prefixed "file:///"
              path = path.replace(/^(file:\/{3})/,"");
              // unescape html codes like '%23' for '#'
              cleanPath = decodeURIComponent(path);
              console.log(cleanPath)
          }
      }
      

      这个正则表达式应该非常健壮,因为它只删除了字符串开头的file:///

      您还需要取消转义一些 HTML 字符(如果文件名包含例如哈希 #,这将返回为 %23。我们使用 JavaScript 函数 decodeURIComponent() 对其进行解码)。

      功能齐全的示例

      如果你不仅要过滤file:///,还要过滤qrc://http://,你可以使用这个RegEx:

      ^(file:\/{3})|(qrc:\/{2})|(http:\/{2})
      

      所以新的、完整的代码是:

      FileDialog {
          onAccepted: {
              var path = myFileDialog.fileUrl.toString();
              // remove prefixed "file:///"
              path= path.replace(/^(file:\/{3})|(qrc:\/{2})|(http:\/{2})/,"");
              // unescape html codes like '%23' for '#'
              cleanPath = decodeURIComponent(path);
              console.log(cleanPath)
          }
      }
      

      这是 RegEx 的一个很好的游乐场:http://regex101.com/r/zC1nD5/1

      【讨论】:

      • Ermm 不,我自己正在使用此代码,它有效。当然它只适用于file:/// URL(而不是file:// - 对于两个三个斜杠,使用/^(file:\/{2,3})/)。或者你是什么意思?参考见:regex101.com/r/aO1qG4/1
      • 我的意思是它不适用于其他方案,例如 qrc://http://。我并不是说它在很多情况下都行不通。只是指出它与QUrl::path()不同。
      • 我明白了。我假设,您只需要文件对话框中的文件。但你是对的,你也可以在那里输入一个http://-URL。我适当地编辑了我的答案。我希望我现在确实涵盖了所有案例。但是,是的,QUrl::path()-like 函数当然是理想的。
      • 为什么要删除 3 /// 而不仅仅是 2?
      • @pooya13 这已经是很久以前的事了,所以对此持保留态度:我认为原因是 file:/// 总是有 3 个斜杠,而其他“协议”如 http:// 有 2斜线。甚至不知道为什么。也许最后一个斜杠只是文件路径的一部分,即/home/mozzbozz(“根”-斜杠)。也许平台依赖?不确定(但对于 Qt 不太可能)。
      猜你喜欢
      • 1970-01-01
      • 2010-10-24
      • 2015-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-28
      • 2018-11-13
      • 2019-07-24
      相关资源
      最近更新 更多