From 44f7c1e097582a704a06ccbbf516536b88ddcd3a Mon Sep 17 00:00:00 2001 From: dka Date: Mon, 12 Oct 2009 16:25:23 +0300 Subject: Changes to support locale change event for symbian platform Subscribing to the locale change notification to be able to update the system locale whenever the user changes the current system locale. Also changed the initialization of the system locale to make construction of the QLocale object as lightweight as possible. So now the default contructor just creates a QLocale and QSystemLocale objects, but doesn't try to fill the cache in the latter with data from the system and postpones it until it is actually requested (most applications create QLocale objects on the stack and might not even use the data from the system locale, so we don't need to initialize system locale right away). Modified-by: axis Modified-by: Denis Dzyubenko Reviewed-by: Denis Dzyubenko Reviewed-by: axis --- src/corelib/kernel/qcore_symbian_p.h | 3 +- src/corelib/kernel/qcoreapplication.cpp | 10 +++ src/corelib/kernel/qcoreapplication.h | 4 ++ src/corelib/kernel/qcoreapplication_p.h | 4 ++ src/corelib/tools/qlocale.cpp | 43 +++++++++--- src/corelib/tools/qlocale_p.h | 5 +- src/corelib/tools/qlocale_symbian.cpp | 121 ++++++++++++++++++++++++++++++-- src/plugins/s60/src/qlocale_3_1.cpp | 8 +++ 8 files changed, 181 insertions(+), 17 deletions(-) diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h index f86bfd3..2ef48b5 100644 --- a/src/corelib/kernel/qcore_symbian_p.h +++ b/src/corelib/kernel/qcore_symbian_p.h @@ -139,7 +139,8 @@ enum S60PluginFuncOrdinals S60Plugin_GetLongDateFormatSpec = 3, S60Plugin_GetShortDateFormatSpec = 4, S60Plugin_LocalizedDirectoryName = 5, - S60Plugin_GetSystemDrive = 6 + S60Plugin_GetSystemDrive = 6, + S60Plugin_RefreshLocaleInfo = 7 }; Q_CORE_EXPORT TLibraryFunction qt_resolveS60PluginFunc(int ordinal); diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 8a55bad..93df45d 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -69,6 +69,7 @@ # include # include "qeventdispatcher_symbian_p.h" # include "private/qcore_symbian_p.h" +# include "private/qlocale_p.h" #elif defined(Q_OS_UNIX) # if !defined(QT_NO_GLIB) # include "qeventdispatcher_glib_p.h" @@ -2601,4 +2602,13 @@ int QCoreApplication::loopLevel() \sa Q_OBJECT, QObject::tr(), QObject::trUtf8() */ +#if defined(Q_OS_SYMBIAN) +void QCoreApplicationPrivate::_q_symbianRegisterLocaleNotifier() +{ + QLocalePrivate::symbianRegisterLocaleNotifier(); +} +#endif + QT_END_NAMESPACE + +#include "moc_qcoreapplication.cpp" diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index 097b8b4..152a775 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -196,6 +196,10 @@ private: static QCoreApplication *self; +#if defined(Q_OS_SYMBIAN) + Q_PRIVATE_SLOT(d_func(), void _q_symbianRegisterLocaleNotifier()) +#endif + Q_DISABLE_COPY(QCoreApplication) friend class QEventDispatcherUNIXPrivate; diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index bf43f88..39e50c4 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -122,6 +122,10 @@ public: static uint attribs; static inline bool testAttribute(uint flag) { return attribs & (1 << flag); } + +#if defined(Q_OS_SYMBIAN) + void _q_symbianRegisterLocaleNotifier(); +#endif }; QT_END_NAMESPACE diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 4a66b92..22114c2 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -129,6 +129,10 @@ inline bool isascii(int c) } #endif +#if defined(Q_OS_SYMBIAN) +void symbianUpdateSystemPrivate(); +#endif + /****************************************************************************** ** Helpers for accessing Qt locale database */ @@ -1388,7 +1392,8 @@ QSystemLocale::QSystemLocale() /*! \internal */ QSystemLocale::QSystemLocale(bool) -{ } +{ +} /*! Deletes the object. @@ -1407,16 +1412,29 @@ static const QSystemLocale *systemLocale() { if (_systemLocale) return _systemLocale; +#if defined(Q_OS_SYMBIAN) + symbianInitSystemLocale(); +#endif return QSystemLocale_globalSystemLocale(); } -void QLocalePrivate::updateSystemPrivate() +void QLocalePrivate::updateSystemPrivate(bool initialize) { const QSystemLocale *sys_locale = systemLocale(); if (!system_lp) system_lp = globalLocalePrivate(); *system_lp = *sys_locale->fallbackLocale().d(); + system_lp->m_language_id = 0; +#if defined(Q_OS_SYMBIAN) + RDebug::Print(_L("updateSystemPrivate")); +#endif + if (!initialize) + return; + +#if defined(Q_OS_SYMBIAN) + symbianUpdateSystemPrivate(); +#endif QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant()); if (!res.isNull()) system_lp->m_language_id = res.toInt(); @@ -1446,12 +1464,12 @@ void QLocalePrivate::updateSystemPrivate() } #endif -static const QLocalePrivate *systemPrivate() +static const QLocalePrivate *systemPrivate(bool initialize = true) { #ifndef QT_NO_SYSTEMLOCALE // copy over the information from the fallback locale and modify if (!system_lp || system_lp->m_language_id == 0) - QLocalePrivate::updateSystemPrivate(); + QLocalePrivate::updateSystemPrivate(initialize); return system_lp; #else @@ -1459,10 +1477,10 @@ static const QLocalePrivate *systemPrivate() #endif } -static const QLocalePrivate *defaultPrivate() +static const QLocalePrivate *defaultPrivate(bool initialize = true) { if (!default_lp) - default_lp = systemPrivate(); + default_lp = systemPrivate(initialize); return default_lp; } @@ -2169,7 +2187,7 @@ QLocale::QLocale() : v(0) { p.numberOptions = default_number_options; - p.index = localePrivateIndex(defaultPrivate()); + p.index = localePrivateIndex(defaultPrivate(false)); } /*! @@ -2199,7 +2217,7 @@ QLocale::QLocale(Language language, Country country) // If not found, should default to system if (d->languageId() == QLocale::C && language != QLocale::C) { p.numberOptions = default_number_options; - p.index = localePrivateIndex(defaultPrivate()); + p.index = localePrivateIndex(defaultPrivate(false)); } else { p.numberOptions = 0; p.index = localePrivateIndex(d); @@ -2283,6 +2301,7 @@ void QLocale::setDefault(const QLocale &locale) */ QLocale::Language QLocale::language() const { + systemPrivate(); // make sure inline data is initialized from the system. return Language(d()->languageId()); } @@ -2293,6 +2312,7 @@ QLocale::Language QLocale::language() const */ QLocale::Country QLocale::country() const { + systemPrivate(); // make sure inline data is initialized from the system. return Country(d()->countryId()); } @@ -3021,6 +3041,7 @@ QDateTime QLocale::toDateTime(const QString &string, const QString &format) cons */ QChar QLocale::decimalPoint() const { + systemPrivate(); // make sure inline data is initialized from the system. return d()->decimal(); } @@ -3031,6 +3052,7 @@ QChar QLocale::decimalPoint() const */ QChar QLocale::groupSeparator() const { + systemPrivate(); // make sure inline data is initialized from the system. return d()->group(); } @@ -3041,6 +3063,7 @@ QChar QLocale::groupSeparator() const */ QChar QLocale::percent() const { + systemPrivate(); // make sure inline data is initialized from the system. return d()->percent(); } @@ -3051,6 +3074,7 @@ QChar QLocale::percent() const */ QChar QLocale::zeroDigit() const { + systemPrivate(); // make sure inline data is initialized from the system. return d()->zero(); } @@ -3061,6 +3085,7 @@ QChar QLocale::zeroDigit() const */ QChar QLocale::negativeSign() const { + systemPrivate(); // make sure inline data is initialized from the system. return d()->minus(); } @@ -3071,6 +3096,7 @@ QChar QLocale::negativeSign() const */ QChar QLocale::positiveSign() const { + systemPrivate(); // make sure inline data is initialized from the system. return d()->plus(); } @@ -3081,6 +3107,7 @@ QChar QLocale::positiveSign() const */ QChar QLocale::exponential() const { + systemPrivate(); // make sure inline data is initialized from the system. return d()->exponential(); } diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index 0123a6e..63e9e0f 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -132,7 +132,10 @@ public: CharBuff *result) const; inline char digitToCLocale(const QChar &c) const; - static void updateSystemPrivate(); + static void updateSystemPrivate(bool initialize = true); +#if defined(Q_OS_SYMBIAN) + static void symbianRegisterLocaleNotifier(); +#endif enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode }; bool validateChars(const QString &str, NumberMode numMode, QByteArray *buff, int decDigits = -1) const; diff --git a/src/corelib/tools/qlocale_symbian.cpp b/src/corelib/tools/qlocale_symbian.cpp index 1273d06..c4ad67c 100644 --- a/src/corelib/tools/qlocale_symbian.cpp +++ b/src/corelib/tools/qlocale_symbian.cpp @@ -46,11 +46,95 @@ #include #include +#include +#include #include "private/qcore_symbian_p.h" - +#include "private/qcoreapplication_p.h" +#include "qlocale_p.h" +#include "qdebug.h" QT_BEGIN_NAMESPACE +class CLocaleChangeNotifier : public CActive +{ +public: + static CLocaleChangeNotifier *NewL(); + ~CLocaleChangeNotifier(); + +private: + CLocaleChangeNotifier(); + void ConstructL(); + void RunL(); + void DoCancel(); + +private: + RChangeNotifier changeNotifier; +}; + +static CLocaleChangeNotifier *qt_changeNotifier = NULL; + +CLocaleChangeNotifier *CLocaleChangeNotifier::NewL() +{ + CLocaleChangeNotifier *self = new (ELeave) CLocaleChangeNotifier(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; +} + +CLocaleChangeNotifier::CLocaleChangeNotifier() + : CActive(CActive::EPriorityStandard) +{ +} + + +CLocaleChangeNotifier::~CLocaleChangeNotifier() +{ + Cancel(); + changeNotifier.Close(); +} + +void CLocaleChangeNotifier::ConstructL() +{ + changeNotifier.Create(); + CActiveScheduler::Add(this); + SetActive(); +} + +void CLocaleChangeNotifier::DoCancel() +{ + changeNotifier.LogonCancel(); +} + +void CLocaleChangeNotifier::RunL() +{ + SetActive(); + if (changeNotifier.Logon(iStatus) == KErrNone) { + if (iStatus.Int() == EChangesLocale) { + RDebug::Print(_L("notifier:locale changed")); + QT_TRYCATCH_LEAVING(QLocalePrivate::updateSystemPrivate()); + } else { + RDebug::Print(_L("notifier:something else changed")); + } + } else { + RDebug::Print(_L("notifier:logon failed")); + } +} + +static void qt_cleanupLocaleNotifier() +{ + delete qt_changeNotifier; + qt_changeNotifier = NULL; +} + +void QLocalePrivate::symbianRegisterLocaleNotifier() +{ + if (!qt_changeNotifier) { + QT_TRAP_THROWING(qt_changeNotifier = CLocaleChangeNotifier::NewL()); + qAddPostRoutine(qt_cleanupLocaleNotifier); + } +} + // Located in qlocale.cpp extern void getLangAndCountry(const QString &name, QLocale::Language &lang, QLocale::Country &cntry); @@ -65,6 +149,7 @@ static FormatFunc ptrTimeFormatL = NULL; static FormatSpecFunc ptrGetTimeFormatSpec = NULL; static FormatSpecFunc ptrGetLongDateFormatSpec = NULL; static FormatSpecFunc ptrGetShortDateFormatSpec = NULL; +static FormatSpecFunc ptrRefreshLocaleInfo = NULL; // Default functions if functions cannot be resolved static void defaultTimeFormatL(TTime&, TDes& des, const TDesC&, const TLocale&) @@ -214,6 +299,8 @@ static const char *jp_locale_dep[] = { */ static QString s60ToQtFormat(const QString &sys_fmt) { + RDebug::Print(_L("Time Format \"%S\""), &timeFormat); + TLocale *locale = _s60Locale.GetLocale(); QString result; @@ -679,6 +766,8 @@ static QString symbianDateFormat(bool short_format) dateFormat.Set(ptrGetLongDateFormatSpec(_s60Locale)); } + RDebug::Print(_L("symDateFormat: \"%S\""), &dateFormat); + return s60ToQtFormat(qt_TDesC2QString(dateFormat)); } @@ -688,6 +777,8 @@ static QString symbianDateFormat(bool short_format) */ static QString symbianTimeFormat() { + TPtrC timeFormat = ptrGetTimeFormatSpec(_s60Locale); + RDebug::Print(_L("symTimeFormat: \"%S\""), &timeFormat); return s60ToQtFormat(qt_TDesC2QString(ptrGetTimeFormatSpec(_s60Locale))); } @@ -771,22 +862,35 @@ static QLocale::MeasurementSystem symbianMeasurementSystem() return QLocale::MetricSystem; } -QLocale QSystemLocale::fallbackLocale() const +void symbianUpdateSystemPrivate() { + RDebug::Print(_L("symbianUpdateSystemPrivate")); // load system data before query calls + _s60Locale.LoadSystemSettings(); + if (ptrRefreshLocaleInfo) + ptrRefreshLocaleInfo(); +} + +void symbianInitSystemLocale() +{ + RDebug::Print(_L("symbianInitSystemLocale")); static QBasicAtomicInt initDone = Q_BASIC_ATOMIC_INITIALIZER(0); if (initDone.testAndSetRelaxed(0, 1)) { - _s60Locale.LoadSystemSettings(); + if (!qt_changeNotifier) { + QMetaObject::invokeMethod(qApp, SLOT(_q_symbianRegisterLocaleNotifier()), Qt::AutoConnection); + } // Initialize platform version dependent function pointers ptrTimeFormatL = reinterpret_cast - (qt_resolveS60PluginFunc(S60Plugin_TimeFormatL)); + (qt_resolveS60PluginFunc(S60Plugin_TimeFormatL)); ptrGetTimeFormatSpec = reinterpret_cast - (qt_resolveS60PluginFunc(S60Plugin_GetTimeFormatSpec)); + (qt_resolveS60PluginFunc(S60Plugin_GetTimeFormatSpec)); ptrGetLongDateFormatSpec = reinterpret_cast - (qt_resolveS60PluginFunc(S60Plugin_GetLongDateFormatSpec)); + (qt_resolveS60PluginFunc(S60Plugin_GetLongDateFormatSpec)); ptrGetShortDateFormatSpec = reinterpret_cast - (qt_resolveS60PluginFunc(S60Plugin_GetShortDateFormatSpec)); + (qt_resolveS60PluginFunc(S60Plugin_GetShortDateFormatSpec)); + ptrRefreshLocaleInfo = reinterpret_cast + (qt_resolveS60PluginFunc(S60Plugin_RefreshLocaleInfo)); if (!ptrTimeFormatL) ptrTimeFormatL = &defaultTimeFormatL; if (!ptrGetTimeFormatSpec) @@ -801,7 +905,10 @@ QLocale QSystemLocale::fallbackLocale() const } while(initDone != 2) QThread::yieldCurrentThread(); +} +QLocale QSystemLocale::fallbackLocale() const +{ TLanguage lang = User::Language(); QString locale = QLatin1String(qt_symbianLocaleName(lang)); return QLocale(locale); diff --git a/src/plugins/s60/src/qlocale_3_1.cpp b/src/plugins/s60/src/qlocale_3_1.cpp index beeee7f..d597861 100644 --- a/src/plugins/s60/src/qlocale_3_1.cpp +++ b/src/plugins/s60/src/qlocale_3_1.cpp @@ -50,6 +50,7 @@ _LIT(KLocaleIndependent, "%F"); static TBuf<10> dateFormat; static TBuf<10> timeFormat; +#define _DEBUG static void initialiseDateFormat() { if(dateFormat.Length()) @@ -146,3 +147,10 @@ EXPORT_C TPtrC defaultGetShortDateFormatSpec(TExtendedLocale&) initialiseDateFormat(); return TPtrC(dateFormat); } + +EXPORT_C void refreshLocaleInfo() +{ + // clear the buffers, so next time we re-read data from the system. + dateFormat.Zero(); + timeFormat.Zero(); +} -- cgit v0.12