1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qlocale_p.h"
44 #include "qstringlist.h"
46 #include "qdatetime.h"
48 #if !defined(QWS) && defined(Q_OS_MAC)
49 # include "private/qcore_mac_p.h"
50 # include <CoreFoundation/CoreFoundation.h>
55 /******************************************************************************
56 ** Wrappers for Mac locale system functions
59 static QByteArray envVarLocale()
61 static QByteArray lang = 0;
63 lang = qgetenv("LC_ALL");
65 lang = qgetenv("LC_NUMERIC");
68 lang = qgetenv("LANG");
72 static QByteArray getMacLocaleName()
74 QByteArray result = envVarLocale();
76 QString lang, script, cntry;
78 || (result != "C" && !qt_splitLocaleName(QString::fromLocal8Bit(result), lang, script, cntry))) {
79 QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
80 CFStringRef locale = CFLocaleGetIdentifier(l);
81 result = QCFString::toQString(locale).toUtf8();
86 static QString macMonthName(int month, bool short_format)
89 if (month < 0 || month > 11)
92 QCFType<CFDateFormatterRef> formatter
93 = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
94 kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
95 QCFType<CFArrayRef> values
96 = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
97 short_format ? kCFDateFormatterShortMonthSymbols
98 : kCFDateFormatterMonthSymbols));
100 CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month));
101 return QCFString::toQString(cfstring);
106 static QString macDayName(int day, bool short_format)
108 if (day < 1 || day > 7)
111 QCFType<CFDateFormatterRef> formatter
112 = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
113 kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
114 QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
115 short_format ? kCFDateFormatterShortWeekdaySymbols
116 : kCFDateFormatterWeekdaySymbols));
118 CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7));
119 return QCFString::toQString(cfstring);
124 static QString macDateToString(const QDate &date, bool short_format)
126 CFGregorianDate macGDate;
127 macGDate.year = date.year();
128 macGDate.month = date.month();
129 macGDate.day = date.day();
132 macGDate.second = 0.0;
133 QCFType<CFDateRef> myDate
134 = CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate,
135 QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault())));
136 QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
137 CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle;
138 QCFType<CFDateFormatterRef> myFormatter
139 = CFDateFormatterCreate(kCFAllocatorDefault,
141 kCFDateFormatterNoStyle);
142 return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
145 static QString macTimeToString(const QTime &time, bool short_format)
147 CFGregorianDate macGDate;
148 // Assume this is local time and the current date
149 QDate dt = QDate::currentDate();
150 macGDate.year = dt.year();
151 macGDate.month = dt.month();
152 macGDate.day = dt.day();
153 macGDate.hour = time.hour();
154 macGDate.minute = time.minute();
155 macGDate.second = time.second();
156 QCFType<CFDateRef> myDate
157 = CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate,
158 QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault())));
160 QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
161 CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle;
162 QCFType<CFDateFormatterRef> myFormatter = CFDateFormatterCreate(kCFAllocatorDefault,
164 kCFDateFormatterNoStyle,
166 return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
169 static QString macToQtFormat(const QString &sys_fmt)
174 while (i < sys_fmt.size()) {
175 if (sys_fmt.at(i).unicode() == '\'') {
176 QString text = qt_readEscapedFormatString(sys_fmt, &i);
177 if (text == QLatin1String("'"))
178 result += QLatin1String("''");
180 result += QLatin1Char('\'') + text + QLatin1Char('\'');
184 QChar c = sys_fmt.at(i);
185 int repeat = qt_repeatCount(sys_fmt, i);
187 switch (c.unicode()) {
188 case 'G': // Qt doesn't support these :(
197 case 'u': // extended year - use 'y'
199 result += QLatin1String("yy");
201 result += QLatin1String("yyyy");
203 case 'S': // fractional second
205 result += QLatin1Char('z');
207 result += QLatin1String("zzz");
211 result += QLatin1String("ddd");
213 result += QLatin1String("dddd");
217 result += QLatin1String("dd");
219 result += QLatin1Char('d');
222 result += QLatin1String("AP");
225 result += QString(repeat, QLatin1Char('H'));
228 result += QString(repeat, QLatin1Char('h'));
233 result += QLatin1Char('t');
236 result += QString(repeat, c);
246 QString getMacDateFormat(CFDateFormatterStyle style)
248 QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
249 QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault,
250 l, style, kCFDateFormatterNoStyle);
251 return macToQtFormat(QCFString::toQString(CFDateFormatterGetFormat(formatter)));
254 static QString getMacTimeFormat(CFDateFormatterStyle style)
256 QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
257 QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault,
258 l, kCFDateFormatterNoStyle, style);
259 return macToQtFormat(QCFString::toQString(CFDateFormatterGetFormat(formatter)));
262 static QString getCFLocaleValue(CFStringRef key)
264 QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
265 CFTypeRef value = CFLocaleGetValue(locale, key);
266 return QCFString::toQString(CFStringRef(static_cast<CFTypeRef>(value)));
269 static QLocale::MeasurementSystem macMeasurementSystem()
271 QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
272 CFStringRef system = static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleMeasurementSystem));
273 if (QCFString::toQString(system) == QLatin1String("Metric")) {
274 return QLocale::MetricSystem;
276 return QLocale::ImperialSystem;
281 static quint8 macFirstDayOfWeek()
283 QCFType<CFCalendarRef> calendar = CFCalendarCopyCurrent();
284 quint8 day = static_cast<quint8>(CFCalendarGetFirstWeekday(calendar))-1;
290 static QString macCurrencySymbol(QLocale::CurrencySymbolFormat format)
292 QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
294 case QLocale::CurrencyIsoCode:
295 return QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleCurrencyCode)));
296 case QLocale::CurrencySymbol:
297 return QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleCurrencySymbol)));
298 case QLocale::CurrencyDisplayName: {
299 CFStringRef code = static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleCurrencyCode));
300 QCFType<CFStringRef> value = CFLocaleCopyDisplayNameForPropertyValue(locale, kCFLocaleCurrencyCode, code);
301 return QCFString::toQString(value);
309 #ifndef QT_NO_SYSTEMLOCALE
310 static QString macFormatCurrency(const QSystemLocale::CurrencyToStringArgument &arg)
312 QCFType<CFNumberRef> value;
313 switch (arg.value.type()) {
315 case QVariant::UInt: {
316 int v = arg.value.toInt();
317 value = CFNumberCreate(NULL, kCFNumberIntType, &v);
320 case QVariant::Double: {
321 double v = arg.value.toDouble();
322 value = CFNumberCreate(NULL, kCFNumberDoubleType, &v);
325 case QVariant::LongLong:
326 case QVariant::ULongLong: {
327 qint64 v = arg.value.toLongLong();
328 value = CFNumberCreate(NULL, kCFNumberLongLongType, &v);
335 QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
336 QCFType<CFNumberFormatterRef> currencyFormatter =
337 CFNumberFormatterCreate(NULL, locale, kCFNumberFormatterCurrencyStyle);
338 if (!arg.symbol.isEmpty()) {
339 CFNumberFormatterSetProperty(currencyFormatter, kCFNumberFormatterCurrencySymbol,
340 QCFString::toCFStringRef(arg.symbol));
342 QCFType<CFStringRef> result = CFNumberFormatterCreateStringWithNumber(NULL, currencyFormatter, value);
343 return QCFString::toQString(result);
346 static QVariant macQuoteString(QSystemLocale::QueryType type, const QStringRef &str)
348 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
349 if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6)
353 QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
355 case QSystemLocale::StringToStandardQuotation:
356 begin = QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleQuotationBeginDelimiterKey)));
357 end = QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleQuotationEndDelimiterKey)));
358 return QString(begin % str % end);
359 case QSystemLocale::StringToAlternateQuotation:
360 begin = QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleAlternateQuotationBeginDelimiterKey)));
361 end = QCFString::toQString(static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleAlternateQuotationEndDelimiterKey)));
362 return QString(begin % str % end);
369 #endif //QT_NO_SYSTEMLOCALE
371 #ifndef QT_NO_SYSTEMLOCALE
373 QLocale QSystemLocale::fallbackUiLocale() const
375 return QLocale(QString::fromUtf8(getMacLocaleName().constData()));
378 QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
382 // return getMacLocaleName();
384 QString value = getCFLocaleValue(kCFLocaleDecimalSeparator);
385 return value.isEmpty() ? QVariant() : value;
387 case GroupSeparator: {
388 QString value = getCFLocaleValue(kCFLocaleGroupingSeparator);
389 return value.isEmpty() ? QVariant() : value;
392 case DateFormatShort:
393 return getMacDateFormat(type == DateFormatShort
394 ? kCFDateFormatterShortStyle
395 : kCFDateFormatterLongStyle);
397 case TimeFormatShort:
398 return getMacTimeFormat(type == TimeFormatShort
399 ? kCFDateFormatterShortStyle
400 : kCFDateFormatterLongStyle);
403 return macDayName(in.toInt(), (type == DayNameShort));
406 return macMonthName(in.toInt(), (type == MonthNameShort));
407 case DateToStringShort:
408 case DateToStringLong:
409 return macDateToString(in.toDate(), (type == DateToStringShort));
410 case TimeToStringShort:
411 case TimeToStringLong:
412 return macTimeToString(in.toTime(), (type == TimeToStringShort));
419 case MeasurementSystem:
420 return QVariant(static_cast<int>(macMeasurementSystem()));
424 QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
425 QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterLongStyle, kCFDateFormatterLongStyle);
426 QCFType<CFStringRef> value = static_cast<CFStringRef>(CFDateFormatterCopyProperty(formatter,
427 (type == AMText ? kCFDateFormatterAMSymbol : kCFDateFormatterPMSymbol)));
428 return QCFString::toQString(value);
431 return QVariant(macFirstDayOfWeek());
433 return QVariant(macCurrencySymbol(QLocale::CurrencySymbolFormat(in.toUInt())));
434 case CurrencyToString:
435 return macFormatCurrency(in.value<QSystemLocale::CurrencyToStringArgument>());
437 QCFType<CFArrayRef> languages = (CFArrayRef)CFPreferencesCopyValue(
438 CFSTR("AppleLanguages"),
439 kCFPreferencesAnyApplication,
440 kCFPreferencesCurrentUser,
441 kCFPreferencesAnyHost);
442 const int cnt = CFArrayGetCount(languages);
445 for (int i = 0; i < cnt; ++i) {
446 const QString lang = QCFString::toQString(
447 static_cast<CFStringRef>(CFArrayGetValueAtIndex(languages, i)));
450 return QVariant(result);
452 case StringToStandardQuotation:
453 case StringToAlternateQuotation:
454 return macQuoteString(type, in.value<QStringRef>());
461 #endif // QT_NO_SYSTEMLOCALE