Merge remote-tracking branch 'origin/5.12' into dev

Change-Id: I9c2a18f5110adf3d8f630718238866aef47bb782
This commit is contained in:
Qt Forward Merge Bot 2018-08-26 01:00:16 +02:00
commit 2cdbe29ef0
29 changed files with 269 additions and 91 deletions

View File

@ -5,7 +5,7 @@
QMAKE_PLATFORM += macos osx macx
QMAKE_MAC_SDK = macosx
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.11
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
QMAKE_APPLE_DEVICE_ARCHS = x86_64
device.sdk = macosx

View File

@ -16,7 +16,9 @@ MAKEFILE_GENERATOR = MSVC.NET
QMAKE_PLATFORM = win32
QMAKE_COMPILER = msvc
CONFIG += flat debug_and_release debug_and_release_target precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE _UNICODE WIN32
# MSVC 2017 15.8+ fixed std::aligned_storage but compilation fails without
# _ENABLE_EXTENDED_ALIGNED_STORAGE flag since the fix breaks binary compatibility.
DEFINES += UNICODE _UNICODE WIN32 _ENABLE_EXTENDED_ALIGNED_STORAGE
QMAKE_COMPILER_DEFINES += _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64

View File

@ -110,12 +110,6 @@ greaterThan(QMAKE_MSC_VER, 1909) {
QMAKE_CXXFLAGS_CXX14 = -std:c++14
QMAKE_CXXFLAGS_CXX1Z = -std:c++17
}
# MSVC 2017 15.8+ fixed std::aligned_storage but compilation fails without
# this flag since the fix breaks binary compatibility.
greaterThan(QMAKE_MSC_VER, 1914) {
DEFINES += _ENABLE_EXTENDED_ALIGNED_STORAGE
}
}
greaterThan(QMAKE_MSC_VER, 1910) {

View File

@ -2,7 +2,7 @@
# qmake configuration for macx-ios-clang
#
QMAKE_IOS_DEPLOYMENT_TARGET = 10.0
QMAKE_IOS_DEPLOYMENT_TARGET = 11.0
# Universal target (iPhone and iPad)
QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 1,2

View File

@ -2,7 +2,7 @@
# qmake configuration for macx-tvos-clang
#
QMAKE_TVOS_DEPLOYMENT_TARGET = 10.0
QMAKE_TVOS_DEPLOYMENT_TARGET = 11.0
QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 3

View File

@ -2,7 +2,7 @@
# qmake configuration for macx-watchos-clang
#
QMAKE_WATCHOS_DEPLOYMENT_TARGET = 3.0
QMAKE_WATCHOS_DEPLOYMENT_TARGET = 4.0
QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 4

View File

@ -12,7 +12,6 @@ include(../common/msvc-desktop.conf)
# modifications to msvc-desktop.conf
QMAKE_COMPILER += intel_icl
DEFINES += _ENABLE_EXTENDED_ALIGNED_STORAGE
QMAKE_CFLAGS_OPTIMIZE_FULL = -O3

View File

@ -45,11 +45,17 @@ QT_BEGIN_NAMESPACE
//
///////////////////////////////////////////////////////////////////////
ProFileCache::ProFileCache()
{
QMakeVfs::ref();
}
ProFileCache::~ProFileCache()
{
for (const Entry &ent : qAsConst(parsed_files))
if (ent.pro)
ent.pro->deref();
QMakeVfs::deref();
}
void ProFileCache::discardFile(const QString &fileName, QMakeVfs *vfs)

View File

@ -201,7 +201,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeParser::ParseFlags)
class QMAKE_EXPORT ProFileCache
{
public:
ProFileCache() {}
ProFileCache();
~ProFileCache();
void discardFile(int id);

View File

@ -52,11 +52,38 @@ QMakeVfs::QMakeVfs()
#ifndef QT_NO_TEXTCODEC
m_textCodec = 0;
#endif
ref();
}
QMakeVfs::~QMakeVfs()
{
deref();
}
void QMakeVfs::ref()
{
#ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&s_mutex);
#endif
++s_refCount;
}
void QMakeVfs::deref()
{
#ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&s_mutex);
#endif
if (!--s_refCount) {
s_fileIdCounter = 0;
s_fileIdMap.clear();
s_idFileMap.clear();
}
}
#ifdef PROPARSER_THREAD_SAFE
QMutex QMakeVfs::s_mutex;
#endif
int QMakeVfs::s_refCount;
QAtomicInt QMakeVfs::s_fileIdCounter;
QHash<QString, int> QMakeVfs::s_fileIdMap;
QHash<int, QString> QMakeVfs::s_idFileMap;
@ -114,16 +141,6 @@ QString QMakeVfs::fileNameForId(int id)
return s_idFileMap.value(id);
}
void QMakeVfs::clearIds()
{
#ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&s_mutex);
#endif
s_fileIdCounter = 0;
s_fileIdMap.clear();
s_idFileMap.clear();
}
bool QMakeVfs::writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags,
const QString &contents, QString *errStr)
{

View File

@ -76,10 +76,13 @@ public:
Q_DECLARE_FLAGS(VfsFlags, VfsFlag)
QMakeVfs();
~QMakeVfs();
static void ref();
static void deref();
int idForFileName(const QString &fn, VfsFlags flags);
QString fileNameForId(int id);
static void clearIds();
bool writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr);
ReadResult readFile(int id, QString *contents, QString *errStr);
bool exists(const QString &fn, QMakeVfs::VfsFlags flags);
@ -97,6 +100,7 @@ private:
#ifdef PROEVALUATOR_THREAD_SAFE
static QMutex s_mutex;
#endif
static int s_refCount;
static QAtomicInt s_fileIdCounter;
// Qt Creator's ProFile cache is a singleton to maximize its cross-project
// effectiveness (shared prf files from QtVersions).

View File

@ -58,6 +58,8 @@
#include "private/qabstractanimation_p.h"
#include <type_traits>
#ifndef QT_NO_ANIMATION
QT_BEGIN_NAMESPACE
@ -104,7 +106,17 @@ public:
};
//this should make the interpolation faster
template<typename T> inline T _q_interpolate(const T &f, const T &t, qreal progress)
template<typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
_q_interpolate(const T &f, const T &t, qreal progress)
{
return T(f + t * progress - f * progress);
}
// the below will apply also to all non-arithmetic types
template<typename T>
typename std::enable_if<!std::is_unsigned<T>::value, T>::type
_q_interpolate(const T &f, const T &t, qreal progress)
{
return T(f + (t - f) * progress);
}

View File

@ -65,6 +65,7 @@ QCFString::operator CFStringRef() const
#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
QT_MAC_WEAK_IMPORT(_os_log_default);
bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogContext &context,
const QString &message, const QString &optionalSubsystem)
{

View File

@ -40,8 +40,13 @@
#include <private/qcore_mac_p.h>
#ifdef Q_OS_OSX
#include <AppKit/NSText.h>
#ifdef Q_OS_MACOS
# include <AppKit/AppKit.h>
# if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
@interface NSApplication (MojaveForwardDeclarations)
@property (strong) NSAppearance *effectiveAppearance NS_AVAILABLE_MAC(10_14);
@end
# endif
#endif
#if defined(QT_PLATFORM_UIKIT)
@ -166,6 +171,16 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool)
}
#endif // !QT_NO_DEBUG_STREAM
#ifdef Q_OS_MACOS
bool qt_mac_applicationIsInDarkMode()
{
if (__builtin_available(macOS 10.14, *))
return [NSApp.effectiveAppearance.name hasSuffix:@"DarkAqua"];
else
return false;
}
#endif
bool qt_apple_isApplicationExtension()
{
static bool isExtension = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSExtension"];
@ -433,16 +448,23 @@ void qt_apple_check_os_version()
version / 10000, version / 100 % 100, version % 100};
const NSOperatingSystemVersion current = NSProcessInfo.processInfo.operatingSystemVersion;
if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:required]) {
fprintf(stderr, "You can't use this version of %s with this version of %s. "
"You have %s %ld.%ld.%ld. Qt requires %s %ld.%ld.%ld or later.\n",
(reinterpret_cast<const NSString *>(
NSBundle.mainBundle.infoDictionary[@"CFBundleName"]).UTF8String),
os,
os, long(current.majorVersion), long(current.minorVersion), long(current.patchVersion),
os, long(required.majorVersion), long(required.minorVersion), long(required.patchVersion));
abort();
NSDictionary *plist = NSBundle.mainBundle.infoDictionary;
NSString *applicationName = plist[@"CFBundleDisplayName"];
if (!applicationName)
applicationName = plist[@"CFBundleName"];
if (!applicationName)
applicationName = NSProcessInfo.processInfo.processName;
fprintf(stderr, "Sorry, \"%s\" can not be run on this version of %s. "
"Qt requires %s %ld.%ld.%ld or later, you have %s %ld.%ld.%ld.\n",
applicationName.UTF8String, os,
os, long(required.majorVersion), long(required.minorVersion), long(required.patchVersion),
os, long(current.majorVersion), long(current.minorVersion), long(current.patchVersion));
exit(1);
}
}
Q_CONSTRUCTOR_FUNCTION(qt_apple_check_os_version);
// -------------------------------------------------------------------------

View File

@ -108,6 +108,8 @@
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
#endif
#define QT_MAC_WEAK_IMPORT(symbol) extern "C" decltype(symbol) symbol __attribute__((weak_import));
QT_BEGIN_NAMESPACE
template <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction)(U)>
class QAppleRefCounted
@ -180,16 +182,16 @@ private:
QString string;
};
#ifdef Q_OS_OSX
#ifdef Q_OS_MACOS
Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode();
#endif
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
#endif
Q_CORE_EXPORT void qt_apple_check_os_version();
Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
@ -326,6 +328,7 @@ private:
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(true, description, parent)
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__)
QT_MAC_WEAK_IMPORT(_os_activity_current);
#define QT_APPLE_LOG_ACTIVITY2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT)
#define QT_APPLE_LOG_ACTIVITY1(description) QT_APPLE_LOG_ACTIVITY2(true, description)
#define QT_APPLE_LOG_ACTIVITY(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY, __VA_ARGS__)

View File

@ -456,9 +456,6 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
, q_ptr(0)
#endif
{
#if defined(Q_OS_DARWIN)
qt_apple_check_os_version();
#endif
app_compile_version = flags & 0xffffff;
static const char *const empty = "";
if (argc == 0 || argv == 0) {

View File

@ -154,7 +154,7 @@ QT_END_NAMESPACE
#else // !QT_CONFIG(thread)
#include <qscopedpointer.h>
#include <QtCore/qscopedpointer.h>
#include <type_traits>

View File

@ -2742,10 +2742,13 @@ QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOption
flags.append("DontCaptureOption|");
if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
flags.append("UseUnicodePropertiesOption|");
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
if (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
flags.append("OptimizeOnFirstUsageOption|");
if (patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)
flags.append("DontAutomaticallyOptimizeOption|");
QT_WARNING_POP
flags.chop(1);
}

View File

@ -2789,7 +2789,7 @@ Qt::MouseButtons QTabletEvent::buttons() const
\header
\li Event Type
\li Description
\li Touch equence
\li Touch sequence
\row
\li Qt::ZoomNativeGesture
\li Magnification delta in percent.

View File

@ -42,6 +42,7 @@
#include <qpa/qplatformfontdatabase.h>
#include <QtCore/qendian.h>
#include <QtCore/qsettings.h>
#include <QtCore/qoperatingsystemversion.h>
#include <private/qimage_p.h>
@ -652,17 +653,36 @@ bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const
QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool aa, const QTransform &matrix)
{
glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat);
bool isColorGlyph = glyphFormat == QFontEngine::Format_ARGB;
QImage::Format imageFormat = isColorGlyph ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
QImage im(br.width.ceil().toInt(), br.height.ceil().toInt(), imageFormat);
im.fill(0);
if (!im.width() || !im.height())
return im;
#if defined(Q_OS_MACOS)
CGColorRef glyphColor = CGColorGetConstantColor(kCGColorWhite);
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) {
// macOS 10.14 uses a new font smoothing algorithm that takes the fill color into
// account. This means our default approach of drawing white on black to produce
// the alpha map will result in non-native looking text when then drawn as black
// on white during the final blit. As a workaround we use the application's current
// appearance to decide whether to draw with white or black fill, and then invert
// the glyph image in the latter case, producing an alpha map. This covers the
// most common use-cases, but longer term we should propagate the fill color all
// the way from the paint engine, and include it in the key for the glyph cache.
if (!qt_mac_applicationIsInDarkMode())
glyphColor = CGColorGetConstantColor(kCGColorBlack);
}
const bool blackOnWhiteGlyphs = !isColorGlyph
&& CGColorEqualToColor(glyphColor, CGColorGetConstantColor(kCGColorBlack));
if (blackOnWhiteGlyphs)
im.fill(Qt::white);
else
#endif
im.fill(0); // Faster than Qt::black
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
uint cgflags = isColorGlyph ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
@ -696,7 +716,11 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
if (!isColorGlyph) {
CGContextSetTextMatrix(ctx, cgMatrix);
#if defined(Q_OS_MACOS)
CGContextSetFillColorWithColor(ctx, glyphColor);
#else
CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
#endif
CGContextSetTextDrawingMode(ctx, kCGTextFill);
CGContextSetTextPosition(ctx, pos_x, pos_y);
@ -721,6 +745,11 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
CGContextRelease(ctx);
CGColorSpaceRelease(colorspace);
#if defined(Q_OS_MACOS)
if (blackOnWhiteGlyphs)
im.invertPixels();
#endif
return im;
}

View File

@ -295,26 +295,17 @@ public:
}
private:
template <std::size_t... Ts>
struct index {};
template <std::size_t N, std::size_t... Ts>
struct gen_seq : gen_seq<N - 1, N - 1, Ts...> {};
template <std::size_t... Ts>
struct gen_seq<0, Ts...> : index<Ts...> {};
template <typename ReturnType, bool V>
using if_requires_stret = typename std::enable_if<objc_msgsend_requires_stret<ReturnType>::value == V, ReturnType>::type;
template <typename ReturnType, std::size_t... Is>
if_requires_stret<ReturnType, false> msgSendSuper(std::tuple<Args...>& args, index<Is...>)
template <typename ReturnType, int... Is>
if_requires_stret<ReturnType, false> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
{
return qt_msgSendSuper<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
}
template <typename ReturnType, std::size_t... Is>
if_requires_stret<ReturnType, true> msgSendSuper(std::tuple<Args...>& args, index<Is...>)
template <typename ReturnType, int... Is>
if_requires_stret<ReturnType, true> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
{
return qt_msgSendSuper_stret<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
}
@ -322,7 +313,7 @@ private:
template <typename ReturnType>
ReturnType msgSendSuper(std::tuple<Args...>& args)
{
return msgSendSuper<ReturnType>(args, gen_seq<sizeof...(Args)>{});
return msgSendSuper<ReturnType>(args, QtPrivate::makeIndexSequence<sizeof...(Args)>{});
}
id m_receiver;

View File

@ -75,6 +75,9 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
<< "TraceLoggingValue(" << name << ".width(), \"width\"), "
<< "TraceLoggingValue(" << name << ".height(), \"height\")";
return;
case Tracepoint::Field::Pointer:
stream << "TraceLoggingPointer(" << name << ", \"" << name << "\")";
return;
default:
break;
}

View File

@ -43,6 +43,7 @@ private slots:
void keyValueAt();
void keyValues();
void duration();
void interpolation();
};
class TestableQVariantAnimation : public QVariantAnimation
@ -129,6 +130,30 @@ void tst_QVariantAnimation::duration()
QCOMPARE(anim.duration(), 500);
}
void tst_QVariantAnimation::interpolation()
{
QVariantAnimation unsignedAnim;
unsignedAnim.setStartValue(100u);
unsignedAnim.setEndValue(0u);
unsignedAnim.setDuration(100);
unsignedAnim.setCurrentTime(50);
QCOMPARE(unsignedAnim.currentValue().toUInt(), 50u);
QVariantAnimation signedAnim;
signedAnim.setStartValue(100);
signedAnim.setEndValue(0);
signedAnim.setDuration(100);
signedAnim.setCurrentTime(50);
QCOMPARE(signedAnim.currentValue().toInt(), 50);
QVariantAnimation pointAnim;
pointAnim.setStartValue(QPoint(100, 100));
pointAnim.setEndValue(QPoint(0, 0));
pointAnim.setDuration(100);
pointAnim.setCurrentTime(50);
QCOMPARE(pointAnim.currentValue().toPoint(), QPoint(50, 50));
}
QTEST_MAIN(tst_QVariantAnimation)
#include "tst_qvariantanimation.moc"

View File

@ -0,0 +1,2 @@
[timeZoneAbbreviation]
osx

View File

@ -2726,15 +2726,15 @@ void tst_QDateTime::timeZoneAbbreviation()
qDebug("(Skipped some CET-only tests)");
}
QString cet(QStringLiteral("CET")), cest(QStringLiteral("CEST"));
#ifdef Q_OS_ANDROID // Only reports (general) zones as offsets (QTBUG-68837)
cet = QStringLiteral("GMT+01:00");
cest = QStringLiteral("GMT+02:00");
#elif defined Q_OS_DARWIN // Lacked real names until 10.13, High Sierra
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSHighSierra) {
cet = QStringLiteral("GMT+1");
cest = QStringLiteral("GMT+2");
}
const QString cet(QStringLiteral("GMT+01:00"));
const QString cest(QStringLiteral("GMT+02:00"));
#elif defined Q_OS_DARWIN
const QString cet(QStringLiteral("GMT+1"));
const QString cest(QStringLiteral("GMT+2"));
#else
const QString cet(QStringLiteral("CET"));
const QString cest(QStringLiteral("CEST"));
#endif
QDateTime dt5(QDate(2013, 1, 1), QTime(0, 0, 0), QTimeZone("Europe/Berlin"));

View File

@ -0,0 +1,2 @@
[formatTimeZone]
osx

View File

@ -1623,15 +1623,15 @@ void tst_QLocale::formatTimeZone()
qDebug("(Skipped some CET-only tests)");
}
QString cet(QStringLiteral("CET")), cest(QStringLiteral("CEST"));
#ifdef Q_OS_ANDROID // Only reports (general) zones as offsets (QTBUG-68837)
cet = QStringLiteral("GMT+01:00");
cest = QStringLiteral("GMT+02:00");
#elif defined Q_OS_DARWIN // Lacked real names until 10.13, High Sierra
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSHighSierra) {
cet = QStringLiteral("GMT+1");
cest = QStringLiteral("GMT+2");
}
const QString cet(QStringLiteral("GMT+01:00"));
const QString cest(QStringLiteral("GMT+02:00"));
#elif defined Q_OS_DARWIN
const QString cet(QStringLiteral("GMT+1"));
const QString cest(QStringLiteral("GMT+2"));
#else
const QString cet(QStringLiteral("CET"));
const QString cest(QStringLiteral("CEST"));
#endif
QDateTime dt6(QDate(2013, 1, 1), QTime(0, 0, 0), QTimeZone("Europe/Berlin"));
@ -2467,6 +2467,10 @@ void tst_QLocale::currency()
QCOMPARE(de_DE.toCurrencyString(double(-1234.56), QLatin1String("BAZ")),
QString::fromUtf8("-1.234,56\xc2\xa0" "BAZ"));
const QLocale es_CR(QLocale::Spanish, QLocale::CostaRica);
QCOMPARE(es_CR.toCurrencyString(double(1565.25)),
QString::fromUtf8("\xE2\x82\xA1" "1\xC2\xA0" "565,25"));
const QLocale system = QLocale::system();
QVERIFY(system.toCurrencyString(1, QLatin1String("FOO")).contains(QLatin1String("FOO")));
}

View File

@ -12,3 +12,5 @@ ubuntu-18.04
ubuntu-18.04
[explicitGraphicsObjectTarget]
ubuntu-18.04
[autoCancelGestures2]
ubuntu-18.04

View File

@ -49,6 +49,7 @@
#include <qsortfilterproxymodel.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qtemporarydir.h>
#include <private/qfiledialog_p.h>
#if defined QT_BUILD_INTERNAL
#include <private/qsidebar_p.h>
@ -1310,57 +1311,116 @@ void tst_QFiledialog::saveButtonText()
QCOMPARE(button->text(), caption);
}
// Predicate for use with QTRY_VERIFY() that checks whether the file dialog list
// has been populated (contains an entry).
class DirPopulatedPredicate
{
public:
explicit DirPopulatedPredicate(QListView *list, const QString &needle) :
m_list(list), m_needle(needle) {}
operator bool() const
{
const auto model = m_list->model();
const auto root = m_list->rootIndex();
for (int r = 0, count = model->rowCount(root); r < count; ++r) {
if (m_needle == model->index(r, 0, root).data(Qt::DisplayRole).toString())
return true;
}
return false;
}
private:
QListView *m_list;
QString m_needle;
};
// A predicate for use with QTRY_VERIFY() that ensures an entry of the file dialog
// list is selected by pressing cursor down.
class SelectDirTestPredicate
{
public:
explicit SelectDirTestPredicate(QListView *list, const QString &needle) :
m_list(list), m_needle(needle) {}
operator bool() const
{
if (m_needle == m_list->currentIndex().data(Qt::DisplayRole).toString())
return true;
QCoreApplication::processEvents();
QTest::keyClick(m_list, Qt::Key_Down);
return false;
}
private:
QListView *m_list;
QString m_needle;
};
void tst_QFiledialog::clearLineEdit()
{
QFileDialog fd(0, "caption", "foo");
// Play it really safe by creating a directory which should show first in
// a temporary dir
QTemporaryDir workDir(QDir::tempPath() + QLatin1String("/tst_qfd_clearXXXXXX"));
QVERIFY2(workDir.isValid(), qPrintable(workDir.errorString()));
const QString workDirPath = workDir.path();
const QString dirName = QLatin1String("aaaaa");
QVERIFY(QDir(workDirPath).mkdir(dirName));
QFileDialog fd(nullptr,
QLatin1String(QTest::currentTestFunction()) + QLatin1String(" AnyFile"),
"foo");
fd.setViewMode(QFileDialog::List);
fd.setFileMode(QFileDialog::AnyFile);
fd.show();
//play it really safe by creating a directory
QDir::home().mkdir("_____aaaaaaaaaaaaaaaaaaaaaa");
QLineEdit *lineEdit = fd.findChild<QLineEdit*>("fileNameEdit");
QVERIFY(lineEdit);
QCOMPARE(lineEdit->text(), QLatin1String("foo"));
fd.setDirectory(QDir::home());
QListView* list = fd.findChild<QListView*>("listView");
QVERIFY(list);
// saving a file the text shouldn't be cleared
fd.setDirectory(QDir::home());
// When in AnyFile mode, lineEdit's text shouldn't be cleared when entering
// a directory by activating one in the list
fd.setDirectory(workDirPath);
DirPopulatedPredicate dirPopulated(list, dirName);
QTRY_VERIFY(dirPopulated);
#ifdef QT_KEYPAD_NAVIGATION
list->setEditFocus(true);
#endif
QTest::keyClick(list, Qt::Key_Down);
SelectDirTestPredicate selectTestDir(list, dirName);
QTRY_VERIFY(selectTestDir);
#ifndef Q_OS_MAC
QTest::keyClick(list, Qt::Key_Return);
#else
QTest::keyClick(list, Qt::Key_O, Qt::ControlModifier);
#endif
QTRY_VERIFY(fd.directory().absolutePath() != QDir::home().absolutePath());
QTRY_VERIFY(fd.directory().absolutePath() != workDirPath);
QVERIFY(!lineEdit->text().isEmpty());
// selecting a dir the text should be cleared so one can just hit ok
// When in Directory mode, lineEdit's text should be cleared when entering
// a directory by activating one in the list so one can just hit ok
// and it selects that directory
fd.setFileMode(QFileDialog::Directory);
fd.setDirectory(QDir::home());
fd.setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1String(" Directory"));
fd.setDirectory(workDirPath);
QTRY_VERIFY(dirPopulated);
QTRY_VERIFY(selectTestDir);
QTest::keyClick(list, Qt::Key_Down);
#ifndef Q_OS_MAC
QTest::keyClick(list, Qt::Key_Return);
#else
QTest::keyClick(list, Qt::Key_O, Qt::ControlModifier);
#endif
QTRY_VERIFY(fd.directory().absolutePath() != QDir::home().absolutePath());
QTRY_VERIFY(fd.directory().absolutePath() != workDirPath);
QVERIFY(lineEdit->text().isEmpty());
//remove the dir
QDir::home().rmdir("_____aaaaaaaaaaaaaaaaaaaaaa");
}
void tst_QFiledialog::enableChooseButton()