QFuture::takeResult() currently returns std::vector instead of QList,
because QList does not support move-only types. Disable this method
until QList is fixed to work with move-only types in Qt 6.1.
Also did minor doc-fixes.
Change-Id: I87feaf75d9433a3b540edd00039c3e21d6994985
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
As propertyobservers can execute arbitrarily complex code, they can also
modify the obsever list in multiple ways. To protect against list
corruption resulting from this, we introduce a protection scheme which
makes the list resilient against modification.
A detailed description of the scheme can be found as a comment in
QPropertyObserverPointer::notify.
Task-number: QTBUG-87153
Change-Id: I9bb49e457165ddc1e4c8bbdf3d3c9fbf5ff27e94
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Implement the better rounding mechanism that was previously blocked
by requiring C++14 to be constexpr.
Change-Id: I4e5b179ce0703f5c0b41c3f0ea00d28dfe53740c
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
The original restriction to UniformBuffer was due to the GL backend
where there is no GL buffer object for QRhiBuffers with usage
UniformBuffer. However, we can still implement this for cases when
there is a true GL buffer object underneath. With other backends it
should all work as-is already.
This becomes useful when one has buffers with usage Vertex that need
full updates every frame. (f.ex. instance data)
Unfortunately this involves renaming the function. But while at it, add
an autotest case as well.
Change-Id: Iff59e4509a8bae06654cc92fe8428bd79eb012fb
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
The qsb files seem to be out of date for those two.
Change-Id: Id832e872667cac4d364e13c440011109a6dbdc7f
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Draw 25000 cubes while doing a uniform buffer update for each.
Change-Id: I2216641c8bf7c6ea147fe3edd679317b472e1f04
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Pending results were never cleared by result store. This led to memory
leaks when the results never transitioned to "visible" results
Change-Id: I674302eb51542ad5f4d918da68d616428c73ae9f
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
It was previously casting enum values to int, which produced unhelpful
answers when a test failed. Better to have them as enum values that
get printed as their names, which are actually informative.
Change-Id: I1bf2971b1426bdbbc321bb48f45ee3e5799e76ec
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
QDateTime's addDays(), addMonths() and addYears() neglected to check
for validity before doing their job, with the result that they could
produce "valid" (but wildly inappropriate) results if used on an
invalid date-time. Added tests for this case (and the boundary).
Change-Id: I7b0d638501cb5d875a678cde213547a83ed7529e
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
QDateTime's range of possible values is wider than anyone generally
needs, but let's not do confusing things when someone does overflow
it.
Change-Id: Ifbaf7a0f02cd3afe7d3d13c829bf0887eba29f7f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Previously, a QDate representing more than about 0.3 gigayears before
or after the epoch would overflow the millisecond count and produce a
"valid" date-time that didn't represent the date and time passed to
its constructor. Changed to detect such overflow and produce an
invalid date-time instead, if it happens.
Corrected some tests that wrongly expected to be able to represent
extreme date-time values with every time-spec. The (milli)seconds
since epoch are from UTC's epoch, so converting to another offset,
zone or local time may give a value outside the actual range. Added
some tests for the actual exact bounds.
Task-number: QTBUG-68855
Change-Id: I866a4974aeb54bba92dbe7eab0a440baf02124f0
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Also correct two comments which lied about the year being tested.
Change-Id: I5be491a2b2c1e0c3b49d6ff9a8de852e17321cff
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
As suggested by the message from QTestLib. This, indeed, fixed the
sadistic test. Also, make sure resources are not leaked.
Pick-to: 5.15
Fixes: QTBUG-87009
Change-Id: Id693a5a562ea5ebacc853e5fc0ab9654ba851e72
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Currently
A a;
QVariant::fromValue(&a).value<const A*>() == nullptr;
Still casting non const to const is safe, and worked in Qt5.
After this change
A a;
QVariant::fromValue(&a).value<const A*>() == &a;
Change-Id: I257049d084c712b00a338a2943d379aa478e0981
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Change types returned and accepted by capacity-related QArrayDataPointer
functions to qsizetype:
1) QArrayData (underlying d-ptr) works with qsizetype
2) QArrayDataPointer::size is of type qsizetype
3) All higher level classes that use QADP (e.g. containers)
cast capacity to qsizetype in their methods
Additionally, fixed newly appeared warnings through qtbase
Change-Id: I899408decfbf2ce9d527be7e8b7f6382875148fc
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This time based on grepping to also include documentation, tests and
examples previously missed by the automatic tool.
Change-Id: Ied1703f4bcc470fbc275f759ed5b7c588a5c4e9f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Unit tests are added to make sure QtConcurrent works on
move-only sequences.
Change-Id: I1d066f75ceab9cef98832e96c5827103cbfd72a8
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Even before adding support for fractional hours, a fraction of a
minute might potentially have represented a whole number of seconds by
a fractional part that, due to rounding, was less than the whole
number of seconds by less than half a millisecond. Previously, the
parsing would have clipped the fractional part at 999 milliseconds, in
the preceding second, instead of correctly rounding it up to the whole
second.
For QTime::fromString(), which can't represent 24:00, and for
TextDate, which doesn't allow 24:00 as a synomym for the next day's
0:0, applying such rounding to 23:59:59.999999 would produce an
invalid result from a string that does represent a valid time, so use
the nearest representable time, as previously.
Added some tests and amended others.
[ChangeLog][QtCore][QDateTime] QDateTime and QTime, in fromString()
with format ISODate or TextDate, now allow a fractional part of the
hour, minute or seconds to round up to the next second (hence
potentially into the next minute, etc.) when this is the closest
representable value to the exact fractional part given. When rounding
up would turn a valid result into an invalid one, however, the old
behavior of clipping to 999 milliseconds is retained.
Change-Id: I8104848d246cdb4545a12819fb4b6755da2b1372
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Andreas Buhr <andreas.buhr@qt.io>
Previously we used 0:0 on the next day, which might fall in a
fall-back's gap.
[ChangeLog][QtCore][QDateTime] When fromString() reads 24:00 in ISO
format, it now uses the start of the next day, rather than 0:0 on the
next day. This only makes a difference if the next day's first hour is
skipped by a time-zone transition.
Change-Id: Ib81feca5dc09fa735321b6ab76d5d118d6db6fd2
Reviewed-by: Andreas Buhr <andreas.buhr@qt.io>
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
We were already using the 'native' nomenclature when referring to these
kinds of APIs, e.g. when talking about native handles, or the existing
QPlatformNativeInterface on a QPA level. Using 'native' for the user
facing APIs also distinguishes them from the 'platform' backend layer
in QPA and elsewhere.
Change-Id: I0f3273265904f0f19c0b6d62471f8820d3c3232e
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Try to get rid of APIs that use raw 'const {char, QChar} *, length'
pairs. Instead, use QByteArrayView or QStringView.
As QStringConverter is a new class, simply change the API to what we'd like
to have. Also adjust hidden API in QStringBuilder and friends.
Change-Id: I897d47f63a7b965f5574a1e51da64147f9e981f6
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Introduce a bunch of helper functions to manipulate compiler
flags and linker flags for the
CMAKE_<LANG>_FLAGS_<CONFIG>
and
CMAKE_<LINK_TYPE>_LINKER_FLAGS_<CONFIG>
CMake variables.
These variables can be assigned and modified either in the cache
or for a specific subdirectory scope, which will apply the flags
only to targets in that scope.
Add qt_internal_add_optimize_full_flags() function which mimics
qmake's CONFIG += optimize_full behavior.
Calling it will force usage of the '-O3' optimization flag on supported
platforms (falling back '-O2' where not supported).
Use the function for the Core and Gui subdirectories, to enable full
optimization for the respective Qt modules as it is done in the qmake
projects.
To ensure that the global qmake-like compiler flags are assigned
eveywhere,
qt_internal_set_up_config_optimizations_like_in_qmake() needs
to be called after Qt global features like optimize_size and
optimize_full are available.
This means that qtbase and its standalone tests need some special
handling in regards to when to call that function.
Task-number: QTBUG-86866
Change-Id: Ic7ac23de0265561cb06a0ba55089b6c0d3347441
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
QUrl hostnames must be compliant with STD3, but we must somehow accept
file paths that begin with double slash but aren't valid hostnames.
Because the file URI spec requires us to start with "file://" anyway, we
can represent those with four slashes. Note that on Unix "//X/y" is a
valid but local file path. If given to QUrl::fromLocalFile(), if the
path at the root does parse as a hostname, we will still try to
normalize (the above becomes "file://x/y").
[ChangeLog][QtCore][QUrl] Changed QUrl::fromLocalFile() to accept
Windows UNC paths whose hostname component is not a valid Internet
hostname. This makes QUrl able to accept extended-length paths (\\?\),
device namespace (\\.\), WSL (\\wsl$), etc.
Pick-to: 5.15
Fixes: QTBUG-86277
Change-Id: I3eb349b832c14610895efffd1635759348214a3b
Reviewed-by: David Faure <david.faure@kdab.com>
No change in testing, juts changed names and order.
Pick-to: 5.15
Change-Id: I3eb349b832c14610895efffd16357498454bcd52
Reviewed-by: David Faure <david.faure@kdab.com>
Also add the very same operators to the QBasicUtf8StringView
class to overcome the compiler issues seen on gcc.
Fixes: QTBUG-86481
Change-Id: I12484455ebd3b7b38d4ad67c38977d76f9b3ddfa
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
In tst_QDateTimeEdit::dateEditCorrectSectionSize(), only the final
displayed date was tested; many of the tests checked day of week (by
name), which might well match despite actually selecting a different
date than the one intended. So test the date is as expected, too.
In the process, tidy up the code, give values more informative names,
turn a trivial static function into a lambda.
Change-Id: I0491159e9ee2f3cfdcf8a194c723be92c190c2a8
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Also adjust the QString constructor from QByteArray to ignore
\0 characters in the string (and not terminate conversion there).
[ChangeLog][QtCore][QString] Constructing a QString from a QByteArray
will not stop at intermediate '\0' (null) characters in the string as
in Qt 5, but will convert all characters in the byte array.
Change-Id: I1f6bfefe76dfa9072b165903fec7aa4af1abd882
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Fix remaining places that still exercised it.
Task-number: QTBUG-85700
Change-Id: I84562f53439197141343831c0b9f88983689e6bf
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Previously the ISO time format would tolerate trailing cruft at the
end in various cases even though there might be an offset specifier
after the time, which should *not* be separated from it by anything
(not even the spaces we originally planned to still tolerate).
The RFC date format is forgiving about space, as is suitable for
parsing of RFC-822 headers, but the other formats should match the
handling in QDateTimeParser, which rejects any dangling cruft.
At the same time, since this required a re-write of
fromIsoTimeString() in any case, add support for the ISO format that
gives the hour a fractional part and skips minutes and
seconds. Previously we only had support for fractional minutes (with
no seconds). The hour without even a fractional part is also valid.
Reworked the documentation of Qt::DateFormat as it was wrong in
places, inconsistent in its formatting and incomplete. Adjusted some
tests to match the new behavior. A fraction separator with no
following digits should have been recognized as an error previously
and now is.
[ChangeLog][QtCore][QDateTime] The ISODate and ISODateWithMs formats
now reject trailing cruft (including spaces) at the end of a time
string. They also gain support for parsing hour-only formats,
including the hour-with-fractional-part format.
Task-number: QTBUG-86133
Change-Id: I38ad1479ae033407f7df97ffbeb7c4bcd463d04a
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
The name toSecsSinceEpoch() gave no hint to the fact that the test
was, in fact, *also* testing round-tripping of the ISODateFormat.
Since there are other tests for string conversion, make this a simple
test of toSecsSinceEpoch().
It did the round-tripping via two methods with overly-terse names that
might just as well be local lambdas - now redundant, so removed.
Change-Id: I1e4fb1cc90224312c995596a8f3fe2bc5d9dfa15
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
During delivery of a TouchBegin event, if no widget accepts it,
we begin treating the first touchpoint as a synth-mouse, as before.
If a second touchpoint is pressed or released in any order, it's
irrelevant: the fake mouse button is released as soon as the first
touchpoint is released. This fixes the bug that such a scenario
caused the mouse release not to be sent, so that a widget could get
"stuck" in pressed state.
Done-with: Tang Haixiang <tanghaixiang@uniontech.com>
Fixes: QTBUG-86253
Pick-to: 5.15
Change-Id: I7fbbe120539d8ded8ef5e7cf712a27bd69391e02
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
QAbstractItemModel::canFetchMore and fetchMore implementations might only
add a few rows to the model each time they are called. The item views don't
generally expect that, and don't call fetchMore repeatedly, even if there
would be room in the itemview for more data. This problem cannot be
generally solved for all item views, as it would require in repeated expensive
laying out of items.
For nested indexes in a treeview however, we can try to fetch enough child
rows to populate the screen when the item is laid out by repeatedly
calling canFetchMore and fetchMore. To calculate how many items have space,
apply the same heuristics as in the scrollContentsBy implementation to
guess the number of items that can fit into the viewport.
Created test case for the fix.
Done-with: Doris Verria <doris.verria@qt.io>
Fixes: QTBUG-85366
Pick-to: 5.15
Change-Id: I54f95552993873dd4cba80b0f70f4db9d98ddc1d
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reports on the Web have it that there's nothing guaranteeing a
driver does any actual freeing of resources then doing
vkFreeCommandBuffer for a command buffer from a command pool that
does not have VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, thus
leading to continuously growing resource usage with our current
allocate/free pattern. It could be that this is the source of out
of memory problems we are seeing on some Android devices.
Instead of just going straight for said command pool flag and doing
ResetCommandBuffer for the command buffers individually, take one
step further and use per-slot (slot being 0 or 1 if QVK_FRAMES_IN_FLIGHT
is 2) command pools. The current pool is reset in each
beginFrame/beginOffscreenFrame, moving all allocated command buffers
to the initial state (while other command buffers with the other pool
are not affected).
This may be (while impossible to tell from just guessing based on the
spec) our best approach to command buffer allocation since a Vulkan
implementation can likely just use some simple per pool allocator,
knowing that we never want to free or reset individual command buffers,
but we rather only reset the whole pool at once.
The option of importing an existing VkCommandPool when creating the
QRhi instance is now gone, but there was probably no point in offering
that in the first place.
When it comes to VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT it will
not be set unless releaseCachedResources() (in Qt Quick this is hooked
into QQuickWindow::releaseResources()) was called. What this does in
practice is unknown, but have an option to set it now and then if the
application really wants.
While we are at it, rename secondaryCbs to activeSecondaryCbStack to
indicate what it really is. (it's a stack as each call to
beginExternal() pushes a new one, while each endExternal() pops)
Change-Id: I2e5c1fad26d794e1f56c778e38f750998d706d84
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
ExternalContentsInPass becomes a per-pass flag now. Why is this
beneficial? Because while Qt Quick has no choice for its render
pass, not being able to guess if the application wants to do some
native rendering in there, Quick 3D's render passes, all the ones
that are under Quick3D's control, do not have native rendering
from the application in them, and so using secondary command
buffers with Vulkan is not necessary.
Introduce something similar for compute and OpenGL. By knowing that
none of the resources used in a pass are used with a compute pass
(e.g. because we know that there are no compute passes at all) a small
amount of time can be saved by skipping tracking buffers and textures
because the only purpose of said tracking is to generate barriers that
are relevant only to compute.
Change-Id: I0eceb4774d87803c73a39db527f5707a9f4d75c1
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Also drop superfluous trailing 0s from QTime's constructor and add
space after commas.
Change-Id: Ie3ae87fd497456d6447c55e5d2c808ef59c9768d
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Andreas Buhr <andreas.buhr@qt.io>
Add some missing versionless functions.
Rename some functions that are not meant to be public API, and their
usages.
Task-number: QTBUG-86827
Change-Id: Ifb66c04cd7598d83fe80c01a92ab2d269ebaf396
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Since we drop the lock while deleting threads, we need to handle
the queue possibly being accessed and changed by the pool threads
while clear() is running.
Pick-to: 5.15
Fixes: QTBUG-87092
Change-Id: I7611edab90520454278502a58621e299f9cd1f6e
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Address an old ### Qt 5 comment. The method has been documented as deprecated
and replaced by QProcess::processId since at least Qt 5.9, so we can first
properly flag it as such for 5.15.2, and remove it from Qt 6 in a follow-up
commit.
Change-Id: Ic4e3351740617083b16723db8eef7a341bccfbf6
Pick-to: 5.15
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
It also demonstrated that the tests were out of sync with reality:
since a97759a336c597327cb82eebc9f45c793aec32c9 QMouseEvent::button()
and QWindowSystemInterfacePrivate::MouseEvent::button should be the
button that changes state of course; but when a button is pressed,
we are reacting to it after the fact, so QMouseEvent::buttons() and
QWindowSystemInterfacePrivate::MouseEvent::buttons should include the
new button that was just pressed. Likewise when a button was released,
we send the event with buttons _omitting_ the button that was just
released.
Amends 147a8bc4c8 and
6d6ed64d6c
Change-Id: I670289019fcfa7de685ca38799804772dc0f1c8f
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Add begin()/end() on QRegularExpressionMatchIterator, making
iterators over an iterator (like directory_iterator).
[ChangeLog][QtCore][QRegularExpression] The iterator object
(QRegularExpressionMatchIterator) returned by a global match
is now usable in a range-based for loop.
Change-Id: If3d31bd2e84e7d1fb626a0b3d2745914dff03e39
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Use a QScopeGuard to fix its restoration of left-to-right mode after completion.
Change-Id: I5ac1e44629e72d993f2d5ba6586b86508d57cdaf
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Andreas Buhr <andreas.buhr@qt.io>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Use std::hypot() instead of sqrt() of a sum of squares.
This ensures length() can't be zero when isNull() is false.
Use length() in QLine::setLength() rather than duplicating that.
Clarify and expand some documentation; isNull() never said what
constituted validity, nor did unitVector() mention that is should not
be used on a line for which isNull() is true. Make clear that lines of
denormal length cannot be rescaled accurately.
Given that we use fuzzy comparison to determine equality of
end-points, isNull() can be false for a line with displacements less
than sqrt(numeric_limits<qreal>::denorm_min()) between the coordinates
of its end-points (as long as these are not much bigger); squaring
these would give zero, hence a zero length, where using hypot() avoids
the underflow and gives a non-zero length. Having a zero length for a
line with isNull() false would lead to problems in setLength(), which
uses an isNull() pre-test, protecting a call to unitVector().
(It was already possible for a null line to have non-zero length; this
now arises in more cases.)
Restored QLine::setLength() to the form it had before a recent change
to avoid division by zero (which resulted from underflow in computing
the length of a non-null line) but allow for the possibility that the
unit vector it computes as transient may not have length exactly one.
Add tests against {ov,und}erflow problems in QLine. Reworked the test
added during the divide-by-zero fix to make it part of the existing
test.
Pick-to: 5.15 5.12
Change-Id: I7b71d66b872ccc08a64e941acd36b45b0ea15fab
Reviewed-by: Sze Howe Koh <szehowe.koh@gmail.com>
addBFail() asserts on the file being non-null. The convention seems to
be "Unknown File" for cases where we cannot determine the file.
Change-Id: I3a4d0130352d77d75f264fad6f3bd47c6700ef4c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Changed QtConcurrent algorithms to take the passed sequences as
universal references, where it makes sense. In addition to avoiding
to create extra copies when passing rvalues, this change allows
passing temporary container adaptors to QtConcurrent::map (e.g. see
the example in the ticket and the new test-cases).
Task-number: QTBUG-83170
Change-Id: Ia7c0833f4ec1d860294fa5214cd53934b65ff084
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
When the default printer supports a duplex mode other than DuplexAuto,
the unit tests change to QPrinter::PdfFormat and expect that
the pdf printer is in duplex mode then. However, the pdf printer
does not support duplex mode.
This patch removes this check.
Change-Id: If394f9f23fd244713bbb1ecce9d3802cbd281d90
Reviewed-by: Andy Shaw <andy.shaw@qt.io>