From 009c480413910e8c1a18f4d1420f4a517ea606e6 Mon Sep 17 00:00:00 2001 From: Alex Merry Date: Wed, 14 Oct 2015 12:18:40 +0100 Subject: Make sure we load translations on the main thread. BUG: 346188 REVIEW: 123726 --- modules/ECMQmLoader.cpp.in | 90 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 27 deletions(-) (limited to 'modules/ECMQmLoader.cpp.in') diff --git a/modules/ECMQmLoader.cpp.in b/modules/ECMQmLoader.cpp.in index bc01bf98..f6b98e7b 100644 --- a/modules/ECMQmLoader.cpp.in +++ b/modules/ECMQmLoader.cpp.in @@ -5,41 +5,77 @@ */ #include #include +#include #include +#include #include -#include +namespace { -static bool loadTranslation(const QString &localeDirName) -{ - QString subPath = QStringLiteral("locale/") + localeDirName + QStringLiteral("/LC_MESSAGES/@catalog_name@.qm"); - QString fullPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, subPath); - if (fullPath.isEmpty()) { - return false; + bool loadTranslation(const QString &localeDirName) + { + QString subPath = QStringLiteral("locale/") + localeDirName + QStringLiteral("/LC_MESSAGES/@catalog_name@.qm"); + QString fullPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, subPath); + if (fullPath.isEmpty()) { + return false; + } + QTranslator *translator = new QTranslator(QCoreApplication::instance()); + if (!translator->load(fullPath)) { + delete translator; + return false; + } + QCoreApplication::instance()->installTranslator(translator); + return true; } - QTranslator *translator = new QTranslator(QCoreApplication::instance()); - if (!translator->load(fullPath)) { - delete translator; - return false; + + void load() + { + // The way Qt translation system handles plural forms makes it necessary to + // have a translation file which contains only plural forms for `en`. That's + // why we load the `en` translation unconditionally, then load the + // translation for the current locale to overload it. + loadTranslation(QStringLiteral("en")); + + QLocale locale = QLocale::system(); + if (locale.name() != QStringLiteral("en")) { + if (!loadTranslation(locale.name())) { + loadTranslation(locale.bcp47Name()); + } + } } - QCoreApplication::instance()->installTranslator(translator); - return true; -} -static void load() -{ - // The way Qt translation system handles plural forms makes it necessary to - // have a translation file which contains only plural forms for `en`. That's - // why we load the `en` translation unconditionally, then load the - // translation for the current locale to overload it. - loadTranslation(QStringLiteral("en")); - - QLocale locale = QLocale::system(); - if (locale.name() != QStringLiteral("en")) { - if (!loadTranslation(locale.name())) { - loadTranslation(locale.bcp47Name()); + // helper to call load() on the correct thread + class Loader : public QObject + { + Q_OBJECT + + public Q_SLOTS: + void callLoadAndDeleteSelf() + { + load(); + this->deleteLater(); + } + }; + + void loadOnMainThread() + { + // If this library is loaded after the QCoreApplication instance is created + // (eg: because it is brought in by a plugin), there is no guarantee this + // function will be called on the main thread. + // QCoreApplication::installTranslator needs to be called on the main + // thread, because it uses QCoreApplication::sendEvent. + if (QThread::currentThread() == QCoreApplication::instance()->thread()) { + load(); + } else { + // QObjects inherit their parent object's thread + Loader *loader = new Loader(); + loader->moveToThread(QCoreApplication::instance()->thread()); + QMetaObject::invokeMethod(loader, "callLoadAndDeleteSelf", Qt::AutoConnection); } } + } -Q_COREAPP_STARTUP_FUNCTION(load) +Q_COREAPP_STARTUP_FUNCTION(loadOnMainThread) + +#include "ECMQmLoader.moc" -- cgit v1.2.1