diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-10-07 14:25:50 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-10-11 09:39:28 +0200 |
commit | f51231164e7074bfcd4deea31e82428b31483e53 (patch) | |
tree | 405c02b2f98b46b2a701e2839bc2f536a881b57a /src/qmlmodels/qqmllistmodel.cpp | |
parent | d8fcc1b8f4c20536cad4f806c4c42d3b8086115f (diff) |
QQmlEngine: Fine grained translation binding tracking
This commit changes translation bindings in such a way that they always
depend on the a newly introduced translationLanguage property of the QML
engine.
Moreover, captureTranslationBinding is changed in the same way, hence
any binding containing a call to a translation function like qsTr will
also be refreshed. After those changes, QQmlEngine::retranslate can be
implemented as a notify on translationLanguage. Finally,
QQmlTranslationPropertyBinding is also changed to depend on
translationLanguage instead of uiLanguage to ensure consistency between
the various binding types.
Note that we do not use the existing uiLanguage property of QJSEngine.
If we were to do this, changing uiLanguage would already trigger the
binding reevaluation, which is a behavior change. In case someone is
manually connecting uiLanguageChanged to QQmlEngine::retranslate, this
would cause a double evaluation of translation bindings. In a future
change, we can however introduce a new enableAutoTranslationUpdate
method, which would cause binding evaluation as soon as uiLanguage is
changed.
Special care is taken for ListModel/ListElement, which does not store a
proper translation binding, but instead operates on
QV4::CompiledData::Binding. For now, we simply refresh the complete
ListModel in case it contains a translation binding. It should be
possible to optimize this further in a future change.
Note that only "static" ListElement properties can contain translations:
The dynamic insertion API makes it impossible to insert a translation,
as it would already be resolved to a string when insert is called.
[ChangeLog][QQmlEngine] QQmlEngine::retranslate no longer refreshes all
bindings, but only translation bindings.
Fixes: QTBUG-96192
Change-Id: I54d213fd46b6914e8f686843b49e155909117218
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit d4039298e710b6b79c018589bcc2145e22e1d5aa)
Diffstat (limited to 'src/qmlmodels/qqmllistmodel.cpp')
-rw-r--r-- | src/qmlmodels/qqmllistmodel.cpp | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp index b9f59040a1..47a95a7ea1 100644 --- a/src/qmlmodels/qqmllistmodel.cpp +++ b/src/qmlmodels/qqmllistmodel.cpp @@ -567,6 +567,17 @@ ListModel *ListModel::getListProperty(int elementIndex, const ListLayout::Role & return e->getListProperty(role); } +void ListModel::updateTranslations() +{ + for (int index = 0; index != elements.count(); ++index) { + ListElement *e = elements[index]; + if (ModelNodeMetaObject *cache = e->objectCache()) { + // TODO: more fine grained tracking? + cache->updateValues(); + } + } +} + void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles) { ListElement *e = elements[elementIndex]; @@ -2499,6 +2510,17 @@ void QQmlListModel::removeElements(int index, int removeCount) destroyer(); } +void QQmlListModel::updateTranslations() +{ + // assumption: it is impossible to have retranslatable strings in a + // dynamic list model, as they would already have "decayed" to strings + // when they were inserted + if (m_dynamicRoles) + return; + Q_ASSERT(m_listModel); + m_listModel->updateTranslations(); +} + /*! \qmlmethod ListModel::insert(int index, jsobject dict) @@ -2924,7 +2946,8 @@ bool QQmlListModelParser::applyProperty( } else { QVariant value; - if (binding->isTranslationBinding()) { + const bool isTranslationBinding = binding->isTranslationBinding(); + if (isTranslationBinding) { value = QVariant::fromValue<const QV4::CompiledData::Binding*>(binding); } else if (binding->evaluatesToString()) { value = compilationUnit->bindingValueAsString(binding); @@ -2966,7 +2989,17 @@ bool QQmlListModelParser::applyProperty( Q_UNREACHABLE(); } + if (!model) + return roleSet; model->setOrCreateProperty(outterElementIndex, elementName, value); + auto listModel = model->m_modelCache; + if (isTranslationBinding && listModel) { + if (!listModel->translationChangeHandler) { + auto ep = QQmlEnginePrivate::get(compilationUnit->engine); + model->m_modelCache->translationChangeHandler = std::make_unique<QPropertyNotifier>( + ep->translationLanguage.addNotifier([listModel](){ listModel->updateTranslations(); })); + } + } roleSet = true; } return roleSet; |