/* * * Copyright 2013 Canonical Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ #include //TODO: switch to QTimeZone (QT 5.1) #include #include #include "globalization.h" Globalization::Globalization(Cordova *cordova): CPlugin(cordova) { } void Globalization::getPreferredLanguage(int scId, int ecId) { Q_UNUSED(ecId) QLocale locale; QString lang = QLocale::languageToString(locale.language()); QVariantMap obj; obj.insert("value", lang); this->cb(scId, obj); } void Globalization::getLocaleName(int scId, int ecId) { Q_UNUSED(ecId) QVariantMap obj; obj.insert("value", QLocale().name()); this->cb(scId, obj); } void Globalization::getFirstDayOfWeek(int scId, int ecId) { Q_UNUSED(ecId) QLocale locale; int res; if (locale.firstDayOfWeek() == Qt::Sunday) { res = 1; } else { res = (2 - Qt::Monday) + locale.firstDayOfWeek(); } QVariantMap obj; obj.insert("value", res); this->cb(scId, obj); } void Globalization::isDayLightSavingsTime(int scId, int ecId, const QVariantMap &options) { time_t time = options.find("time_t")->toLongLong() / 1000; const tm *desc = std::localtime(&time); if (desc->tm_isdst < 0) { this->callback(ecId, QString("new GlobalizationError(%1, 'information is not available');").arg(Globalization::UNKNOWN_ERROR)); return; } this->callback(scId, QString("{dst:%1}").arg(desc->tm_isdst > 0 ? "true" : "false")); } QLocale::FormatType translateFormat(Globalization::Format formatLength) { QLocale::FormatType format = QLocale::ShortFormat; switch (formatLength) { case Globalization::FORMAT_FULL: case Globalization::FORMAT_LONG: format = QLocale::ShortFormat; // TODO: Qt cant parse string produced with QLocale::LongFormat; break; case Globalization::FORMAT_MEDIUM: format = QLocale::ShortFormat; break; case Globalization::FORMAT_SHORT: format = QLocale::NarrowFormat; break; } return format; } void Globalization::dateToString(int scId, int ecId, const QVariantMap &options) { time_t time = options.find("time_t")->toLongLong() / 1000; Globalization::Format formatLength = static_cast(options.find("formatLength")->toInt()); Globalization::Selector selector = static_cast(options.find("selector")->toInt()); QLocale::FormatType format = translateFormat(formatLength); if (time < 0) { this->callback(ecId, QString("new GlobalizationError(%1, 'unsupported operation');").arg(Globalization::FORMATTING_ERROR)); return; } QLocale locale; QString res; QDateTime dateTime = QDateTime::fromTime_t((uint)time); switch (selector) { case SELECTOR_ALL: res = locale.toString(dateTime,format); break; case SELECTOR_TIME: res = locale.toString(dateTime.time(), format); break; case SELECTOR_DATE: res = locale.toString(dateTime.date(), format); break; } QVariantMap obj; obj.insert("value", res); this->cb(scId, obj); } void Globalization::stringToDate(int scId, int ecId, const QVariantMap &options) { QString dateString = options.find("dateString")->toString(); Globalization::Format formatLength = static_cast(options.find("formatLength")->toInt()); Globalization::Selector selector = static_cast(options.find("selector")->toInt()); QLocale::FormatType format = translateFormat(formatLength); QLocale locale; bool valid(true); int year(0), month(0), day(0), hour(0), minute(0), second(0), millisecond(0); switch (selector) { case SELECTOR_ALL: { QDateTime dateTime = locale.toDateTime(dateString, format); valid = dateTime.isValid(); QTime time = dateTime.time(); hour = time.hour(); minute = time.minute(); second = time.second(); millisecond = time.msec(); QDate date = dateTime.date(); year = date.year(); month = date.month(); day = date.day(); } break; case SELECTOR_TIME: { QTime time = locale.toTime(dateString, format); valid = time.isValid(); hour = time.hour(); minute = time.minute(); second = time.second(); millisecond = time.msec(); } break; case SELECTOR_DATE: { QDate date = locale.toDate(dateString, format); valid = date.isValid(); year = date.year(); month = date.month(); day = date.day(); } break; } if ((format == QLocale::NarrowFormat || format == QLocale::ShortFormat) && year < 2000 && year > 1900) { year += 100; } if (!valid) { this->callback(ecId, QString("new GlobalizationError(%1, 'parsing error')").arg(Globalization::PARSING_ERROR)); } else { QVariantMap obj; obj.insert("year", year); obj.insert("month", month - 1); obj.insert("day", day); obj.insert("hour", hour); obj.insert("minute", minute); obj.insert("second", second); obj.insert("millisecond", millisecond); this->cb(scId, obj); } } void Globalization::getDateNames(int scId, int ecId, const QVariantMap &options) { Q_UNUSED(ecId) int type = options.find("type")->toInt(); int item = options.find("item")->toInt(); QLocale::FormatType format; if (type == FORMAT_SHORT) format = QLocale::ShortFormat; else format = QLocale::LongFormat; QLocale locale; QList res; if (item == REQUEST_DAY_NAMES) { for (int i = 1; i <= 7; i++) { res.append(locale.dayName(i, format)); } } else { //REQUEST_MONTH_NAMES for (int i = 1; i <= 12; i++) { res.append(locale.monthName(i, format)); } } QString result; for (QList::iterator it = res.begin(); it != res.end(); it++) { result += QString("'%1',").arg(*it); } this->callback(scId, QString("{ value: [ %1 ]}").arg(result)); } template static QString format(T number, Globalization::NumberType type) { QString res; QLocale locale; switch (type) { case Globalization::DECIMAL: res = locale.toString(number); break; case Globalization::PERCENT: res = locale.toString(number) + locale.percent(); break; case Globalization::CURRENCY: res = locale.toCurrencyString(number); break; }; return res; } void Globalization::numberToString(int scId, int ecId, const QVariantMap &options) { Q_UNUSED(ecId) bool isInt = options.find("isInt")->toBool(); NumberType type = static_cast(options.find("type")->toBool()); QString res; if (isInt) { long long number = options.find("number")->toLongLong(); res = format(number, type); } else { double number = options.find("number")->toDouble(); res = format(number, type); } this->callback(scId, QString("{ value: '%1' }").arg(res)); } void Globalization::stringToNumber(int scId, int ecId, int type, QString string) { switch ((NumberType)type) { case Globalization::DECIMAL: string = string.remove(QLocale().groupSeparator()); break; case Globalization::PERCENT: string = string.remove(QLocale().percent()).remove(QLocale().groupSeparator()); break; case Globalization::CURRENCY: string = string.remove(QLocale().currencySymbol()).remove(QLocale().groupSeparator()); break; }; bool ok; double res = QLocale().toDouble(string, &ok); if (ok) this->callback(scId, QString("{ value: %1 }").arg(res)); else this->callback(ecId, QString("new GlobalizationError(%1, 'parsing error')").arg(Globalization::PARSING_ERROR)); } static QString ustr2qstr(UnicodeString &ustr) { std::string res; ustr.toUTF8String(res); return QString(res.c_str()); } void Globalization::getNumberPattern(int scId, int ecId, int type) { Q_UNUSED(ecId); UErrorCode status = U_ZERO_ERROR; icu::DecimalFormat icu(status); icu::UnicodeString pattern; icu.toPattern(pattern); QLocale locale; QVariantMap obj; obj.insert("pattern", ustr2qstr(pattern)); switch ((NumberType)type) { case Globalization::DECIMAL: obj.insert("symbol", ""); break; case Globalization::PERCENT: obj.insert("symbol", QString(locale.percent())); break; case Globalization::CURRENCY: obj.insert("symbol", QString(locale.currencySymbol())); break; }; obj.insert("fraction", icu.getMaximumFractionDigits()); obj.insert("rounding", icu.getRoundingIncrement()); obj.insert("positive", QString(locale.positiveSign())); obj.insert("negative", QString(locale.negativeSign())); obj.insert("decimal", QString(locale.decimalPoint())); obj.insert("grouping", QString(locale.groupSeparator())); this->cb(scId, obj); } static bool inDayLightSavingsTime() { time_t now; time(&now); const tm *desc = std::localtime(&now); return desc->tm_isdst > 0; } void Globalization::getDatePattern(int scId, int ecId, int formatLength, int selector) { Q_UNUSED(ecId); QLocale locale; QVariantMap res; QLocale::FormatType format = translateFormat((Format)formatLength); switch ((Selector)selector) { case Selector::SELECTOR_TIME: res.insert("pattern", locale.timeFormat(format)); break; case Selector::SELECTOR_DATE: res.insert("pattern", locale.dateFormat(format)); break; case Selector::SELECTOR_ALL: res.insert("pattern", locale.dateTimeFormat(format)); break; }; UnicodeString result; QSharedPointer timezone = QSharedPointer(TimeZone::createDefault()); timezone->getDisplayName(inDayLightSavingsTime(), TimeZone::SHORT, result); res.insert("timezone", ustr2qstr(result)); res.insert("utc_offset", timezone->getRawOffset() / 1000 + timezone->getDSTSavings() / 1000); res.insert("dst_offset", timezone->getDSTSavings() / 1000); this->cb(scId, res); }