Add QUrl::fromUserInput overload with a cwd argument.

Useful for any application that can take URLs on the command-line, so that
full paths and relative paths can also be accepted.

Change-Id: I8a2c50f36d60bdc49c065b3065972fd5d45fa12a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
David Faure 2014-04-23 22:59:34 +02:00 committed by The Qt Project
parent da24bfe1f7
commit 31ce6f50c6
3 changed files with 117 additions and 0 deletions

View File

@ -363,6 +363,29 @@
\sa QUrl::FormattingOptions
*/
/*!
\enum QUrl::UserInputResolutionOption
\since 5.4
The user input resolution options define how fromUserInput() should
interpret strings that could either be a relative path or the short
form of a HTTP URL. For instance \c{file.pl} can be either a local file
or the URL \c{http://file.pl}.
\value DefaultResolution The default resolution mechanism is to check
whether a local file exists, in the working
directory given to fromUserInput, and only
return a local path in that case. Otherwise a URL
is assumed.
\value AssumeLocalFile This option makes fromUserInput() always return
a local path unless the input contains a scheme, such as
\c{http://file.pl}. This is useful for applications
such as text editors, which are able to create
the file if it doesn't exist.
\sa fromUserInput()
*/
/*!
\fn QUrl::QUrl(QUrl &&other)
@ -4091,6 +4114,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*!
Returns a valid URL from a user supplied \a userInput string if one can be
deducted. In the case that is not possible, an invalid QUrl() is returned.
This overload takes a \a workingDirectory path, in order to be able to
handle relative paths. This is especially useful when handling command
line arguments.
If \a workingDirectory is empty, no handling of relative paths will be done,
so this method will behave like its one argument overload.
By default, an input string that looks like a relative path will only be treated
as such if the file actually exists in the given working directory.
If the application can handle files that don't exist yet, it should pass the
flag AssumeLocalFile in \a options.
\since 5.4
*/
QUrl QUrl::fromUserInput(const QString &userInput, const QString &workingDirectory,
UserInputResolutionOptions options)
{
QString trimmedString = userInput.trimmed();
if (trimmedString.isEmpty())
return QUrl();
// Check both QUrl::isRelative (to detect full URLs) and QDir::isAbsolutePath (since on Windows drive letters can be interpreted as schemes)
QUrl url = QUrl(trimmedString, QUrl::TolerantMode);
if (url.isRelative() && !QDir::isAbsolutePath(trimmedString)) {
QFileInfo fileInfo(QDir(workingDirectory), trimmedString);
if ((options & AssumeLocalFile) || fileInfo.exists())
return QUrl::fromLocalFile(fileInfo.absoluteFilePath());
}
return fromUserInput(trimmedString);
}
/*!
Returns a valid URL from a user supplied \a userInput string if one can be
deducted. In the case that is not possible, an invalid QUrl() is returned.

View File

@ -199,7 +199,16 @@ public:
QByteArray toEncoded(FormattingOptions options = FullyEncoded) const;
static QUrl fromEncoded(const QByteArray &url, ParsingMode mode = TolerantMode);
enum UserInputResolutionOption {
DefaultResolution,
AssumeLocalFile
};
Q_DECLARE_FLAGS(UserInputResolutionOptions, UserInputResolutionOption)
static QUrl fromUserInput(const QString &userInput);
// ### Qt6 merge with fromUserInput(QString), by adding = QString()
static QUrl fromUserInput(const QString &userInput, const QString &workingDirectory,
UserInputResolutionOptions options = DefaultResolution);
bool isValid() const;
QString errorString() const;

View File

@ -165,6 +165,8 @@ private slots:
void binaryData();
void fromUserInput_data();
void fromUserInput();
void fromUserInputWithCwd_data();
void fromUserInputWithCwd();
void fileName_data();
void fileName();
void isEmptyForEncodedUrl();
@ -2913,6 +2915,52 @@ void tst_QUrl::fromUserInput()
QCOMPARE(url, guessUrlFromString);
}
void tst_QUrl::fromUserInputWithCwd_data()
{
QTest::addColumn<QString>("string");
QTest::addColumn<QString>("directory");
QTest::addColumn<QUrl>("guessedUrlDefault");
QTest::addColumn<QUrl>("guessedUrlAssumeLocalFile");
// Null
QTest::newRow("null") << QString() << QString() << QUrl() << QUrl();
// Existing file
QDirIterator it(QDir::currentPath(), QDir::NoDotDot | QDir::AllEntries);
int c = 0;
while (it.hasNext()) {
it.next();
QUrl url = QUrl::fromLocalFile(it.filePath());
QTest::newRow(QString("file-%1").arg(c++).toLatin1()) << it.fileName() << QDir::currentPath() << url << url;
}
QDir parent = QDir::current();
QVERIFY(parent.cdUp());
QUrl parentUrl = QUrl::fromLocalFile(parent.path());
QTest::newRow("dotdot") << ".." << QDir::currentPath() << parentUrl << parentUrl;
QTest::newRow("nonexisting") << "nonexisting" << QDir::currentPath() << QUrl("http://nonexisting") << QUrl::fromLocalFile(QDir::currentPath() + "/nonexisting");
QTest::newRow("short-url") << "example.org" << QDir::currentPath() << QUrl("http://example.org") << QUrl::fromLocalFile(QDir::currentPath() + "/example.org");
QTest::newRow("full-url") << "http://example.org" << QDir::currentPath() << QUrl("http://example.org") << QUrl("http://example.org");
QTest::newRow("absolute") << "/doesnotexist.txt" << QDir::currentPath() << QUrl("file:///doesnotexist.txt") << QUrl("file:///doesnotexist.txt");
#ifdef Q_OS_WIN
QTest::newRow("windows-absolute") << "c:/doesnotexist.txt" << QDir::currentPath() << QUrl("file:///c:/doesnotexist.txt") << QUrl("file:///c:/doesnotexist.txt");
#endif
}
void tst_QUrl::fromUserInputWithCwd()
{
QFETCH(QString, string);
QFETCH(QString, directory);
QFETCH(QUrl, guessedUrlDefault);
QFETCH(QUrl, guessedUrlAssumeLocalFile);
QUrl url = QUrl::fromUserInput(string, directory);
QCOMPARE(url, guessedUrlDefault);
url = QUrl::fromUserInput(string, directory, QUrl::AssumeLocalFile);
QCOMPARE(url, guessedUrlAssumeLocalFile);
}
void tst_QUrl::fileName_data()
{
QTest::addColumn<QString>("urlStr");