Get the path from a QML url
Solution 1
As noted in the comments already, there seems to be no way (yet?) to get the path itself without a regex. So this is the only way to go:
Basic solution
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)
}
}
This regex should be quite robust as it only removes the file:///
from the beginning of the string.
You will also need to unescape some HTML characters (if the file name contains e.g. the hash #
, this would be returned as %23
. We decode this by using the JavaScript function decodeURIComponent()
).
Fully featured example
If you not only want to filter the file:///
but also qrc://
and http://
, you can use this RegEx:
^(file:\/{3})|(qrc:\/{2})|(http:\/{2})
So the new, complete code would be:
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)
}
}
This is a good playground for RegEx'es: http://regex101.com/r/zC1nD5/1
Solution 2
Following Chris Dolan's answer above, it's probably neatest to deal with this using a slot in C++:
public slots:
void handleFileChosen(const QString &urlString) {
const QUrl url(urlString);
if (url.isLocalFile()) {
setFile(QDir::toNativeSeparators(url.toLocalFile()));
} else {
setFile(urlString);
}
}
Solution 3
In MS Windows "file:///c:\foo\bar.txt" should be converted to "c:\foo\bar.txt". However in Linux the url "file:///Users/data/abcdef" has the correct path as "/Users/data/abcdef". I have created a simple function to convert url to path:
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);
}
Related videos on Youtube
Timmmm
Updated on July 09, 2022Comments
-
Timmmm almost 2 years
FileDialog
gives a QMLurl
variable.theurl.toString()
gives something likefile:///c:\foo\bar.txt
. How do I getc:\foo\bar.txt
?I want to do it in a cross-platform way, and ideally without relying on regex-style hacks.
QUrl
provides apath()
method, but I don't seem to be able to access it from QML.-
folibis almost 10 yearsIf you want you app will be cross-platform this URL is exactly what you need. According to
RFC 3986
URL starts with protocol. In your case it isfile://
.All Qt components understand it, even worse sometimes you will get an error while passing something likec:/bar.txt
. If you still want to get this URL inwrong
way you just want to replace the protocol part -theurl.toString().replace("file:///","")
-
Timmmm almost 10 yearsYeah I said I don't want to use regex style hacks. I was wondering if there was a method that actually gives me the path data directly (it is stored in the QUrl object). And this isn't to pass to a Qt component.
-
folibis almost 10 yearsBtw, for what do you need it?
-
Timmmm almost 10 yearsShowing the filename to the user.
-
Chris Dolan almost 10 yearsI dug into the Qt source. The QML "url" type seems to be backed by the C++ QUrl class, which has a very nice toLocalFile() method, but that's not a Q_INVOKABLE method, sadly.
-
Roman Plášil almost 7 yearsI think removing
file:///
with 3 slashes is necessary for Windows but will break on Unix. -
bam over 3 yearsQUrl class has
::toString(QUrl::FormattingOptions options)
method. Relevant options here isQUrl::RemoveScheme
andQUrl::PreferLocalFile
: org.qt-project.qtlocation.5151/qtcore/… Not sure if it exposed to QML.
-
-
mozzbozz over 9 yearsErmm no, I'm using this code myself and it works. Of course it works for
file:///
URLs only (and notfile://
- for two or three slashes, use/^(file:\/{2,3})/
). Or what do you mean? For reference, see: regex101.com/r/aO1qG4/1 -
Timmmm over 9 yearsI mean it won't work for other schemes, like
qrc://
orhttp://
. I'm not saying it won't work in many cases; just point out that it isn't the same asQUrl::path()
. -
mozzbozz over 9 yearsI got it. I assumed, you only wanted files from the file dialog. But you are right, you could also input an
http://
-URL there. I edited my answer appropriately. I hope I did cover all cases now. But yes, of course aQUrl::path()
-like function would be ideal. -
pooya13 about 3 yearsWhy are you removing 3
///
and not just 2? -
mozzbozz about 3 years@pooya13 it's been a long time ago, so take this with a grain of salt: I think the reason was that
file:///
always has 3 slashes while other "protocols" likehttp://
have 2 slashes. Not even sure why. Maybe the last slash is just part of the filepath, i.e./home/mozzbozz
(the "root"-slash). Maybe platform dependent? Not sure (but unlikely for Qt). -
pooya13 about 3 years@mozzbozz Thanks for your response. Then I think you need to remove only 2 and leave the third as that seems to be the root slash.