Merge "Merge remote-tracking branch 'origin/5.13' into 5.14"

This commit is contained in:
Qt Forward Merge Bot 2019-10-24 01:00:14 +02:00 committed by Edward Welbourne
commit 4158de330d
37 changed files with 437 additions and 174 deletions

View File

@ -4690,7 +4690,7 @@
The definitions above define a qmake target called \c mytarget, containing a
Makefile target called \c{.buildfile} which in turn is generated with the
\l{touchfunction}{touch()} function. Finally, the
\c touch command. Finally, the
\c{.depends} member specifies that \c mytarget depends on \c mytarget2,
another target that is defined afterwards. \c mytarget2 is a dummy target.
It is only defined to echo some text to the console.

View File

@ -327,9 +327,9 @@ public:
return pre;
}
static constexpr QSpecialInteger max()
static Q_DECL_CONSTEXPR QSpecialInteger max()
{ return QSpecialInteger(std::numeric_limits<T>::max()); }
static constexpr QSpecialInteger min()
static Q_DECL_CONSTEXPR QSpecialInteger min()
{ return QSpecialInteger(std::numeric_limits<T>::min()); }
};
@ -373,8 +373,8 @@ public:
QLEInteger &operator ++(int);
QLEInteger &operator --(int);
static constexpr QLEInteger max();
static constexpr QLEInteger min();
static Q_DECL_CONSTEXPR QLEInteger max();
static Q_DECL_CONSTEXPR QLEInteger min();
};
template<typename T>
@ -400,8 +400,8 @@ public:
QBEInteger &operator ++(int);
QBEInteger &operator --(int);
static constexpr QBEInteger max();
static constexpr QBEInteger min();
static Q_DECL_CONSTEXPR QBEInteger max();
static Q_DECL_CONSTEXPR QBEInteger min();
};
#else

View File

@ -114,8 +114,8 @@ extern "C" {
// without full system POSIX.
# pragma weak shm_area_password
# pragma weak shm_area_name
char *shm_area_password = "dummy";
char *shm_area_name = "dummy";
char shm_area_password[] = "dummy";
char shm_area_name[] = "dummy";
}
#endif

View File

@ -142,36 +142,45 @@ QString QStandardPaths::writableLocation(StandardLocation type)
}
case RuntimeLocation:
{
const uint myUid = uint(geteuid());
// http://standards.freedesktop.org/basedir-spec/latest/
const uint myUid = uint(geteuid());
// since the current user is the owner, set both xxxUser and xxxOwner
const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
| QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
QFileInfo fileInfo;
QString xdgRuntimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
if (xdgRuntimeDir.isEmpty()) {
const QString userName = QFileSystemEngine::resolveUserName(myUid);
xdgRuntimeDir = QDir::tempPath() + QLatin1String("/runtime-") + userName;
fileInfo.setFile(xdgRuntimeDir);
if (!fileInfo.isDir()) {
if (!QDir().mkdir(xdgRuntimeDir)) {
qErrnoWarning("QStandardPaths: error creating runtime directory %ls",
qUtf16Printable(xdgRuntimeDir));
return QString();
}
}
#ifndef Q_OS_WASM
qWarning("QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '%ls'", qUtf16Printable(xdgRuntimeDir));
#endif
} else {
fileInfo.setFile(xdgRuntimeDir);
if (!fileInfo.exists()) {
qWarning("QStandardPaths: XDG_RUNTIME_DIR points to non-existing path '%ls', "
"please create it with 0700 permissions.", qUtf16Printable(xdgRuntimeDir));
return QString();
}
}
if (fileInfo.exists()) {
if (!fileInfo.isDir()) {
qWarning("QStandardPaths: XDG_RUNTIME_DIR points to '%ls' which is not a directory",
qUtf16Printable(xdgRuntimeDir));
return QString();
}
} else {
QFileSystemEntry entry(xdgRuntimeDir);
if (!QFileSystemEngine::createDirectory(entry, false)) {
if (errno != EEXIST) {
qErrnoWarning("QStandardPaths: error creating runtime directory %ls",
qUtf16Printable(xdgRuntimeDir));
return QString();
}
} else {
QSystemError error;
if (!QFileSystemEngine::setPermissions(entry, wantedPerms, error)) {
qWarning("QStandardPaths: could not set correct permissions on runtime directory %ls: %ls",
qUtf16Printable(xdgRuntimeDir), qUtf16Printable(error.toString()));
return QString();
}
}
}
// "The directory MUST be owned by the user"
if (fileInfo.ownerId() != myUid) {
@ -181,17 +190,12 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return QString();
}
// "and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700."
// since the current user is the owner, set both xxxUser and xxxOwner
const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
| QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
if (fileInfo.permissions() != wantedPerms) {
QFile file(xdgRuntimeDir);
if (!file.setPermissions(wantedPerms)) {
qWarning("QStandardPaths: could not set correct permissions on runtime directory %ls: %ls",
qUtf16Printable(xdgRuntimeDir), qUtf16Printable(file.errorString()));
return QString();
}
qWarning("QStandardPaths: wrong permissions on runtime directory %ls, %x instead of %x",
qUtf16Printable(xdgRuntimeDir), uint(fileInfo.permissions()), uint(wantedPerms));
return QString();
}
return xdgRuntimeDir;
}
default:

View File

@ -71,21 +71,6 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
// Macro QSHAREDPOINTER_VERIFY_AUTO_CAST
// generates a compiler error if the following construct isn't valid:
// T *ptr1;
// X *ptr2 = ptr1;
//
#ifdef QT_NO_DEBUG
# define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) qt_noop()
#else
template<typename T> inline void qt_sharedpointer_cast_check(T *) { }
# define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) \
qt_sharedpointer_cast_check<T>(static_cast<X *>(0))
#endif
//
// forward declarations
//
@ -299,6 +284,9 @@ template <class T> class QSharedPointer
{
typedef T *QSharedPointer:: *RestrictedBool;
typedef QtSharedPointer::ExternalRefCountData Data;
template <typename X>
using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
public:
typedef T Type;
typedef T element_type;
@ -322,11 +310,11 @@ public:
Q_DECL_CONSTEXPR QSharedPointer(std::nullptr_t) noexcept : value(nullptr), d(nullptr) { }
template <class X>
template <class X, IfCompatible<X> = true>
inline explicit QSharedPointer(X *ptr) : value(ptr) // noexcept
{ internalConstruct(ptr, QtSharedPointer::NormalDeleter()); }
template <class X, typename Deleter>
template <class X, typename Deleter, IfCompatible<X> = true>
inline QSharedPointer(X *ptr, Deleter deleter) : value(ptr) // throws
{ internalConstruct(ptr, deleter); }
@ -354,7 +342,7 @@ public:
return *this;
}
template <class X>
template <class X, IfCompatible<X> = true>
QSharedPointer(QSharedPointer<X> &&other) noexcept
: value(other.value), d(other.d)
{
@ -362,7 +350,7 @@ public:
other.value = nullptr;
}
template <class X>
template <class X, IfCompatible<X> = true>
QSharedPointer &operator=(QSharedPointer<X> &&other) noexcept
{
QSharedPointer moved(std::move(other));
@ -370,11 +358,11 @@ public:
return *this;
}
template <class X>
template <class X, IfCompatible<X> = true>
QSharedPointer(const QSharedPointer<X> &other) noexcept : value(other.value), d(other.d)
{ if (d) ref(); }
template <class X>
template <class X, IfCompatible<X> = true>
inline QSharedPointer &operator=(const QSharedPointer<X> &other)
{
QSharedPointer copy(other);
@ -382,11 +370,11 @@ public:
return *this;
}
template <class X>
template <class X, IfCompatible<X> = true>
inline QSharedPointer(const QWeakPointer<X> &other) : value(nullptr), d(nullptr)
{ *this = other; }
template <class X>
template <class X, IfCompatible<X> = true>
inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other)
{ internalSet(other.d, other.value); return *this; }
@ -556,6 +544,8 @@ class QWeakPointer
{
typedef T *QWeakPointer:: *RestrictedBool;
typedef QtSharedPointer::ExternalRefCountData Data;
template <typename X>
using IfCompatible = typename std::enable_if<std::is_convertible<X*, T*>::value, bool>::type;
public:
typedef T element_type;
@ -581,14 +571,14 @@ public:
#ifndef QT_NO_QOBJECT
// special constructor that is enabled only if X derives from QObject
#if QT_DEPRECATED_SINCE(5, 0)
template <class X>
template <class X, IfCompatible<X> = true>
QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
{ }
#endif
#endif
#if QT_DEPRECATED_SINCE(5, 0)
template <class X>
template <class X, IfCompatible<X> = true>
QT_DEPRECATED inline QWeakPointer &operator=(X *ptr)
{ return *this = QWeakPointer(ptr); }
#endif
@ -624,11 +614,11 @@ public:
return *this;
}
template <class X>
template <class X, IfCompatible<X> = true>
inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr)
{ *this = o; }
template <class X>
template <class X, IfCompatible<X> = true>
inline QWeakPointer &operator=(const QWeakPointer<X> &o)
{
// conversion between X and T could require access to the virtual table
@ -645,14 +635,13 @@ public:
bool operator!=(const QWeakPointer<X> &o) const noexcept
{ return !(*this == o); }
template <class X>
template <class X, IfCompatible<X> = true>
inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr)
{ *this = o; }
template <class X>
template <class X, IfCompatible<X> = true>
inline QWeakPointer &operator=(const QSharedPointer<X> &o)
{
QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid
internalSet(o.d, o.data());
return *this;
}
@ -689,7 +678,7 @@ public:
{ return *this = QWeakPointer<X>(ptr, true); }
#ifndef QT_NO_QOBJECT
template <class X>
template <class X, IfCompatible<X> = true>
inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr)
{ }
#endif

View File

@ -57,6 +57,12 @@
#include <QtGui/QOpenGLVersionFunctions>
#include <QtGui/qopenglcontext.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QOpenGLFunctions_4_2_Compatibility : public QAbstractOpenGLFunctions
@ -5632,6 +5638,10 @@ inline void QOpenGLFunctions_4_2_Compatibility::glVertexAttribI1i(GLuint index,
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL && !QT_OPENGL_ES_2
#endif

View File

@ -57,6 +57,12 @@
#include <QtGui/QOpenGLVersionFunctions>
#include <QtGui/qopenglcontext.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QOpenGLFunctions_4_2_Core : public QAbstractOpenGLFunctions
@ -3027,6 +3033,10 @@ inline void QOpenGLFunctions_4_2_Core::glDrawArraysInstancedBaseInstance(GLenum
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL && !QT_OPENGL_ES_2
#endif

View File

@ -57,6 +57,12 @@
#include <QtGui/QOpenGLVersionFunctions>
#include <QtGui/qopenglcontext.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QOpenGLFunctions_4_3_Compatibility : public QAbstractOpenGLFunctions
@ -5839,6 +5845,10 @@ inline void QOpenGLFunctions_4_3_Compatibility::glVertexAttribI1i(GLuint index,
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL && !QT_OPENGL_ES_2
#endif

View File

@ -57,6 +57,13 @@
#include <QtGui/QOpenGLVersionFunctions>
#include <QtGui/qopenglcontext.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QOpenGLFunctions_4_3_Core : public QAbstractOpenGLFunctions
@ -3230,6 +3237,10 @@ inline void QOpenGLFunctions_4_3_Core::glClearBufferData(GLenum target, GLenum i
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL && !QT_OPENGL_ES_2
#endif

View File

@ -59,6 +59,12 @@
QT_BEGIN_NAMESPACE
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
class Q_GUI_EXPORT QOpenGLFunctions_4_4_Compatibility : public QAbstractOpenGLFunctions
{
public:
@ -5961,6 +5967,10 @@ inline void QOpenGLFunctions_4_4_Compatibility::glVertexP2ui(GLenum type, GLuint
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL && !QT_OPENGL_ES_2
#endif

View File

@ -57,6 +57,12 @@
#include <QtGui/QOpenGLVersionFunctions>
#include <QtGui/qopenglcontext.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QOpenGLFunctions_4_4_Core : public QAbstractOpenGLFunctions
@ -3415,6 +3421,10 @@ inline void QOpenGLFunctions_4_4_Core::glBufferStorage(GLenum target, GLsizeiptr
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL && !QT_OPENGL_ES_2
#endif

View File

@ -57,6 +57,12 @@
#include <QtGui/QOpenGLVersionFunctions>
#include <QtGui/qopenglcontext.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QOpenGLFunctions_4_5_Compatibility : public QAbstractOpenGLFunctions
@ -6679,6 +6685,10 @@ inline void QOpenGLFunctions_4_5_Compatibility::glGetnMapdv(GLenum target, GLenu
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL && !QT_OPENGL_ES_2
#endif

View File

@ -57,6 +57,12 @@
#include <QtGui/QOpenGLVersionFunctions>
#include <QtGui/qopenglcontext.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QOpenGLFunctions_4_5_Core : public QAbstractOpenGLFunctions
@ -4056,6 +4062,11 @@ inline void QOpenGLFunctions_4_5_Core::glClipControl(GLenum origin, GLenum depth
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL && !QT_OPENGL_ES_2
#endif

View File

@ -61,6 +61,12 @@
#include <QtCore/qpair.h>
#include <QtGui/qopengl.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
class QOpenGLContext;
@ -1897,6 +1903,10 @@ public:
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL
#endif

View File

@ -2088,8 +2088,12 @@ void QTextDocumentLayoutPrivate::drawBlock(const QPointF &offset, QPainter *pain
tl->draw(painter, offset, selections, context.clip.isValid() ? (context.clip & clipRect) : clipRect);
if ((context.cursorPosition >= blpos && context.cursorPosition < blpos + bllen)
|| (context.cursorPosition < -1 && !tl->preeditAreaText().isEmpty())) {
// if the block is empty and it precedes a table, do not draw the cursor.
// the cursor is drawn later after the table has been drawn so no need
// to draw it here.
if (!isEmptyBlockBeforeTable(frameIteratorForTextPosition(blpos))
&& ((context.cursorPosition >= blpos && context.cursorPosition < blpos + bllen)
|| (context.cursorPosition < -1 && !tl->preeditAreaText().isEmpty()))) {
int cpos = context.cursorPosition;
if (cpos < -1)
cpos = tl->preeditAreaPosition() - (cpos + 2);

View File

@ -60,6 +60,12 @@
#include "qopenglextensions.h"
#include <QtGui/qopenglcontext.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
QAbstractOpenGLExtension::~QAbstractOpenGLExtension()
@ -7720,3 +7726,6 @@ bool QOpenGLExtension_QCOM_tiled_rendering::initializeOpenGLFunctions()
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif

View File

@ -66,6 +66,12 @@
#include <QtGui/qopengl.h>
// MemoryBarrier is a macro on some architectures on Windows
#ifdef Q_OS_WIN
#pragma push_macro("MemoryBarrier")
#undef MemoryBarrier
#endif
QT_BEGIN_NAMESPACE
class QOpenGLContext;
@ -19473,6 +19479,10 @@ inline void QOpenGLExtension_QCOM_tiled_rendering::glEndTilingQCOM(GLbitfield pr
QT_END_NAMESPACE
#ifdef Q_OS_WIN
#pragma pop_macro("MemoryBarrier")
#endif
#endif // QT_NO_OPENGL
#endif

View File

@ -195,20 +195,6 @@ namespace QtAndroidInput
angleDelta);
}
void releaseMouse(int x, int y)
{
m_ignoreMouseEvents = true;
QPoint globalPos(x,y);
QWindow *tlw = topLevelWindowAt(globalPos);
QPoint localPos = tlw ? (globalPos-tlw->position()) : globalPos;
// Release left button
QWindowSystemInterface::handleMouseEvent(tlw,
localPos,
globalPos,
Qt::MouseButtons(Qt::NoButton));
}
static void longPress(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y)
{
QAndroidInputContext *inputContext = QAndroidInputContext::androidInputContext();

View File

@ -61,8 +61,6 @@ namespace QtAndroidInput
void updateHandles(int handleCount, QPoint editMenuPos = QPoint(), uint32_t editButtons = 0, QPoint cursor = QPoint(), QPoint anchor = QPoint(), bool rtl = false);
bool registerNatives(JNIEnv *env);
void releaseMouse(int x, int y);
}
QT_END_NAMESPACE

View File

@ -827,9 +827,6 @@ void QAndroidInputContext::longPress(int x, int y)
focusObjectStopComposing();
// Release left button, otherwise the following events will cancel the menu popup
QtAndroidInput::releaseMouse(x, y);
const double pixelDensity =
QGuiApplication::focusWindow()
? QHighDpiScaling::factor(QGuiApplication::focusWindow())

View File

@ -59,6 +59,8 @@ QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode, const QString &devi
QString id = deviceId;
if (id.isEmpty())
id = QCocoaPrinterSupport().defaultPrintDeviceId();
else
setProperty(QPrintEngine::PPK_PrinterName, deviceId);
d->m_printDevice.reset(new QCocoaPrintDevice(id));
d->m_pageLayout.setPageSize(d->m_printDevice->defaultPageSize());
d->initialize();

View File

@ -221,18 +221,18 @@ public:
int disconnectCount;
bool hasSQLFetchScroll;
bool isStmtHandleValid();
bool isStmtHandleValid() const;
void updateStmtHandleState();
};
bool QODBCResultPrivate::isStmtHandleValid()
bool QODBCResultPrivate::isStmtHandleValid() const
{
return disconnectCount == drv_d_func()->disconnectCount;
return drv_d_func() && disconnectCount == drv_d_func()->disconnectCount;
}
void QODBCResultPrivate::updateStmtHandleState()
{
disconnectCount = drv_d_func()->disconnectCount;
disconnectCount = drv_d_func() ? drv_d_func()->disconnectCount : 0;
}
static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode = 0)
@ -975,7 +975,7 @@ QODBCResult::QODBCResult(const QODBCDriver *db)
QODBCResult::~QODBCResult()
{
Q_D(QODBCResult);
if (d->hStmt && d->isStmtHandleValid() && driver()->isOpen()) {
if (d->hStmt && d->isStmtHandleValid() && driver() && driver()->isOpen()) {
SQLRETURN r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt);
if (r != SQL_SUCCESS)
qSqlWarning(QLatin1String("QODBCDriver: Unable to free statement handle ")

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@ -296,3 +296,31 @@ QTest::keyClick(myWindow, Qt::Key_Escape, Qt::ShiftModifier, 200);
}
//! [30]
void TestQLocale::initTestCase_data()
{
QTest::addColumn<QLocale>("locale");
QTest::newRow("C") << QLocale::c();
QTest::newRow("UKish") << QLocale("en_GB");
QTest::newRow("USAish") << QLocale(QLocale::English);
}
void TestQLocale::roundTripInt_data()
{
QTest::addColumn<int>("number");
QTest::newRow("one") << 1;
QTest::newRow("two") << 2;
QTest::newRow("ten") << 10;
}
//! [30]
//! [31]
void TestQLocale::roundTripInt()
{
QFETCH_GLOBAL(QLocale, locale);
QFETCH(int, number);
bool ok;
QCOMPARE(locale.toInt(locale.toString(number), &ok), number);
QVERIFY(ok);
}
//! [31]

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@ -89,12 +89,14 @@
private slot is a test function in your test. QTest::qExec() can be used to execute
all test functions in the test object.
In addition, there are four private slots that are \e not treated as test functions.
They will be executed by the testing framework and can be used to initialize and
clean up either the entire test or the current test function.
In addition, you can define the following private slots that are \e not
treated as test functions. When present, they will be executed by the
testing framework and can be used to initialize and clean up either the
entire test or the current test function.
\list
\li \c{initTestCase()} will be called before the first test function is executed.
\li \c{initTestCase_data()} will be called to create a global test data table.
\li \c{cleanupTestCase()} will be called after the last test function was executed.
\li \c{init()} will be called before each test function is executed.
\li \c{cleanup()} will be called after every test function.
@ -358,18 +360,44 @@
counters can be obtained by running any benchmark executable with the
option \c -perfcounterlist.
\list
\li \b Notes:
\note
\list
\li Using the performance counter may require enabling access to non-privileged
applications.
\li Devices that do not support high-resolution timers default to
one-millisecond granularity.
\endlist
\endlist
See \l {Chapter 5: Writing a Benchmark}{Writing a Benchmark} in the Qt Test
Tutorial for more benchmarking examples.
\section1 Using Global Test Data
You can define \c{initTestCase_data()} to set up a global test data table.
Each test is run once for each row in the global test data table. When the
test function itself \l{Chapter 2: Data-driven Testing}{is data-driven},
it is run for each local data row, for each global data row. So, if there
are \c g rows in the global data table and \c d rows in the test's own
data-table, the number of runs of this test is \c g times \c d.
Global data is fetched from the table using the \l QFETCH_GLOBAL() macro.
The following are typical use cases for global test data:
\list
\li Selecting among the available database backends in QSql tests to run
every test against every database.
\li Doing all networking tests with and without SSL (HTTP versus HTTPS)
and proxying.
\li Testing a timer with a high precision clock and with a coarse one.
\li Selecting whether a parser shall read from a QByteArray or from a
QIODevice.
\endlist
For example, to test each number provided by \c {roundTripInt_data()} with
each locale provided by \c {initTestCase_data()}:
\snippet code/src_qtestlib_qtestcase.cpp 31
*/
/*!
@ -513,10 +541,9 @@
QTest::newRow() function. Each set of data will become a
separate row in the test table.
\l QTest::newRow() takes one argument: a name that will be
associated with the data set. If the test fails, the name will be
used in the test log, referencing the failed data. Then we
stream the data set into the new table row. First an arbitrary
\l QTest::newRow() takes one argument: a name that will be associated
with the data set and used in the test log to identify the data set.
Then we stream the data set into the new table row. First an arbitrary
string, and then the expected result of applying the
QString::toUpper() function to that string.
@ -548,6 +575,10 @@
\li HELLO
\endtable
When data is streamed into the row, each datum is asserted to match
the type of the column whose value it supplies. If any assertion fails,
the test is aborted.
\section1 Rewriting the Test Function
Our test function can now be rewritten:

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@ -48,7 +48,7 @@
\snippet code/doc_src_qsignalspy.cpp 1
\b {Note:} Non-standard data types need to be registered, using
\note Non-standard data types need to be registered, using
the qRegisterMetaType() function, before you can create a
QSignalSpy. For example:
@ -57,6 +57,18 @@
To retrieve the instance, you can use qvariant_cast:
\snippet code/doc_src_qsignalspy.cpp 3
\section1 Verifying Signal Emissions
The QSignalSpy class provides an elegant mechanism for capturing the list
of signals emitted by an object. However, you should verify its validity
after construction. The constructor does a number of sanity checks, such as
verifying that the signal to be spied upon actually exists. To make the
diagnosis of test failures easier, the results of these checks should be
checked by calling \c QVERIFY(spy.isValid()) before proceeding further with
a test.
\sa QVERIFY()
*/
/*! \fn QSignalSpy::QSignalSpy(const QObject *object, const char *signal)

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@ -220,8 +220,8 @@
\relates QTest
The fetch macro creates a local variable named \a name with the type \a type
on the stack. \a name has to match the element name from the test's data.
If no such element exists, the test will assert.
on the stack. The \a name and \a type must match a column from the test's
data table. This is asserted and the test will abort if the assertion fails.
Assuming a test has the following data:
@ -235,10 +235,37 @@
\c aString and \c expected are variables on the stack that are initialized with
the current test data.
\b {Note:} This macro can only be used in a test function that is invoked
\note This macro can only be used in a test function that is invoked
by the test framework. The test function must have a _data function.
*/
/*! \macro QFETCH_GLOBAL(type, name)
\relates QTest
This macro fetches a variable named \a name with the type \a type from
a row in the global data table. The \a name and \a type must match a
column in the global data table. This is asserted and the test will abort
if the assertion fails.
Assuming a test has the following data:
\snippet code/src_qtestlib_qtestcase.cpp 30
The test's own data is a single number per row. In this case,
\c initTestCase_data() also supplies a locale per row. Therefore,
this test will be run with every combination of locale from the
latter and number from the former.
\snippet code/src_qtestlib_qtestcase.cpp 31
The locale is read from the global data table using QFETCH_GLOBAL(),
and the number is read from the local data table using QFETCH().
\note This macro can only be used in test methods of a class with an
\c initTestCase_data() method.
*/
/*! \macro QWARN(message)
\relates QTest
@ -255,7 +282,7 @@
This macro can be used to force a test failure. The test stops
executing and the failure \a message is appended to the test log.
\b {Note:} This macro can only be used in a test function that is invoked
\note This macro can only be used in a test function that is invoked
by the test framework.
Example:
@ -332,7 +359,7 @@
\a mode is a \l QTest::TestFailMode and sets whether the test should
continue to execute or not.
\b {Note:} This macro can only be used in a test function that is invoked
\note This macro can only be used in a test function that is invoked
by the test framework.
Example 1:
@ -394,13 +421,13 @@
test has been installed, and regardless of whether the test's build tree
is equal to the test's source tree.
\b {Note:} reliable detection of testdata from the source directory requires
\note reliable detection of testdata from the source directory requires
either that qmake is used, or the \c{QT_TESTCASE_BUILDDIR} macro is defined to
point to the working directory from which the compiler is invoked, or only
absolute paths to the source files are passed to the compiler. Otherwise, the
absolute path of the source directory cannot be determined.
\b {Note:} For tests that use the \l QTEST_APPLESS_MAIN() macro to generate a
\note For tests that use the \l QTEST_APPLESS_MAIN() macro to generate a
\c{main()} function, \c{QFINDTESTDATA} will not attempt to find test data
relative to QCoreApplication::applicationDirPath(). In practice, this means that
tests using \c{QTEST_APPLESS_MAIN()} will fail to find their test data
@ -422,7 +449,7 @@
Similarly, if qmake is used and the configuration includes \c{QT += gui}, then
\c QT_GUI_LIB will be defined automatically.
\b {Note:} On platforms that have keypad navigation enabled by default,
\note On platforms that have keypad navigation enabled by default,
this macro will forcefully disable it if \c QT_WIDGETS_LIB is defined. This is done
to simplify the usage of key events when writing autotests. If you wish to write a
test case that uses keypad navigation, you should enable it either in the
@ -662,7 +689,7 @@
Simulates pressing a \a key with an optional \a modifier on a \a widget. If \a delay
is larger than 0, the test will wait for \a delay milliseconds before pressing the key.
\b {Note:} At some point you should release the key using \l keyRelease().
\note At some point you should release the key using \l keyRelease().
\sa QTest::keyRelease(), QTest::keyClick()
*/
@ -674,7 +701,7 @@
If \a delay is larger than 0, the test will wait for \a delay milliseconds
before pressing the key.
\b {Note:} At some point you should release the key using \l keyRelease().
\note At some point you should release the key using \l keyRelease().
\sa QTest::keyRelease(), QTest::keyClick()
*/
@ -686,7 +713,7 @@
Simulates pressing a \a key with an optional \a modifier on a \a window. If \a delay
is larger than 0, the test will wait for \a delay milliseconds before pressing the key.
\b {Note:} At some point you should release the key using \l keyRelease().
\note At some point you should release the key using \l keyRelease().
\sa QTest::keyRelease(), QTest::keyClick()
*/
@ -699,7 +726,7 @@
If \a delay is larger than 0, the test will wait for \a delay milliseconds
before pressing the key.
\b {Note:} At some point you should release the key using \l keyRelease().
\note At some point you should release the key using \l keyRelease().
\sa QTest::keyRelease(), QTest::keyClick()
*/
@ -920,12 +947,12 @@
You can add specializations or overloads of this function to your test to enable
verbose output.
\b {Note:} Starting with Qt 5.5, you should prefer to provide a toString() function
\note Starting with Qt 5.5, you should prefer to provide a toString() function
in the type's namespace instead of specializing this template.
If your code needs to continue to work with the QTestLib from Qt 5.4 or
earlier, you need to continue to use specialization.
\b {Note:} The caller of toString() must delete the returned data
\note The caller of toString() must delete the returned data
using \c{delete[]}. Your implementation should return a string
created with \c{new[]} or qstrdup(). The easiest way to do so is to
create a QByteArray or QString and calling QTest::toString() on it

View File

@ -1107,10 +1107,10 @@ QMenu::indicator:exclusive:checked:selected {
QMenuBar {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 lightgray, stop:1 darkgray);
spacing: 3px; /* spacing between menu bar items */
}
QMenuBar::item {
spacing: 3px; /* spacing between menu bar items */
padding: 1px 4px;
background: transparent;
border-radius: 4px;

View File

@ -386,7 +386,15 @@ void QGraphicsScenePrivate::_q_emitUpdated()
// Notify the changes to anybody interested.
QList<QRectF> oldUpdatedRects;
oldUpdatedRects = updateAll ? (QList<QRectF>() << q->sceneRect()) : updatedRects;
if (updateAll) {
oldUpdatedRects << q->sceneRect();
} else {
// Switch to a ranged constructor in Qt 6...
oldUpdatedRects.reserve(int(updatedRects.size()));
std::copy(updatedRects.cbegin(), updatedRects.cend(),
std::back_inserter(oldUpdatedRects));
}
updateAll = false;
updatedRects.clear();
emit q->changed(oldUpdatedRects);
@ -3219,8 +3227,7 @@ void QGraphicsScene::update(const QRectF &rect)
view->d_func()->updateRectF(rect);
}
} else {
if (!d->updatedRects.contains(rect))
d->updatedRects << rect;
d->updatedRects.insert(rect);
}
}

View File

@ -69,6 +69,9 @@
#include <QtWidgets/qstyle.h>
#include <QtWidgets/qstyleoption.h>
#include <set>
#include <tuple>
QT_REQUIRE_CONFIG(graphicsview);
QT_BEGIN_NAMESPACE
@ -122,7 +125,19 @@ public:
QRectF growingItemsBoundingRect;
void _q_emitUpdated();
QList<QRectF> updatedRects;
struct UpdatedRectsCmp
{
bool operator() (const QRectF &a, const QRectF &b) const noexcept
{
return std::make_tuple(a.y(), a.x(), a.height(), a.width())
< std::make_tuple(b.y(), b.x(), b.height(), b.width());
}
};
// std::set was used here instead of std::unordered_set due to requiring only a comparator and
// showing equivalent performance in empirical measurements within the ranges of interest...
std::set<QRectF, UpdatedRectsCmp> updatedRects;
QPainterPath selectionArea;
int selectionChanging;

View File

@ -514,15 +514,6 @@ void QStyledItemDelegate::updateEditorGeometry(QWidget *editor,
QStyle *style = widget ? widget->style() : QApplication::style();
QRect geom = style->subElementRect(QStyle::SE_ItemViewItemText, &opt, widget);
const int delta = qSmartMinSize(editor).width() - geom.width();
if (delta > 0) {
//we need to widen the geometry
if (editor->layoutDirection() == Qt::RightToLeft)
geom.adjust(-delta, 0, 0, 0);
else
geom.adjust(0, 0, delta, 0);
}
editor->setGeometry(geom);
}

View File

@ -893,7 +893,7 @@ void QWidgetWindow::handleDragEnterEvent(QDragEnterEvent *event, QWidget *widget
void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
{
auto *widget = findDnDTarget(m_widget, event->pos());
QPointer<QWidget> widget = findDnDTarget(m_widget, event->pos());
if (!widget) {
event->ignore();
if (m_dragTarget) { // Send DragLeave to previous
@ -916,14 +916,18 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event);
m_dragTarget = nullptr;
}
// Send DragEnter to new widget.
handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget);
// Handling 'DragEnter' should suffice for the application.
translated.setDropAction(event->dropAction());
translated.setAccepted(event->isAccepted());
// The drag enter event is always immediately followed by a drag move event,
// see QDragEnterEvent documentation.
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
// widget might have been deleted when handling the leaveEvent
if (widget) {
// Send DragEnter to new widget.
handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget);
// Handling 'DragEnter' should suffice for the application.
translated.setDropAction(event->dropAction());
translated.setAccepted(event->isAccepted());
// The drag enter event is always immediately followed by a drag move event,
// see QDragEnterEvent documentation.
if (m_dragTarget)
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
}
}
event->setAccepted(translated.isAccepted());
event->setDropAction(translated.dropAction());

View File

@ -465,16 +465,6 @@ void tst_qstandardpaths::testRuntimeDirectory()
#ifdef Q_XDG_PLATFORM
const QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
QVERIFY(!runtimeDir.isEmpty());
// Check that it can automatically fix permissions
QFile file(runtimeDir);
const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser;
const QFile::Permissions additionalPerms = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
QCOMPARE(file.permissions(), wantedPerms | additionalPerms);
QVERIFY(file.setPermissions(wantedPerms | QFile::ExeGroup));
const QString runtimeDirAgain = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
QCOMPARE(runtimeDirAgain, runtimeDir);
QCOMPARE(QFile(runtimeDirAgain).permissions(), wantedPerms | additionalPerms);
#endif
}
@ -516,11 +506,27 @@ void tst_qstandardpaths::testCustomRuntimeDirectory()
const QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
QVERIFY2(runtimeDir.isEmpty(), qPrintable(runtimeDir));
// When $XDG_RUNTIME_DIR points to a non-existing directory, QStandardPaths should warn (QTBUG-48771)
qputenv("XDG_RUNTIME_DIR", "does_not_exist");
QTest::ignoreMessage(QtWarningMsg, "QStandardPaths: XDG_RUNTIME_DIR points to non-existing path 'does_not_exist', please create it with 0700 permissions.");
// When $XDG_RUNTIME_DIR points to a directory with wrong permissions, QStandardPaths should warn
const QByteArray wrongPermissionFileName = "wrong_permissions";
QDir::current().mkdir(wrongPermissionFileName);
QFile wrongPermissionFile(wrongPermissionFileName);
const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser;
QVERIFY(wrongPermissionFile.setPermissions(wantedPerms | QFile::ExeGroup));
qputenv("XDG_RUNTIME_DIR", wrongPermissionFileName);
QTest::ignoreMessage(QtWarningMsg,
qPrintable(QString::fromLatin1("QStandardPaths: wrong permissions on runtime directory " + wrongPermissionFileName + ", 7710 instead of 7700")));
const QString wrongPermissionRuntimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
QVERIFY(wrongPermissionRuntimeDir.isEmpty());
QDir::current().rmdir(wrongPermissionFileName);
// When $XDG_RUNTIME_DIR points to a non-existing directory, QStandardPaths should create it first
const QByteArray nonExistingDir = "does_not_exist";
qputenv("XDG_RUNTIME_DIR", nonExistingDir);
const QString nonExistingRuntimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
QVERIFY2(nonExistingRuntimeDir.isEmpty(), qPrintable(nonExistingRuntimeDir));
QVERIFY2(!nonExistingRuntimeDir.compare(nonExistingDir), qPrintable(nonExistingRuntimeDir));
QVERIFY(QDir::current().exists(nonExistingRuntimeDir));
QDir::current().rmdir(nonExistingRuntimeDir);
// When $XDG_RUNTIME_DIR points to a file, QStandardPaths should warn
const QString file = QFINDTESTDATA("tst_qstandardpaths.cpp");

View File

@ -40,6 +40,7 @@
#include "nontracked.h"
#include "wrapper.h"
#include <array>
#include <memory>
#include <stdlib.h>
#include <time.h>
@ -106,12 +107,15 @@ private slots:
void sharedFromThis();
void constructorThrow();
void overloads();
void threadStressTest_data();
void threadStressTest();
void validConstructs();
void invalidConstructs_data();
void invalidConstructs();
// let invalidConstructs be the last test, because it's the slowest;
// add new tests above this block
public slots:
@ -2383,6 +2387,11 @@ void tst_QSharedPointer::invalidConstructs_data()
QTest::newRow("incompatible-custom-lambda-deleter")
<< &QTest::QExternalTest::tryCompileFail
<< "QSharedPointer<Data> ptr(new Data, [](int *) {});\n";
QTest::newRow("incompatible-overload")
<< &QTest::QExternalTest::tryCompileFail
<< "void foo(QSharedPointer<DerivedData>) {}\n"
"void bar() { foo(QSharedPointer<Data>()); }\n";
}
void tst_QSharedPointer::invalidConstructs()
@ -2883,5 +2892,50 @@ void tst_QSharedPointer::reentrancyWhileDestructing()
ReentrancyWhileDestructing::A obj;
}
namespace {
struct Base1 {};
struct Base2 {};
struct Child1 : Base1 {};
struct Child2 : Base2 {};
template<template<typename> class SmartPtr>
struct Overloaded
{
std::array<int, 1> call(const SmartPtr<const Base1> &)
{
return {};
}
std::array<int, 2> call(const SmartPtr<const Base2> &)
{
return {};
}
static const Q_CONSTEXPR uint base1Called = sizeof(std::array<int, 1>);
static const Q_CONSTEXPR uint base2Called = sizeof(std::array<int, 2>);
void test()
{
#define QVERIFY_CALLS(expr, base) Q_STATIC_ASSERT(sizeof(call(expr)) == base##Called)
QVERIFY_CALLS(SmartPtr<Base1>{}, base1);
QVERIFY_CALLS(SmartPtr<Base2>{}, base2);
QVERIFY_CALLS(SmartPtr<const Base1>{}, base1);
QVERIFY_CALLS(SmartPtr<const Base2>{}, base2);
QVERIFY_CALLS(SmartPtr<Child1>{}, base1);
QVERIFY_CALLS(SmartPtr<Child2>{}, base2);
QVERIFY_CALLS(SmartPtr<const Child1>{}, base1);
QVERIFY_CALLS(SmartPtr<const Child2>{}, base2);
#undef QVERIFY_CALLS
}
};
}
void tst_QSharedPointer::overloads()
{
Overloaded<QSharedPointer> sharedOverloaded;
sharedOverloaded.test();
Overloaded<QWeakPointer> weakOverloaded;
weakOverloaded.test();
}
QTEST_MAIN(tst_QSharedPointer)
#include "tst_qsharedpointer.moc"

View File

@ -1131,7 +1131,7 @@ void tst_QDtls::handshakeReadyRead()
QUdpSocket *socket = qobject_cast<QUdpSocket *>(sender());
Q_ASSERT(socket);
if (!socket->pendingDatagramSize())
if (socket->pendingDatagramSize() <= 0)
return;
const bool isServer = socket == &serverSocket;

View File

@ -352,7 +352,7 @@ void tst_QDtlsCookie::receiveMessage(QUdpSocket *socket, QByteArray *message,
{
Q_ASSERT(socket && message);
if (!socket->pendingDatagramSize())
if (socket->pendingDatagramSize() <= 0)
testLoop.enterLoopMSecs(handshakeTimeoutMS);
QVERIFY(!testLoop.timeout());
@ -377,7 +377,7 @@ void tst_QDtlsCookie::serverReadyRead()
{
Q_ASSERT(clientsToWait);
if (!serverSocket.pendingDatagramSize())
if (serverSocket.pendingDatagramSize() <= 0)
return;
QByteArray hello;
@ -410,7 +410,7 @@ void tst_QDtlsCookie::clientReadyRead()
QUdpSocket *clientSocket = qobject_cast<QUdpSocket *>(sender());
Q_ASSERT(clientSocket);
if (!clientSocket->pendingDatagramSize())
if (clientSocket->pendingDatagramSize() <= 0)
return;
QDtls *handshake = nullptr;

View File

@ -190,8 +190,7 @@ private slots:
void task_250026_data() { generic_data("QODBC"); }
void task_250026();
void task_205701_data() { generic_data("QMYSQL"); }
void task_205701();
void crashQueryOnCloseDatabase();
void task_233829_data() { generic_data("QPSQL"); }
void task_233829();
@ -305,6 +304,8 @@ void tst_QSqlQuery::init()
void tst_QSqlQuery::cleanup()
{
if (QTest::currentTestFunction() == QLatin1String("crashQueryOnCloseDatabase"))
return;
QFETCH( QString, dbName );
QSqlDatabase db = QSqlDatabase::database( dbName );
CHECK_DATABASE( db );
@ -3442,19 +3443,17 @@ void tst_QSqlQuery::task_250026()
QCOMPARE( q.value( 0 ).toString().length(), data1026.length() );
}
void tst_QSqlQuery::task_205701()
void tst_QSqlQuery::crashQueryOnCloseDatabase()
{
QSqlDatabase qsdb = QSqlDatabase::addDatabase("QMYSQL", "atest");
qsdb.setHostName("test");
qsdb.setDatabaseName("test");
qsdb.setUserName("test");
qsdb.setPassword("test");
qsdb.open();
// {
QSqlQuery query(qsdb);
// }
QSqlDatabase::removeDatabase("atest");
for (const auto &dbName : qAsConst(dbs.dbNames)) {
QSqlDatabase clonedDb = QSqlDatabase::cloneDatabase(
QSqlDatabase::database(dbName), "crashTest");
qDebug() << "Testing crash in sqlquery dtor for driver" << clonedDb.driverName();
QVERIFY(clonedDb.open());
QSqlQuery q(clonedDb);
clonedDb.close();
QSqlDatabase::removeDatabase("crashTest");
}
}
void tst_QSqlQuery::task_233829()

View File

@ -3738,8 +3738,6 @@ void tst_QGraphicsScene::changedSignal()
QCoreApplication::processEvents();
QCOMPARE(cl.changes.size(), 2);
QCOMPARE(cl.changes.at(1).size(), 2);
QCOMPARE(cl.changes.at(1).first(), QRectF(0, 0, 10, 10));
QCOMPARE(cl.changes.at(1).last(), QRectF(20, 0, 10, 10));
QCOMPARE(scene.sceneRect(), QRectF(0, 0, 30, 10));
}