aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
Commit message (Collapse)AuthorAgeFilesLines
* Merge "Merge remote-tracking branch 'origin/5.9.3' into 5.9" into ↵Liang Qi2017-11-251-1/+9
|\ | | | | | | refs/staging/5.9
| * Merge remote-tracking branch 'origin/5.9.3' into 5.9Liang Qi2017-11-231-1/+9
| |\ | | | | | | | | | Change-Id: Ic6457df47bed359fd43653e73726f1896944241c
| | * Improve encapsulation of the the IR de-serialization from QtQuick CompilerSimon Hausmann2017-11-121-1/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The code used by QQC to deserialize the IR requires setting the javaScriptCompilationUnit member in order to connect the generated C++ code. Knowledge of the QmlIR::Document data structure layout on the side of the generated code (thus application) has its downsides though (see referenced bug). We can avoid that dependency easily by doing the entire de-serialization on the QtQml library side. The old "API" (load member function) is still around until the qqc change is also in. Task-number: QTBUG-63474 Change-Id: I239838afacc71474c86114b5b05679ff36e4c2e2 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* | | More fine-grained deferred property executionJ-P Nurmi2017-11-254-13/+113
|/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This allows Qt Quick Controls 2 to defer the execution of certain building blocks until needed. For example, a button control can defer its background item so that the default background is not executed at all when replaced by a custom background. First of all, this gives a massive performance boost for customized controls. Secondly, this avoids the most burning issue in QQC2, problems with asynchronous incubation ("Object destroyed during incubation"). Task-number: QTBUG-50992 Change-Id: If3616c9dac70e3a474a20070ad0452874d267164 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* | Don't reject plugin-only qmldir filesUlf Hermann2017-11-221-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | On QQmlImportsPrivate::updateQmldirContent we need to check if the new module has actually been established after figuring out that it doesn't have any components or scripts. If it has, then we shouldn't fail, as obviously a plugin has been loaded. We don't need to check the component and script versions in that case, as plugins don't have separate versions. Change-Id: Ie328b59038fe65c3f6a2eeecfe969927bba6cd68 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* | Fix URL interception for qmldir filesUlf Hermann2017-11-223-17/+59
|/ | | | | | | | | | | | | | | | | We need to intercept the URL when it is created. This relieves us of the need to hack around in it when actually retrieving the content of the qmldir file and prevents the futile attempt to load remote qmldir files via the code path that should load local ones (or vice versa). The back and forth conversion between URLs and strings is unfortunate, but can only be solved by using QUrl rather than QString where we actually mean URL. This would be a bigger change which is unsuitable for 5.9. Mind that nothing changes for code that doesn't use URL interceptors. Task-number: QTBUG-36773 Change-Id: I6bff3ae352009fdc0a17ec209691c7b390367f11 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Prevent the QML engine from registering circular dependenciesErik Verbruggen2017-11-062-1/+10
| | | | | | | | Change-Id: Ic4fd2bde745e7dfaf0909e8cc575441bb04cefa3 Task-number: QTBUG-64017 Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Marco Martin <mart@kde.org> Reviewed-by: Bhushan Shah <bshah@kde.org>
* Fix crash with dangling context object pointersAndy Shaw2017-10-261-0/+2
| | | | | | | | | | | | | This is a regression introduced by commit e22b624d9ab1f36021adb9cdbfa9b37054282bb8, where the object that owns the QML context would destroy the context upon destruction. Now the context may live longer and thus the context->contextObject pointer would become a dangling pointer. Task-number: QTBUG-63733 Change-Id: Idc660116752d312917a0a149110b92a042ccfb17 Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Return "qnx" for Qt.platform.os when appropriateLiang Qi2017-10-242-0/+3
| | | | | | | | | | [ChangeLog][QtQml] Qt.platform.os returns "qnx" when running on QNX platforms. Task-number: QTBUG-52515 Change-Id: Ie46f235248f7832fff12906cf858e8527e8060b1 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
* QQmlTypeLoader: Drain events before shutting down the threadUlf Hermann2017-10-201-10/+17
| | | | | | | | | | We take references to types when sending events to the other thread. If we don't process the events, the references are kept, which leads to memory leaks. Therefore, when shutting down a QML engine, we have to make sure the event queues are emptied. Change-Id: Id8b0440029cfd7d03a9e540747eaedbcaa7c9ff3 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Tell QQmlImportInstance::resolveType what kind of type we wantUlf Hermann2017-10-195-29/+66
| | | | | | | | | | | | | | | | | | | | | | | | | | | In QQmlTypeData::resolveTypes() we know if we're looking at a reference to a composite singleton type, or some other type reference. When we call resolveType() we expect the correct type to be returned, not only based on URL, but also based on its singleton property. QQmlTypeData::resolveType() eventually invokes QQmlImportInstance::resolveType() which will call fetchOrCreateTypeForUrl(), passing a parameter on whether the result should be a composite singleton. When operating on a qmldir component the component itself encodes this. When fetching a type from a local file without qmldir, we currently assume that it isn't a singleton, no matter QQmlTypeData::resolveTypes() has determined. This means that actual singletons loaded this way later get refused by the sanity check. In order to fix this, pass the information about the expected singleton property on to QQmlImportInstance. This is done using QQmlType::RegistrationType, which gets another entry for "any type". If the expected type is CompositeSingletonType QQmlTypeData::resolveType() will not create a non-singleton type. If it is any specific other type, it will not create a composite singleton. And if it is AnyRegistrationType, it will behave as it previously did. Change-Id: I6b7e082b63582e0aed946bb3d19077b94c7a45f7 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Fix execution of deferred propertiesJ-P Nurmi2017-10-186-31/+60
| | | | | | | | | | | When deferred properties were assigned in multiple contexts, only the outermost context was executed. Any deferred property assignments in other inner contexts were never executed. Collect the deferred data to a container to be able to execute them all. Task-number: QTBUG-63200 Change-Id: I88fab27c1f81b5188430ada086dcc19842507e99 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* QQmlTypeLoader: The profiler is a quintptr(0) if QT_NO_QML_DEBUGGINGUlf Hermann2017-09-271-2/+2
| | | | | | | | | | This follows the pattern established in other places. Task-number: QTBUG-63392 Change-Id: I11cd66d5552f751804dd0a9460b26bda546c1726 Reviewed-by: Mikko Gronoff <mikko.gronoff@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Samuli Piippo <samuli.piippo@qt.io>
* Fix behaviors not working when sub-types declare propertiesSimon Hausmann2017-09-221-0/+2
| | | | | | | | | | | | | Since commit 81867dfbf9c16d4300727a08eed9b5c6c979e0ba we have an optimization in place to avoid the virtual meta-call when writing properties that cannot be intercepted. Unfortunately that check did not take parent VME meta-objects into account, which triggered the bug. Test case by Harald Hvaal <hhvaal@cisco.com> Task-number: QTBUG-63365 Change-Id: I66cb2967da2c09ca5e38cebd9db2ee6e3ee78f5f Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
* Fix qmlClearTypeRegistrations() not dropping all registrationsSimon Hausmann2017-09-192-0/+9
| | | | | | | | | | | | | In commit 48c09a85ce397979c7e706e3694c879ffe456e09 we added the undeletableTypes container to hold a reference on C++ registered types to keep the indices returned by the public qmlRegisterType() API stable. Since qmlClearTypeRegistrations() is API that also resets those indices, we must also clear the undeletableTypes container to avoid leaking memory. Change-Id: I2038c00913f894d58aca3714d64d497493585326 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Fix qml cache invalidation when changing dependent C++ registered QML singletonsSimon Hausmann2017-09-123-0/+25
| | | | | | | | | | | | | | | | | | When a qml file uses a qml singleton, we need to reliably detect when the singleton changes and re-generate the cache of the qml file using it. This is a scenario covered and fixed by commit 5b94de09cc738837d1539e28b3c0dccd17c18d29, with the exception that currently QML singletons registered via qmlRegisterSingleton were not added to the list of dependent singletons for a qml file. We can fix this by extending findCompositeSingletons() to also cover the singletons that do not originate from a qmldir file. [ChangeLog][Qt][Qml] Fixed bug where sometimes changes to a qml singleton would not propagate to the users or cause crashes. Task-number: QTBUG-62243 Change-Id: I16c3d9ba65fd82e898a29b946c341907751135a9 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Remove temporary allocations during type cleanupSimon Hausmann2017-09-081-1/+1
| | | | | | | | | | As a follow-up commit to 48c09a85, avoid the use of key() to create a temporary string when cleaning the QML type registry. There is strictly speaking no need to perform another hash lookup anyway. Change-Id: Ibd5f0210d5584d1f847d8ec61f25cb0972076365 Reviewed-by: Pasi Petäjäjärvi <pasi.petajajarvi@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Get rid of the root object index variableSimon Hausmann2017-09-082-3/+3
| | | | | | | | This is a follow-up to the parent commit to remove the variable that is really a constant (zero). Change-Id: I8fc20027c5c7b871269b814cb8b93636e94be267 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Fix crash with dangling context object pointersSimon Hausmann2017-09-081-0/+2
| | | | | | | | | | | | This is a regression introduced by commit e22b624d9ab1f36021adb9cdbfa9b37054282bb8, where the object that owns the QML context would destroy the context upon struction. Now the context may live longer and thus the context->contextObject pointer would become a dangling pointer. Task-number: QTBUG-63078 Change-Id: I8fdab4086b0472d5d4930cf57aa76922b7ed9e2e Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Fix crashes with closures created in QML componentsLars Knoll2017-09-068-78/+183
| | | | | | | | | | | | | | | When closures created inside QML components are called after the surrounding component (and consequently QML context) has been destroyed, we are in a somewhat limited environment. Initially we would just crash as the calling QML context is not valid anymore. We can alleviate that by introducing reference counting on the context and letting the QML context wrapper keep a strong reference. This avoids the crashes and also ensures that at least imports continue to be accessible within these contexts (as the singleton test case demonstrates). Task-number: QTBUG-61781 Change-Id: I893f171842d01b0863d95a02ea738adc2620e236 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Qml Tooling: Replace bare pointers with QScopedPointerUlf Hermann2017-09-062-11/+12
| | | | | | | This way we don't have to manually initialize and delete them. Change-Id: I0104c744dba380e957271d0924498e3643856e9e Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* QmlProfiler: Avoid race conditions in QQmlTypeLoaderUlf Hermann2017-09-052-4/+25
| | | | | | | | | | | | | We have to make sure all profiler calls to one adapter are done from the same thread. It turns out that all the calls from QQmlTypeLoader are done from the type loader thread. By using a separate adapter for that, we avoid any extra locking. Task-number: QTBUG-62987 Change-Id: I5cffcc30b84dd4154daa0c56312a1141ce2033e1 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Update doc to clarify the slot parameter for connectNotifySignalAndy Shaw2017-08-251-0/+3
| | | | | Change-Id: I89da2d258d6e5663d45497bd4b7fa105a11e46e7 Reviewed-by: Venugopal Shivashankar <Venugopal.Shivashankar@qt.io>
* Fix memory corruption with type trimmingSimon Hausmann2017-08-232-4/+4
| | | | | | | | | | | | | | | | | | When creating a composite type, we register the meta-type in the qml loader thread. However we would require linking of the compilation unit to the QML/engine thread before we would be able to also undo that registration in unlink(), because we require the engine member to be set. If that did not happen, i.e. a qml type was loaded and trimmed from the cache before it was ever linked, we would end up with a dangling pointer in m_compositeTypes. Let's handle the case of CompilationUnit referring to a QML composite type separately from it being a compilation unit resulting from a .js file or in a plain QJSEngine environment. Task-number: QTBUG-62630 Change-Id: Ia68cc46f05345702bd9ba0378f61118f1964d141 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Small cleanupLars Knoll2017-08-231-2/+1
| | | | | Change-Id: Ifb111ceab64244965569f59eda8d9604131d209d Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Cleanup obsolete TODO in source codeLars Knoll2017-08-231-3/+0
| | | | | Change-Id: I0c4f5d908215b9b6fac0fadb352f7c36849dce6f Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Clean up void * usageLars Knoll2017-08-235-13/+16
| | | | | | | | Don't use void * in our internals, when we can simply pass a typed pointer. Change-Id: Id02033c7e66df7e041c079d3546f9dd6027ef8d5 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Don't crash when trying to bind an invalid property indexUlf Hermann2017-08-171-1/+1
| | | | | | | | findAliasTarget() in binding() can result in an invalid index. We do check for valueTypeIndex below, so we should also check for coreIndex. Change-Id: I8cfed237666f8c1f8733592d3abd9be5ccee3229 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Avoid meta-object creation when looking up QML properties in the property cacheSimon Hausmann2017-08-021-4/+8
| | | | | | | | | | | | | | When looking up QML properties in the property cache, we also need to verify that they should be visible in the QML context they are requested from, i.e. if the revision of the object in that context has the property visible or not. That requires retrieving the VME meta-object for QML declared properties. We can retrieve that directly from the QObjectPrivate instead of going through the potential meta-object builder creation path. Task-number: QTBUG-61536 Change-Id: I695921d625169de5c58941087464beb5367fb2db Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Reduce memory consumption of stat() cache in QML type loaderSimon Hausmann2017-08-022-24/+20
| | | | | | | | | | | The m_importDirCache caches the result of QDir/File::exists across paths. By changing the data structure to a QCache we impose a limit on the size of the entries and thus the memory consumption for long running programs that access many qml files. Task-number: QTBUG-61536 Change-Id: I20c4dc77260fe353c13da570b7e1bbd3f47d4b79 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Fix void * usage in our internal APIsLars Knoll2017-08-025-52/+46
| | | | | | Task-number: QTBUG-61536 Change-Id: Ia2b5cfeab093d8be91728032528788dd238c2872 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Move the m_qmlLists member in the QML engine to QQmlMetaTypeLars Knoll2017-08-024-43/+61
| | | | | | | | | | This is a pure metatype id to metatype id mapping, nothing in there is specific to a QML engine instance. Thus move the mapping to QQmlMetaType and make it global for all engines. Task-number: QTBUG-61536 Change-Id: I3792567bc9f585e3e0fbbad94efd1ec3a0db3de0 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Remove unused types on engine destructionSimon Hausmann2017-08-025-98/+201
| | | | | | | | | | | | | The QML engine destructor as well as trimComponentCache() do now clean out unused composite types that the engine registered internally. This helps avoid 'static' leaks, when more and more types would get registered by the engine. Task-number: QTBUG-61536 Change-Id: I5b32af4b88fbf626de8c0bfbaedb2285b09e3679 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Remove unused variableSimon Hausmann2017-08-021-1/+0
| | | | | | | | QQmlTypeModulePrivate::types is not used (anymore?). Task-number: QTBUG-61536 Change-Id: Ia7af542e6969c167d1f05a460e0926398f56f380 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Change data structures in QQmlMetaTypeDataLars Knoll2017-08-023-136/+117
| | | | | | | | | | | | | | | | | Make sure any QQmlType stored in the meta type data has a refcount of 1. This should now make it possible to clean out unused types by iterating over the list of types and removing those that have a refcount of 1. Some care is still needed for C++ registered types, that will need to get one more refcount, so we don't accidentally remove them. Task-number: QTBUG-61536 Change-Id: Id2a18dae5ddcb815f34013f5fde1f05d2d9d0214 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Remove QQmlEnginePrivate::typePropertyCacheSimon Hausmann2017-08-025-112/+146
| | | | | | | | | Instead of maintaining a hash per QQmlType and minor version, move the version specific property caches into QQmlType. Task-number: QTBUG-61536 Change-Id: I72f3990cb93e64ac5074060b4ff327043eab7966 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Move property cache from the engine to QQmlTypeSimon Hausmann2017-08-023-0/+34
| | | | | | | | | | | | | Now that the property cache is independent of a specific engine, we can cache them in QQmlType instead of caching them per engine. This simplifies the logic and avoids duplicated property caches when multiple engines are running. Task-number: QTBUG-61536 Change-Id: I6f082e1e7495ae0f5b92559e8d0a3437c56e303a Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Move the engine pointer from the property cache to the VME meta objectLars Knoll2017-08-026-82/+56
| | | | | | | | | This is where it belongs, and it makes the PropertyCache independent of the engine used. Task-number: QTBUG-61536 Change-Id: I21c2674ee3e2895abd2418764d140b154b47b868 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Use QQmlType by valueLars Knoll2017-08-0215-231/+252
| | | | | | | | | | | QQmlType is now refcounted, and we need to use it by value, to control it's lifetime properly. This is required, so we can clean up the QQmlMetaTypeData cache on engine destruction and with trimComponentCache() Task-number: QTBUG-61536 Change-Id: If86391c86ea20a646ded7c9925d8f743f628fb91 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Use QQmlType by value in the type wrapperLars Knoll2017-08-024-34/+63
| | | | | | Task-number: QTBUG-61536 Change-Id: Ie40cb3a6e170331b0ec7ab5deaf7c1d7ef0cdaeb Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Turn QQmlType into a refcounted value typeLars Knoll2017-08-022-67/+142
| | | | | | Task-number: QTBUG-61536 Change-Id: If906af2bf3afd09c23a612aaac417a751b06eba4 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Fix loading of QML plugins with old IID in static buildsSimon Hausmann2017-07-262-2/+5
| | | | | | | | | | | | | | | | | After commit 709f6370884b110def2e4665df8fa7bbf5fae734 we required the use of QQmlExtensionInterface_iid in qml plugins for static linkage. This mean that plugins using the "/1.0" variant would also continue to load, but those not would fail to load. This is annoying when porting apps from older Qt versions. To make the upgrade path easier, let's just support both IIDs. [ChangeLog][Qml] Fix loading of static qml plugins using the old plugin interface id Change-Id: I1c662b1fedad3f32b7dea1eddc32838d2eb9f3be Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
* Do not (dis)connectNotify on dynamically created model item objectsErik Verbruggen2017-07-254-10/+15
| | | | | | | | | | | | These item objects are direct subclasses of QObject, and cannot override connectNotify/disconnectNotify. This prevents the creation of the backing QMetaObject during disconnect, which happens during destruction, which in turn will call back into the model that is being destroyed. Task-number: QTBUG-59704 Change-Id: I7f997e5d2fda242b38e67b9147224d72aa4508ba Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Rebuild QQmlData::propertyCache if deleted by another engineDavid Edmundson2017-07-131-1/+6
| | | | | | | | | | | | | QQmlData is shared between engines, but the relevant QObjectWrapper is not. Since 749a7212e903d8e8c6f256edb1836b9449cc7fe1 when a QObjectWrapper is deleted it resets the shared QQmlData propertyCache. In most cases the propertyCache except when a property updated in an existing binding in the first engine, where it currently asserts. Task-number: QTBUG-61681 Change-Id: I6efdc506e5c7e30b95cda1be282afa9feb781cd2 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Doc: Fix link to Window.screenTopi Reinio2017-06-201-1/+1
| | | | | | | | src/qml/qml/qqmlengine.cpp:455: warning: Can't link to 'QtQuick::Window::screen' Change-Id: I3f662ff574673d86ca048aec709948b236c17fd9 Reviewed-by: Nico Vertriest <nico.vertriest@qt.io>
* Don't leak QQmlJavaScriptExpression errorsColin Ogilvie2017-06-162-1/+1
| | | | | | | Ensure any error is deleted when the expression is Change-Id: Ibbfd28f50279d4c66830b40c5c917eb8d98f266e Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Fix loading QML caches for qrc:/// urlsAlexander Volkov2017-06-131-0/+6
| | | | | | | | | | | | | | | Running examples/quick/window/window produces debug messages: "QML source file has moved to a different location." This is because QQmlFile::urlToLocalFileOrQrc(const QString &) overload is incompatible with QQmlFile::urlToLocalFileOrQrc(const QUrl &) when it deals with qrc:/// urls. For example it returns ":///window/window.qml" while the QUrl overload returns ":/window/window.qml". Thus the comparison of source paths in CompilationUnit::loadFromDisk() fails. Fix the incompatibility and add a test. Change-Id: I20449b8cf13d715d88860f2cd413ab39c893f3ef Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Doc: correct link issuesNico Vertriest2017-06-131-1/+1
| | | | | | | | qqmlengine.cpp:2182: warning: Can't link to 'LocalStorage.openDatabaseSync()' qqmlengine.cpp:451: warning: Can't link to 'Window.screen' Change-Id: Ib2a3548805125366d7a81982fa2039f6b9341d9b Reviewed-by: Venugopal Shivashankar <Venugopal.Shivashankar@qt.io>
* Move the engine() accessor from Object to ManagedLars Knoll2017-05-191-2/+2
| | | | | | | | | | | | We can easily do this now that Managed has a pointer to an internal class (which always has a back pointer to the ExecutionEngine). Remove the extra engine pointer from ExecutionContext, and clean up tow methods in String. Change-Id: I98d750b1afbdeadf42e66ae0c92c48db1a7adc31 Reviewed-by: Robin Burchell <robin.burchell@crimson.no>
* Don't crash: Connections with a signal on a nonexistent objectShawn Rutledge2017-05-071-1/+4
| | | | | | Task-number: QTBUG-56551 Change-Id: Ide09f177d3f6a3e9902f8ea904b3e6e4b998bd39 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>