The code was already partially behind the feature flag, but not fully.
Pick-to: 6.9 6.8
Fixes: QTBUG-135693
Change-Id: Iad76221837aa37b90b3be998afc41ce9bbc05c55
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
The instantiated file engine handlers inherit from the private
QAbstractFileEngineHandler class, instantiation means also registration
(~RAII) for Qt file engine classes. This may not be obvious, so
perhaps a clarifying comment is welcome.
Change-Id: Ie8793060a62559e7550d4f808dec947fd5f09ca7
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Don't check for current primary screen available geometry as that value
might not have been set (invokeMethod() is used for that) from a
previous call. Also, in any case, handleLayoutSizeChanged() is only ever
called when the root layout size has really changed.
Amends 0f2c6450201bfa1e612175cddf7481ab72eb4620.
Fixes: QTBUG-133456
Change-Id: I3219529d0f18d4cfc8a9d0eca7573de57ae9e43d
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
Those values should be under the plaftoform screen as they are now, and
handling them also here is just duplication that's not needed.
Change-Id: Ib6be6655527aa86403173d477d137b92d8e51987
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
The screen size doens't need to be updated each time the layout size is
changed, they don't always happen together. The screen size change
happens less often than the layout/available size. Thus, do handle only
layout change under setDisplayMetrics() and move screen size changes to
onDisplayChanged() callback where it logically belongs.
Along the way rename setDisplayMetrics() to handleLayoutSizeChanged()
to reflect what it actually does now after the cleanups.
Task-number: QTBUG-132720
Change-Id: I9dfcfe4a0d2c0be36fb0a5fbf5975c7d466ddef2
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
Those values are only used to calculate the final value for the screen
size, which means we can simply do the calculation first and pass the
final values anyway and avoid carrying those params and making things
harder to read, and since those values are tied to the screen, we can
deffer calculating the physical size to the screen itself.
Dpi values are at least DisplayMetrics.DENSITY_LOW, if the xdpi/ydpi
returned metrics values are below that.
Task-number: QTBUG-132720
Change-Id: Idd6a4db24a460aeb66e626cd93d52b87566ce69c
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
The default screen size and physical size are not needed, since
QAndroidPlatformScreen constructor calculates that shortly after we
assign it a default value. As for the default available geometry,
we need to keep that, but we can move that to live directly under
QAndroidPlatformScreen class, with that we can reduce the chained
calls from androidjnimain.cpp to the platform integration to the
platform screen.
Task-number: QTBUG-132720
Change-Id: Icd2db91ab36a68cd53c3dfb702f41f6b519e476b
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Instead of doing it every time under setDisplayMetrics().
Task-number: QTBUG-132716
Change-Id: I0887c086d7f653b0170e107a86cb0115582bbc89
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
This value is used by nothing throughout the Qt Android code.
Task-number: QTBUG-132716
Change-Id: I694d016131b7eccd9ea5789e77f0501676a7f21a
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
Those two params are already marked as unused, so there's no point in
calculating them passing them and then not using them.
Task-number: QTBUG-132716
Change-Id: I840473a42ac4256164252df805b52b859d2fa3de
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
In Quick for Android case, if Qt exits itself (Qt.exit() in QML, etc),
we get deadlock in startQtApplication after the user-provided main()
exits.
This is due to terminateQt waiting for a semaphore that - in a normal
Q4A context - is called when the hosting Activity itself is destroyed
from another thread via an activity status callback.
Task-number: QTBUG-130342
Change-Id: I9cd701e0ea86a445e13a6568c4954de6e356e98a
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
When quitting Qt, only quit the hosting Activity or Service if it's
primarily a Qt app, i.e. Qt is in the driver's seat. When using QtQuick
for Android, i.e. Qt is just a View, we do not want to forcefully quit
Activities, that is up to the app code.
Task-number: QTBUG-123711
Pick-to: 6.8 6.9
Change-Id: Ib98700be8693c3d30a296998b863b0f224c9bf69
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Currently, we create references to Java classes and objects
in JNI_OnLoad. However, that is done only once, when the
Android QPA plugin is loaded, and in case we would like to stop
Qt entirely and then start it again, we want
to reinitialize all these things. Move these initializations to
a separate method, and call it before starting the Qt runtime and
app.
Remove the synchronization block guarder by m_mainActivityMutex
in QtNative.startApplication(), as it calls startQtAndroidPlugin()
which now will call activity() if the JNI needs to be
reinitialized, leading to a deadlock as that method is guarded
with the same object.
Task-number: QTBUG-130610
Pick-to: 6.8 6.9
Change-Id: I826dfb9b032a6c615f2408d484d1f4f0ea528d02
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
Keep refresh rate calculation and handling in one place and one method
that various delegates call with a context. Also, don't try to update
the refresh rate each time with setDisplayMetrics() beacuse refresh rate
updates are done under the display listener's onDisplayChanged().
Task-number: QTBUG-132716
Change-Id: I689c7a1c350695c27efc6d1bcc9c159855736e43
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Move calls for handling system UI visibility to QAndroidPlatformWindow
where they belongs.
Change-Id: I3802cf9d205ee6678f71b787c5ea4804d3aaeb29
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
That method is related to window management so move it to
QtWindow where it belongs, and any related C++ code from
androidjnimain.cpp to QAndroidPlatformWindow.
Rename the method to updateWindows since it's operating on all
windows and not one window.
Change-Id: I91e729b0749b6a8168b7126f9140d79c542b23d3
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This enables applications to retranslate or otherwise update their UI
when the Android system locale/language settings are changed during
their runtime.
Pick-to: 6.8
Change-Id: Id482ca146080d9f3e74990f64e686f6b3504887c
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Similar to other Android file engine handlers.
Pick-to: 6.8
Change-Id: I63591e09312e439eee1e7bdd71a65d3df4cefbae
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
Android 6 and above produces uncompressed native libraries that
are only part of the APK by default. However, Qt had this behavior
explicitly disabled via packagingOptions.jniLibs.useLegacyPackaging
Gradle flag (previously extractNativeLibs manifest flag) because
we didn't support loading libraries directly from the APK.
This patch adds support for reading and loading shared libraries
directly from the APK without having them extracted to disk. Enabling
this might increase slightly the total size of produced APKs, but
saves on disk space after installation and also on update sizes from
the Play Store and slightly faster startups [1][2].
Loading libraries on the Java side is handled by System.loadLibrary().
On C++, dlopen(3) can directly handle library paths relative to the
APK file [3] which would save us the need to add custom code that calls
android_dlopen_ext() [4] which works with compressed libraries then
using AssetFileDescriptor and having to manage its file descriptor
manually.
To ensure proper integration with various Qt APIs and modules, this
adds a QAbstractFileEngine/Iterator implementations to allow reading
and listing APK files. Since, the files are expected to not change,
they are cached once at startup and re-used thereafter. The engine
implementation allows reading the libraries content using Android's
AssetManager. Also, it allows mapping the libraries directly to
memory to allow proper integration with QPluginLoader.
For plugins, the native libs dir inside the APK is added to Qt and
QML plugins search paths.
With this patch, both compressed and uncompressed libs should work,
to ensure this, an auto test is added with 'useLegacyPackaging true'
to make sure both scenarios still works.
[ChangeLog][Android] Add support for uncompressed native libraries
within APKs.
[1] https://android-developers.googleblog.com/2016/07/improvements-for-
smaller-app-downloads.html
[2] https://developer.android.com/guide/topics/manifest/application-
element#extractNativeLibs
[3] https://android.googlesource.com/platform/bionic/+/master/android-
changes-for-ndk-developers.md#Opening-shared-libraries-directly-from-an-
APK
[4] https://developer.android.com/ndk/reference/group/
libdl#android_dlopen_ext
Fixes: QTBUG-61072
Fixes: QTBUG-97650
Change-Id: Ica6c4cc9e5bd8f3610829b76b64bf599339435d9
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
These classes used to be a part of QtDeclarative and are being moved
to QtCore based on API reviews.
Pick-to: 6.8
Task-number: QTBUG-126976
Task-number: QTBUG-126977
Change-Id: Ic269f23ca2292031cda62faf41428667889537d0
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Since the new functionality interface feature has removed all calls to
qtActivityDelegate, this is no longer needed.
Task-number: QTBUG-118874
Change-Id: Ibf65f953be8c4694b543610b405b65b91f3ec9ee
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Interface for input-related actions, based off of QtInputDelegate.
Implements all the QtInputDelegate functions called from native code
plus an extra function that allows the native side to get a
QtInputConnectionListener object for QtWindow creation.
Removed some unused functions and unmarked @UsedFromNativeCode in some
that are no longer called from native, but still used from java.
Added QtInputConnectionListener null checks in QtInputConnection, due
to the possibility of a non-existent InputInterface returning a null
QtInputConnectionListener for the QtInputConnection constructor.
Task-number: QTBUG-118874
Change-Id: I8d4cde3e0c735471d0fa30d16db20eb13542cdaa
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
This will provide the JNI API used by QtAndroidAccessibility namespace
via QtAndroid namespace.
Removed unnecessary functions like createAccessibilityDelegate from
QtEmbeddedDelegate, moved the interface extension to where it is
actually supported: QtActivityDelegate.
Until now, QtActivityDelegateBase has called the QtEmbeddedDelegate
implementation on createAccessibilityDelegate() in order to create a
QtAccessibilityDelegate - which has not actually created the delegate -
and then done a null check before trying to call the - always null -
QtAccessibilityDelegate member.
The embedding and service-embedding usecases are now dealt with via the
interface validity checks on the C++ side, until an actual
implementation for those is completed.
Task-number: QTBUG-118874
Change-Id: Iea3db0e17ae80c0443e9027bdfe36bba311eed2b
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Add QtWindowInterface interface, to access native functionality related
to windows.
QtActivityBase now follows QtNative.onAppStateDetailsChanged in order
to register and unregister functionalities of QtActivityDelegate.
Task-number: QTBUG-118874
Change-Id: Ifad33bd7aac7683081f026f0591ef496909be095
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This class will be used by java delegates to register their supported
functionalities to the Qt/C++ side.
It registers two native functions: register- and
unregisterBackend, which will be used by the aforementioned
delegates.
It will be used by C++ classes which currently use
QtAndroid::qtActivityDelegate() to access a JNI object which implements
all these features in one big class.
Task-number: QTBUG-118874
Change-Id: I23a7e433104c20b96c08b682a96cfaec98ecb4a9
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
When embedding QML into an Android service, Qt is not actually running
as a service. Avoid checking for QtAndroid::Service() and assuming that
means we are running as a service.
Task-number: QTBUG-118874
Change-Id: I5eea32b9fc200c4f34f1507d591aa1a483849118
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Sending an ObjectShow event, e.g. by setting QQuickItem::visible to
true, has to trigger a refresh of the screen reader hierarchy. If the
signal is ignored the source of the signal will be ignored by the
screen reader.
Fixes: QTBUG-122436
Pick-to: 6.5 6.7
Change-Id: I32ee2e8b2602cd0dd9b9a83ff1fe426d88d137a8
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
The current QStyleHintsPrivate::setColorScheme is called when the system
theme changes, handling the change and informing the application. It is
not a setter. When we add a public setter, that setter will have to go
through the QPlatformTheme to request an override for the application.
That will then result in a call back to the QStyleHints to update the
theme with the effective color scheme (or ignore the request for the
override, on some platforms).
Rename it (and similar misleading APIs in platform plugins) to
updateColorScheme, and adjust outdated comments in some of the platform
plugins.
Task-number: QTBUG-124490
Change-Id: I6a852211254993df86acf2e2d42cf345e7401f4f
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Doris Verria <doris.verria@qt.io>
Add classes that make it possible to add QML as a View into
a native Android app:
QtView: Base class for QtQuickView, handles non-Quick dependent
operations. In essence a Java ViewGroup class which loads a
QWindow and embeds it into itself.
QtEmbeddedLoader: Extends QtLoader for embedded case, creates the
embedded version of QtActivityDelegate and provides an embedded-specific
path to loading Qt libraries (Mostly just allows users to set the name
of the main lib)
QtAndroidWindowEmbedding namespace: Deals with calls from
QtEmbeddedDelegate to create/destroy QWindow and from QtView to
show the window.
Take the QtEmbeddedDelegate introduced in an earlier commit
into use, and add functionality for loading QWindows for
QtViews and managing QtViews into it.
Add a factory for creating instances of QtEmbeddedDelegate.
The factory holds a map of QtEmbeddedDelegate objects and
creates them, with the Activity as the key. This is to make
it so that the same delegate can be used by multiple views
which share the same Context.
Known issues left:
* keyboard focus not working, as with other child windows
Pick-to: 6.7
Task-number: QTBUG-118872
Change-Id: I94a5f9b4f904c05cc6368cf20f273fcf10d31f17
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
When we are embedding a QML view to a non-Qt Android app, there are a lot
of functionalities that are shared with the refular Qt Android app, but
some are not. We should not, for example, try to control the hosting
Activity.
Create a base class that both the QtActivityDelegate, used for the
standard Qt for Android app, and the delegate for the embedding case
can extend.
In this commit, the QtEmbeddedDelegate is very simple, the
biggest difference to QtActivityDelegate being it does not create
a QtLayout or instantiate a QtAccessibilityDelegate.
It does start the Qt app, without waiting for a layout, and register
to listen for changes in the state of the Qt app.
Taking the embedded delegate into use, loading the embedded QML
views and their handling is added in a follow up commit.
Task-number: QTBUG-118872
Pick-to: 6.7
Change-Id: Id390a2b35c70b35880523886bf6fcf59d420cb42
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Add a helper method to tell whether the app is a standalone Qt for
Android app, where also the Context is created by Qt, or whether Qt
content is embedded as a View into a Context created by the user, i.e.
a "native" Android app.
Pick-to: 6.7
Change-Id: I618ba1c8cb40c9b132fc12a7ee6d54c071efa983
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
In the touch dispatcher methods, all events were routed for the
top level window at the position, which lead to all the events
being delivered for the parent window.
Since the JNI methods already have a parameter for window ID, take
that into use and determine the window to deliver the events to
by ID.
Pick-to: 6.7
Change-Id: I07ad7851c32a3e633ee748036d6818b6d0fa5588
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Each QAndroidPlatformWindow has its own QtLayout,
instead of one for the whole app/screen. This paves the
way for addition of child windows.
Task-number: QTBUG-116187
Change-Id: I36c68cea1a5f27ded3696bcfc2fbc04d9a8ce79e
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Refactored platform windows on Android so that all window
types, including raster windows, have their own surface to
draw on.
Raster windows now flush the backing-store via RHI/OpenGL.
As a drive by, update to newer JNI syntax where appropriate.
Task-number: QTBUG-116187
Change-Id: I3b764b7126abf53556750b0ccbb7d27efe007bc1
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
First, replace double quote characters with 3 escaped double quotes
to allow QProcess::splitCommand() to treat it as an actual quote
character that's part of the tag.
Then, escape single quote characters so they don't interfere with
the shell command and also to be treated as part of the argument.
Lastly, surround the args with escaped double quote so that args
with spaces are also treated as one.
Amends b044323c1656aeeec508afab8457755cc1e8c587.
Example of this:
tst_qkeyevent::modifiers("M","e","t","a") for double quotes
tst_qunicodetools::wordBreakClass(two words) for spaces
tst_QSpinBox::stepSelectAll("don't select all") for single quotes
Task-number: QTQAINFRA-5703
Change-Id: Ie4317e4350bbac619bac41e41f42613f50cf1ad4
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This has two parts, under testrunner, make sure to pass test args
that has quotes as \\\" so that the Android app gets a \" after parsing
the intent extras. The app args are then is passed to C++ where
QProcess::splitCommand() is used to parse the args string into a list,
and to preserve the quotes in this case, the former call expects triple
quotes to to get the quote character preserved in the split list.
Fixes: QTQAINFRA-5703
Change-Id: Iad81cadf24a6def21ef1536c882ecd510c4426cf
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This has been used to notify that the platform integration is
setup and ready, now the name is more descriptive of what it does.
Task-number: QTBUG-118077
Change-Id: I9fab525f07433f9ec8057e2475a3b1e4658f84d9
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
... and print it always after main() returns.
Task-number: QTBUG-118077
Change-Id: I1f57b3f7a646d01eebf67d4a4ff6a8d9f6e82cc7
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
Method is trying to infer the signature from the types of the
arguments, but since the argument for the view is a plain jobject
this signature is wrong, method is not found and the view is never
inserted.
Change-Id: I3cbf9bccbcb1e5526f843213ba0f66e5bd1e7107
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
The delegate classes shouldn't be used outside of the Activity/Service
classes, since they're practically private implementation, so don't use
them anywhere outside Activity/Service.
Since Qt Android apps still mainly support having one QtActivity/
QtService, QtNative heavily uses those objects to do various operations.
For that reason, we still need to use the delegate there. The aim is
to change that in future patches and do the operations where they make
more sense for example directly under QtActivityBase/QtActivityDelegate
or Service counterpart.
The QtServiceDelegate is used no where and have no special
implementation, so it's removed here.
Task-number: QTBUG-118077
Change-Id: I5e106318169be19fec8163e8e500ee573af0e1bc
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Remove yet another two layers of delegation, QtNative calling
QtActivityDelegate and that in turn calls QtAccessibilityDelegate.
Now from c++ native code, acquire the a11y delegate and use it to
call a11y operations that live in QtAccessibilityDelegate.
Task-number: QTBUG-118077
Change-Id: I9e84520c2caa281a6f786a687b0106d702f92a67
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
Have all or most of Android code dealing with displays in
QtDisplayManager. Also, simplify setApplicationDisplayMetrics()
call and avoid caching any uneccessary members.
Task-number: QTBUG-118077
Change-Id: I943069c24bb40ae3016db5896e553b501e700a6b
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
Emit log output and return false immediately if we fail to get both the
Activity and the Service objects. Standardize the registerNative methods
to return bool and take a QJniEnvironment, and adjust the macros
accordingly.
Simplify the startup routine to use QJniEnvironment.
Change-Id: I11be35426520dc803f5a07bbb495e908592f254e
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
Move all clipboard management logic outside of QtNative and
to own QtClipboardManager class. Also, don't keep any keep
Activity objects under it to avoid memory leaks, the native
c++ clipboard manager should be responsible of passing a
context when needed instead.
As a pass-by, use newer JNI APIs for C++ QtAndroidClipboard
code.
Task-number: QTBUG-118077
Change-Id: I61726e84a75918d80329f753e9e1c6ebde179bf4
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
The operator jobject() should be removed from declared QtJniTypes in
qtbase, as it's dangerous. Prepare for that by calling object(), which
returns the wrapped jobject as well, or isValid() where previously the
implicit conversion to jobject also enabled implicit conversion to bool.
Change-Id: I00cf6f1463dd5ab5cbaf03d9e77bfff3bced9b15
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
There's no need for both, and QtAndroidPrivate is a documented namespace.
Replace all calls to QtAndroid::activity/service with QtAndroidPrivate
equivalents, and drop the QtAndroid version. Since we no longer store a
global copy of the activity and service, we can drop the reference right
away.
This comes with a bit of overhead - QtAndroid::activity returned a copy
of a global static QJniObject (62cb5589b3723fe8162e190cd54d9c78929b98d2,
after which declared QtJniTypes became QJniObjects), while
QtAndroidPrivate::activity returns a newly created QtJniTypes::Activity
on each call.
This however makes it also safer, as the QJniObject is then associated
with the calling thread's JNI environment, and we can optimize critical
code paths where it's safe to do so later. Also, QtAndroid's activity
object was never updated, while QtAndroidPrivate's activity is updated
in the updateNativeActivity native method.
Change-Id: I36c5b504eac52d9e28b4c6b265daab8fedc877e2
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
To further simplify the code and logic of the delegate, move keyboard
input code to separate class. Make an input delegate available under the
QtActivityDelegate to allow classes like QtNative and the Activity to
access that. For now, it's okay to leave access from QtNative to that,
but for future even that should be simplified and the Activity should be
accessing that directly.
For the case where the QtInputDelegate needs access to
QtActivityDelegate, for now namely updateFullScreen(), a new Listener
is implemented to be implemented under QtActivityDelegate.
Along the way use newer JNI APIs under C++ QtAndroidInput.
Don't make them static methods, so that it can be possible later to
do various keyboard operations to specific activity and not a global
one.
Task-number: QTBUG-114593
Task-number: QTBUG-118077
Change-Id: I110b897f6f16d0ae5f5a645551b4a82e8ad3f2fb
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>