Add QFileSelector API

For easy cross-platform and cross-device UIs, automatic asset swapping
based on filename is being developed. This API provides the logic for
the swapping, so that applications can use it themselves with the same
logic as any automatic swapping done in application templates.

Selector set is initially minimal, aiming for just platform selection
and enabling a common selection mechanism for Qt platforms to use.

Change-Id: I219517d740fa7385e923a9e09cb7e241378f857a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Alan Alpert 2013-02-18 20:06:09 -08:00 committed by The Qt Project
parent 4b02585f30
commit b674b15dff
27 changed files with 773 additions and 2 deletions

View File

@ -47,7 +47,9 @@ HEADERS += \
io/qfilesystementry_p.h \
io/qfilesystemengine_p.h \
io/qfilesystemmetadata_p.h \
io/qfilesystemiterator_p.h
io/qfilesystemiterator_p.h \
io/qfileselector.h \
io/qfileselector_p.h
SOURCES += \
io/qabstractfileengine.cpp \
@ -83,7 +85,8 @@ SOURCES += \
io/qfilesystemwatcher.cpp \
io/qfilesystemwatcher_polling.cpp \
io/qfilesystementry.cpp \
io/qfilesystemengine.cpp
io/qfilesystemengine.cpp \
io/qfileselector.cpp
win32 {
SOURCES += io/qsettings_win.cpp

View File

@ -0,0 +1,383 @@
/***************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qfileselector.h"
#include "qfileselector_p.h"
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QMutex>
#include <QtCore/QMutexLocker>
#include <QtCore/QUrl>
#include <QtCore/QFileInfo>
#include <QtCore/QLocale>
#include <QtCore/QDebug>
QT_BEGIN_NAMESPACE
//Environment variable to allow tooling full control of file selectors
static const char env_override[] = "QT_NO_BUILTIN_SELECTORS";
static const ushort selectorIndicator = '+';
Q_GLOBAL_STATIC(QFileSelectorSharedData, sharedData);
static QBasicMutex sharedDataMutex;
QFileSelectorPrivate::QFileSelectorPrivate()
: QObjectPrivate()
{
}
/*!
\class QFileSelector
\inmodule QtCore
\brief QFileSelector provides a convenient way of selecting file variants
\since 5.2
QFileSelector is a convenience for selecting file variants based on platform or device
characteristics. This allows you to develop and deploy one codebase containing all the
different variants more easily in some circumstances, such as when the correct variant cannot
be determined during the deploy step.
Consider the following example usage, where you want to use different settings files on
different locales. You might select code between locales like this:
\code
QString defaultsBasePath = "data/";
QString defaultsPath = defaultsBasePath + "defaults.conf";
QString localizedPath = defaultsBasePath
+ QString("%1/defaults.conf").arg(QLocale::system().name());
if (QFile::exists(localizedPath))
defaultsPath = localizedPath;
QFile defaults(defaultsPath);
\endcode
Similarly, if you want to pick a different data file based on target platform,
your code might look something like this:
\code
QString defaultsPath = "data/defaults.conf";
#if defined(Q_OS_LINUX_ANDROID)
defaultsPath = "data/android/defaults.conf";
#elif defined(Q_OS_BLACKBERRY)
defaultsPath = "data/blackberry/defaults.conf";
#elif defined(Q_OS_IOS)
defaultsPath = "data/ios/defaults.conf";
#endif
QFile defaults(defaultsPath);
\endcode
QFileSelector provides a convenient alternative to writing such boilerplate code, and in the
latter case it allows you to start using an platform-specific configuration without a recompile.
QFileSelector also allows for chaining of multiple selectors in a convenient way, for example
selecting a different file only on certain combinations of platform and locale. For example, to
select based on platform and/or locale, the code is as follows:
\code
QFileSelector selector;
QFile defaultsFile(selector.select("data/defaults.conf"));
\endcode
The files to be selected are placed in directories named with a '+' and a selector name. In the above
example you could have the platform configurations selected by placing them in the following locations:
\code
data/defaults.conf
data/+android/defaults.conf
data/+blackberry/defaults.conf
data/+ios/+en_GB/defaults.conf
\endcode
If you always use the same file you do not need to use QFileSelector.
To find selected files, QFileSelector looks in the same directory as the base file. If there are
any directories of the form +<selector> with an active selector, QFileSelector will prefer a file
with the same file name from that directory over the base file. These directories can be nested to
check against multiple selectors, for example:
\code
images/background.png
images/+android/+en_GB/background.png
images/+blackberry/+en_GB/background.png
\endcode
With those files available, you would select a different file on android and blackberry platforms,
but only if the locale was en_GB.
Selectors normally available are
\list
\li platform, one of: android, blackberry, ios, windows, mac, linux, generic_unix or unknown.
\li locale, same as QLocale::system().name().
\endlist
Further selectors will be added from the QT_FILE_SELECTORS environment variable, which when
set should be a set of colon (semi-colon on windows) separated selectors. Note that this
variable will only be read once, selectors may not update if the variable changes while the
application is running.
The initial set of selectors are evaluated only once, on first use. In a future
version, some may be marked as deploy-time static and be moved during the deployment step as an
optimization. As selectors come with a performance cost, it is recommended to avoid their use
in circumstances involving performance-critical code.
Additionally you can add extra selectors at runtime to customize behavior further. These will
be used in any future calls to select(). If the extra selectors list has been changed, calls to
select() will use the new list and may return differently.
When multiple selectors could be applied to the same file, the first matching selector is chosen.
The order selectors are checked in are:
1. Selectors set via setExtraSelectors(), in the order they are in the list
2. Selectors in the QT_FILE_SELECTORS environment variable, from left to right
3. Locale
4. Platform
Here is an example involving multiple selectors matching at the same time. It uses platform
selectors, plus an extra selector named "admin" is set by the application based on user
credentials. The example is sorted so that the lowest matching file would be chosen if all
selectors were present:
\code
images/background.png
images/+linux/background.png
images/+windows/background.png
images/+admin/background.png
images/+admin/+linux/background.png
\endcode
Because extra selectors are checked before platform the +admin/background.png will be chosen
on windows when the admin selector is set, and +windows/background.png will be chosen on
windows when the admin selector is not set. On linux, the +admin/+linux/background.png will be
chosen when admin is set, and the +linux/background.png when it is not.
QFileSelector will not attempt to select if the base file does not exist. For error handling in
the case no valid selectors are present, it is recommended to have a default or error-handling
file in the base file location even if you expect selectors to be present for all deployments.
*/
/*!
Create a QFileSelector instance. This instance will have the same static selectors as other
QFileSelector instances, but its own set of extra selectors.
If supplied, it will have the given QObject \a parent.
*/
QFileSelector::QFileSelector(QObject *parent)
: QObject(*(new QFileSelectorPrivate()), parent)
{
}
/*!
Destroys this selector instance.
*/
QFileSelector::~QFileSelector()
{
}
/*!
This function returns the selected version of the path, based on the conditions at runtime.
If no selectable files are present, returns the original \a filePath.
If the original file does not exist, the original \a filePath is returned. This means that you
must have a base file to fall back on, you cannot have only files in selectable sub-directories.
See the class overview for the selection algorithm.
*/
QString QFileSelector::select(const QString &filePath) const
{
Q_D(const QFileSelector);
return d->select(filePath);
}
static QString qrcScheme()
{
return QStringLiteral("qrc");
}
/*!
This is a convenience version of select operating on QUrls. If the scheme is not file or qrc,
\a filePath is returned immediately. Otherwise selection is applied to the path of \a filePath
and a QUrl is returned with the selected path and other QUrl parts the same as \a filePath.
See the class overview for the selection algorithm.
*/
QUrl QFileSelector::select(const QUrl &filePath) const
{
Q_D(const QFileSelector);
if (filePath.scheme() != qrcScheme() && !filePath.isLocalFile())
return filePath;
QUrl ret(filePath);
if (filePath.scheme() == qrcScheme()) {
QString equivalentPath = QLatin1Char(':') + filePath.path();
QString selectedPath = d->select(equivalentPath);
ret.setPath(selectedPath.remove(0, 1));
} else {
ret = QUrl::fromLocalFile(d->select(ret.toLocalFile()));
}
return ret;
}
static QString selectionHelper(const QString &path, const QString &fileName, const QStringList &selectors)
{
/* selectionHelper does a depth-first search of possible selected files. Because there is strict
selector ordering in the API, we can stop checking as soon as we find the file in a directory
which does not contain any other valid selector directories.
*/
Q_ASSERT(path.isEmpty() || path.endsWith(QLatin1Char('/')));
foreach (const QString &s, selectors) {
QString prospectiveBase = path + QLatin1Char(selectorIndicator) + s + QLatin1Char('/');
QStringList remainingSelectors = selectors;
remainingSelectors.removeAll(s);
if (!QDir(prospectiveBase).exists())
continue;
QString prospectiveFile = selectionHelper(prospectiveBase, fileName, remainingSelectors);
if (!prospectiveFile.isEmpty())
return prospectiveFile;
}
// If we reach here there were no successful files found at a lower level in this branch, so we
// should check this level as a potential result.
if (!QFile::exists(path + fileName))
return QString();
return path + fileName;
}
QString QFileSelectorPrivate::select(const QString &filePath) const
{
Q_Q(const QFileSelector);
QFileInfo fi(filePath);
// If file doesn't exist, don't select
if (!fi.exists())
return filePath;
QString ret = selectionHelper(fi.path().isEmpty() ? QString() : fi.path() + QLatin1Char('/'),
fi.fileName(), q->allSelectors());
if (!ret.isEmpty())
return ret;
return filePath;
}
/*!
Returns the list of extra selectors which have been added programmatically to this instance.
*/
QStringList QFileSelector::extraSelectors() const
{
Q_D(const QFileSelector);
return d->extras;
}
/*!
Sets the \a list of extra selectors which have been added programmatically to this instance.
These selectors have priority over any which have been automatically picked up.
*/
void QFileSelector::setExtraSelectors(const QStringList &list)
{
Q_D(QFileSelector);
d->extras = list;
}
/*!
Returns the complete, ordered list of selectors used by this instance
*/
QStringList QFileSelector::allSelectors() const
{
Q_D(const QFileSelector);
QMutexLocker locker(&sharedDataMutex);
QFileSelectorPrivate::updateSelectors();
return d->extras + sharedData->staticSelectors;
}
void QFileSelectorPrivate::updateSelectors()
{
if (!sharedData->staticSelectors.isEmpty())
return; //Already loaded
#if defined(Q_OS_WIN)
QLatin1Char pathSep(';');
#else
QLatin1Char pathSep(':');
#endif
QStringList envSelectors = QString::fromLatin1(qgetenv("QT_FILE_SELECTORS"))
.split(pathSep, QString::SkipEmptyParts);
if (envSelectors.count())
sharedData->staticSelectors << envSelectors;
if (!qgetenv(env_override).isEmpty())
return;
sharedData->staticSelectors << sharedData->preloadedStatics; //Potential for static selectors from other modules
// TODO: Update on locale changed?
sharedData->staticSelectors << QLocale::system().name();
sharedData->staticSelectors << platformSelectors();
}
QStringList QFileSelectorPrivate::platformSelectors()
{
QStringList ret;
#if defined(Q_OS_LINUX_ANDROID)
ret << QStringLiteral("android");
#elif defined(Q_OS_BLACKBERRY)
ret << QStringLiteral("blackberry");
#elif defined(Q_OS_IOS)
ret << QStringLiteral("ios");
#elif defined(Q_OS_WINCE)
ret << QStringLiteral("wince");
#elif defined(Q_OS_WIN)
ret << QStringLiteral("windows");
#elif defined(Q_OS_LINUX)
ret << QStringLiteral("linux");
#elif defined(Q_OS_MAC)
ret << QStringLiteral("mac");
#elif defined(Q_OS_UNIX)
ret << QStringLiteral("generic_unix");
#endif
return ret;
}
void QFileSelectorPrivate::addStatics(const QStringList &statics)
{
QMutexLocker locker(&sharedDataMutex);
sharedData->preloadedStatics << statics;
}
QT_END_NAMESPACE
#include "moc_qfileselector.cpp"

View File

@ -0,0 +1,72 @@
/***************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFILESELECTOR_H
#define QFILESELECTOR_H
#include <QtCore/QObject>
#include <QtCore/QStringList>
QT_BEGIN_NAMESPACE
class QFileSelectorPrivate;
class Q_CORE_EXPORT QFileSelector : public QObject
{
Q_OBJECT
public:
QFileSelector(QObject *parent = 0);
~QFileSelector();
QString select(const QString &filePath) const;
QUrl select(const QUrl &filePath) const;
QStringList extraSelectors() const;
void setExtraSelectors(const QStringList &list);
QStringList allSelectors() const;
private:
Q_DECLARE_PRIVATE(QFileSelector)
};
QT_END_NAMESPACE
#endif

View File

@ -0,0 +1,84 @@
/***************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFILESELECTOR_P_H
#define QFILESELECTOR_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/QString>
#include <QtCore/QFileSelector>
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
struct QFileSelectorSharedData //Not QSharedData because currently is just a global store
{
QStringList staticSelectors;
QStringList preloadedStatics;
};
class Q_CORE_EXPORT QFileSelectorPrivate : QObjectPrivate //Exported for use in other modules (like QtGui)
{
Q_DECLARE_PUBLIC(QFileSelector)
public:
static void updateSelectors();
static QStringList platformSelectors();
static void addStatics(const QStringList &); //For loading GUI statics from other Qt modules
QFileSelectorPrivate();
QString select(const QString &filePath) const;
QStringList extras;
};
QT_END_NAMESPACE
#endif

View File

@ -10,6 +10,7 @@ SUBDIRS=\
qfile \
largefile \
qfileinfo \
qfileselector \
qfilesystementry \
qfilesystemwatcher \
qiodevice \

View File

@ -0,0 +1,6 @@
CONFIG += parallel_test
CONFIG += testcase
TARGET = tst_qfileselectors
QT = core-private testlib
SOURCES = tst_qfileselector.cpp
RESOURCES = qfileselector.qrc

View File

@ -0,0 +1,23 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>extras/test</file>
<file>extras/test2</file>
<file>extras/+custom1/test</file>
<file>extras/+custom1/test3</file>
<file>extras/+custom2/test</file>
<file>extras/+custom3/test</file>
<file>extras/+custom3/+custom2/test</file>
<file>extras/+custom3/+custom4/test</file>
<file>extras/+custom3/+custom5/test</file>
<file>extras/+custom5/+custom3/test</file>
<file>platforms/test</file>
<file>platforms/+android/test</file>
<file>platforms/+blackberry/test</file>
<file>platforms/+ios/test</file>
<file>platforms/+mac/test</file>
<file>platforms/+wince/test</file>
<file>platforms/+windows/test</file>
<file>platforms/+linux/test</file>
<file>platforms/+generic_unix/test</file>
</qresource>
</RCC>

View File

@ -0,0 +1,199 @@
/****************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <qplatformdefs.h>
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QString>
#include <private/qfileselector_p.h>
#include <private/qabstractfileengine_p.h>
#include <private/qfsfileengine_p.h>
#include <private/qfilesystemengine_p.h>
const ushort selectorIndicator = '+';
class tst_QFileSelector : public QObject
{
Q_OBJECT
public:
tst_QFileSelector() {}
private slots:
void basicTest_data();
void basicTest();
void urlConvenience_data();
void urlConvenience();
};
void tst_QFileSelector::basicTest_data()
{
/* Files existing for this test
* platform/test
* platform/+<platform>/test for all <platform> in QFileSelectorPrivate::platformSelectors()
* extras/test
* extras/test2 to test for when selector directories exist, but don't have the files
* extras/+custom1/test
* extras/+custom1/test3 to test for when base file doesn't exist
* extras/+custom2/test
* extras/+custom3/test
* extras/+custom3/+custom2/test
* extras/+custom3/+custom4/test
* extras/+custom3/+custom5/test
* extras/+custom5/+custom3/test
*/
QTest::addColumn<QString>("testPath");
QTest::addColumn<QStringList>("customSelectors");
QTest::addColumn<QString>("expectedPath");
QString test("/test");// '/' is here so dir string can also be selector string
QTest::newRow("platform") << QString(":/platforms/test") << QStringList()
<< QString(":/platforms/") + QLatin1Char(selectorIndicator)
+ QFileSelectorPrivate::platformSelectors().first() + test;
QString resourceTestPath(":/extras/test");
QString custom1("custom1");
QTest::newRow("custom1-noselector") << resourceTestPath << QStringList()
<< QString(":/extras") + test;
QTest::newRow("custom1-withselector") << resourceTestPath << (QStringList() << custom1)
<< QString(":/extras/") + QLatin1Char(selectorIndicator) + custom1 + test;
QTest::newRow("customX-withselector-nofile") << QString(":/extras/test2") << (QStringList() << custom1)
<< QString(":/extras/test2");
QTest::newRow("custom1-withselector-nobasefile") << QString(":/extras/test3") << (QStringList() << custom1)
<< QString(":/extras/test3");
QString custom2("custom2");
QString custom3("custom3");
QString custom4("custom4");
QString custom5("custom5");
QString slash("/");
QTest::newRow("custom12") << resourceTestPath << (QStringList() << custom1 << custom2)
<< QString(":/extras/") + QLatin1Char(selectorIndicator) + custom1 + test;
QTest::newRow("custom21") << resourceTestPath << (QStringList() << custom2 << custom1)
<< QString(":/extras/") + QLatin1Char(selectorIndicator) + custom2 + test;
QTest::newRow("custom213") << resourceTestPath << (QStringList() << custom2 << custom1 << custom3)
<< QString(":/extras/") + QLatin1Char(selectorIndicator) + custom2 + test;
QTest::newRow("custom23") << resourceTestPath << (QStringList() << custom2 << custom3)
<< QString(":/extras/") + QLatin1Char(selectorIndicator) + custom2 + test;
QTest::newRow("custom34nested") << resourceTestPath << (QStringList() << custom3 << custom4)
<< QString(":/extras/") + QLatin1Char(selectorIndicator) + custom3 + slash
+ QLatin1Char(selectorIndicator) + custom4 + test;
QTest::newRow("custom43nested") << resourceTestPath << (QStringList() << custom4 << custom3)
<< QString(":/extras/") + QLatin1Char(selectorIndicator) + custom3 + slash
+ QLatin1Char(selectorIndicator) + custom4 + test;
QTest::newRow("custom35conflict") << resourceTestPath << (QStringList() << custom3 << custom5)
<< QString(":/extras/") + QLatin1Char(selectorIndicator) + custom3 + slash
+ QLatin1Char(selectorIndicator) + custom5 + test;
QTest::newRow("relativePaths") << QFINDTESTDATA("extras/test") << (QStringList() << custom1)
<< QFINDTESTDATA(QString("extras/") + QLatin1Char(selectorIndicator) + custom1
+ QString("/test"));
}
void tst_QFileSelector::basicTest()
{
QFETCH(QString, testPath);
QFETCH(QStringList, customSelectors);
QFETCH(QString, expectedPath);
QFileSelector fs;
fs.setExtraSelectors(customSelectors);
QCOMPARE(fs.select(testPath), expectedPath);
}
void tst_QFileSelector::urlConvenience_data()
{
/* Files existing for this test
* extras/test
* extras/+custom1/test
*/
QTest::addColumn<QUrl>("testUrl");
QTest::addColumn<QStringList>("customSelectors");
QTest::addColumn<QUrl>("expectedUrl");
QString test("/test");// '/' is here so dir string can also be selector string
QString custom1("custom1");
QTest::newRow("qrc") << QUrl("qrc:///extras/test") << (QStringList() << custom1)
<< QUrl(QString("qrc:///extras/") + QLatin1Char(selectorIndicator) + custom1 + test);
QString fileBasePath = QFINDTESTDATA("extras/test");
QString fileSelectedPath = QFINDTESTDATA(QString("extras/") + QLatin1Char(selectorIndicator)
+ custom1 + QString("/test"));
QTest::newRow("file") << QUrl::fromLocalFile(fileBasePath) << (QStringList() << custom1)
<< QUrl::fromLocalFile(fileSelectedPath);
// http://qt-project.org/images/qtdn/sprites-combined-latest.png is chosen as a representative real world URL
// But note that this test is checking that http urls are NOT selected so it shouldn't be checked
QUrl testHttpUrl("http://qt-project.org/images/sprites-combined-latest.png");
QTest::newRow("http") << testHttpUrl << (QStringList() << QString("qtdn")) << testHttpUrl;
}
void tst_QFileSelector::urlConvenience()
{
QFETCH(QUrl, testUrl);
QFETCH(QStringList, customSelectors);
QFETCH(QUrl, expectedUrl);
QFileSelector fs;
//All rows of this test use only custom selectors, so should not select before the setExtra call
QCOMPARE(fs.select(testUrl), testUrl);
fs.setExtraSelectors(customSelectors);
QCOMPARE(fs.select(testUrl), expectedUrl);
}
QTEST_MAIN(tst_QFileSelector)
#include "tst_qfileselector.moc"