Получить путь из URL-адреса QML

FileDialog дает переменную QML url. theurl.toString() дает что-то вроде file:///c:\foo\bar.txt. Как мне получить c:\foo\bar.txt?

Я хочу сделать это кроссплатформенным способом и, в идеале, не полагаться на хаки в стиле регулярных выражений. QUrl предоставляет path() метод, но, похоже, я не могу получить к нему доступ из QML.


person Timmmm    schedule 24.07.2014    source источник
comment
Если вы хотите, чтобы ваше приложение было кроссплатформенным, этот URL - именно то, что вам нужно. Согласно RFC 3986 URL начинается с протокола. В вашем случае это file://. Все компоненты Qt понимают это, даже хуже, иногда вы получите ошибку при передаче чего-то вроде c:/bar.txt. Если вы все еще хотите получить этот URL wrong способом, вы просто хотите заменить часть протокола - theurl.toString().replace("file:///","")   -  person folibis    schedule 24.07.2014
comment
Да, я сказал, что не хочу использовать хаки в стиле регулярных выражений. Мне было интересно, существует ли метод, который действительно дает мне данные пути напрямую (они хранятся в объекте QUrl). И это не для того, чтобы переходить к компоненту Qt.   -  person Timmmm    schedule 24.07.2014
comment
Кстати, для чего он тебе нужен?   -  person folibis    schedule 24.07.2014
comment
Показывает имя файла пользователю.   -  person Timmmm    schedule 24.07.2014
comment
Я покопался в исходниках Qt. Тип url QML, похоже, поддерживается классом C ++ QUrl, который имеет очень хороший метод toLocalFile (), но, к сожалению, это не метод Q_INVOKABLE.   -  person Chris Dolan    schedule 06.08.2014
comment
Я думаю, что удаление file:/// с тремя косыми чертами необходимо для Windows, но не работает в Unix.   -  person Roman Plášil    schedule 20.08.2017
comment
Класс QUrl имеет ::toString(QUrl::FormattingOptions options) метод. Соответствующие параметры здесь: QUrl::RemoveScheme и QUrl::PreferLocalFile: org.qt-project. qtlocation.5151 / qtcore / Не уверен, доступен ли он QML.   -  person bam    schedule 31.12.2020


Ответы (3)


Как уже отмечалось в комментариях, похоже, нет способа (пока?) Получить сам путь без регулярного выражения. Так что это единственный выход:

Базовое решение

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

person mozzbozz    schedule 11.11.2014
comment
Я имею в виду, что это не будет работать для других схем, таких как qrc:// или http://. Я не говорю, что во многих случаях это не сработает; просто укажите, что это не то же самое, что QUrl::path(). - person Timmmm; 12.11.2014
comment
Я понял. Я предположил, что вам нужны только файлы из файлового диалога. Но вы правы, вы также можете ввести http://-URL. Я соответствующим образом отредактировал свой ответ. Надеюсь, теперь я рассмотрел все случаи. Но да, конечно, функция, подобная QUrl::path(), была бы идеальной. - person mozzbozz; 12.11.2014
comment
Почему вы удаляете 3 ///, а не только 2? - person pooya13; 12.05.2021
comment
@ pooya13 это было давно, так что отнеситесь к этому с недоверием: я думаю, причина в том, что file:/// всегда имеет 3 слэша, в то время как другие протоколы, такие как http://, имеют 2 слэша. Даже не знаю почему. Возможно, последняя косая черта - это просто часть пути к файлу, то есть /home/mozzbozz (корневая косая черта). Может быть, зависит от платформы? Не уверен (но вряд ли для Qt). - person mozzbozz; 19.05.2021
comment
@mozzbozz Спасибо за ваш ответ. Тогда я думаю, вам нужно удалить только 2 и оставить третью, поскольку это, кажется, корневая косая черта. - person pooya13; 24.05.2021

Следуя приведенному выше ответу Криса Долана, вероятно, лучше всего справиться с этим, используя слот в C ++:

public slots:

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

В MS Windows "файл: /// 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);
}
person Tony    schedule 29.03.2018