PageRenderTime 30ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/corelib/tools/qlocale_blackberry.cpp

https://gitlab.com/pteam/pteam-qtbase
C++ | 333 lines | 230 code | 54 blank | 49 comment | 47 complexity | 25b36150f4dc8dcca8838fb1c9726b87 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0, MIT
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
  4. ** Contact: http://www.qt-project.org/legal
  5. **
  6. ** This file is part of the QtCore module of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:LGPL21$
  9. ** Commercial License Usage
  10. ** Licensees holding valid commercial Qt licenses may use this file in
  11. ** accordance with the commercial license agreement provided with the
  12. ** Software or, alternatively, in accordance with the terms contained in
  13. ** a written agreement between you and Digia. For licensing terms and
  14. ** conditions see http://qt.digia.com/licensing. For further information
  15. ** use the contact form at http://qt.digia.com/contact-us.
  16. **
  17. ** GNU Lesser General Public License Usage
  18. ** Alternatively, this file may be used under the terms of the GNU Lesser
  19. ** General Public License version 2.1 or version 3 as published by the Free
  20. ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
  21. ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
  22. ** following information to ensure the GNU Lesser General Public License
  23. ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
  24. ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  25. **
  26. ** In addition, as a special exception, Digia gives you certain additional
  27. ** rights. These rights are described in the Digia Qt LGPL Exception
  28. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  29. **
  30. ** $QT_END_LICENSE$
  31. **
  32. ****************************************************************************/
  33. #include "qlocale_blackberry.h"
  34. #include "qlocale_p.h"
  35. #include "qdatetime.h"
  36. #include "qcoreapplication.h"
  37. #include "private/qcore_unix_p.h"
  38. #include <errno.h>
  39. #include <sys/pps.h>
  40. #include <unistd.h>
  41. QT_BEGIN_NAMESPACE
  42. #ifndef QT_NO_SYSTEMLOCALE
  43. static const char ppsUomPath[] = "/pps/services/locale/uom";
  44. static const char ppsRegionLocalePath[] = "/pps/services/locale/settings";
  45. static const char ppsLanguageLocalePath[] = "/pps/services/confstr/_CS_LOCALE";
  46. static const char ppsHourFormatPath[] = "/pps/system/settings";
  47. static const int MAX_PPS_SIZE = 16000;
  48. QBBSystemLocaleData::QBBSystemLocaleData()
  49. : languageNotifier(0)
  50. , regionNotifier(0)
  51. , measurementNotifier(0)
  52. , hourNotifier(0)
  53. {
  54. // Do not use qWarning to log warnings if qt_safe_open fails to open the pps file
  55. // since the user code may install a message handler that invokes QLocale API again
  56. // (i.e QDate, QDateTime, ...) which will cause a deadlock.
  57. if ((measurementFd = qt_safe_open(ppsUomPath, O_RDONLY)) == -1)
  58. fprintf(stderr, "Failed to open uom pps, errno=%d\n", errno);
  59. if ((regionFd = qt_safe_open(ppsRegionLocalePath, O_RDONLY)) == -1)
  60. fprintf(stderr, "Failed to open region pps, errno=%d\n", errno);
  61. if ((languageFd = qt_safe_open(ppsLanguageLocalePath, O_RDONLY)) == -1)
  62. fprintf(stderr, "Failed to open language pps, errno=%d\n", errno);
  63. if ((hourFd = qt_safe_open(ppsHourFormatPath, O_RDONLY)) == -1)
  64. fprintf(stderr, "Failed to open hour format pps, errno=%d\n", errno);
  65. // we cannot call this directly, because by the time this constructor is
  66. // called, the event dispatcher has not yet been created, causing the
  67. // subsequent call to QSocketNotifier constructor to fail.
  68. QMetaObject::invokeMethod(this, "installSocketNotifiers", Qt::QueuedConnection);
  69. readLanguageLocale();
  70. readRegionLocale();
  71. readMeasurementSystem();
  72. readHourFormat();
  73. }
  74. QBBSystemLocaleData::~QBBSystemLocaleData()
  75. {
  76. if (measurementFd != -1)
  77. qt_safe_close(measurementFd);
  78. if (languageFd != -1)
  79. qt_safe_close(languageFd);
  80. if (regionFd != -1)
  81. qt_safe_close(regionFd);
  82. if (hourFd != -1)
  83. qt_safe_close(hourFd);
  84. }
  85. uint QBBSystemLocaleData::measurementSystem()
  86. {
  87. return m_measurementSystem;
  88. }
  89. QVariant QBBSystemLocaleData::timeFormat(QLocale::FormatType formatType)
  90. {
  91. return getCorrectFormat(regionLocale().timeFormat(formatType), formatType);
  92. }
  93. QVariant QBBSystemLocaleData::dateTimeFormat(QLocale::FormatType formatType)
  94. {
  95. return getCorrectFormat(regionLocale().dateTimeFormat(formatType), formatType);
  96. }
  97. QLocale QBBSystemLocaleData::languageLocale()
  98. {
  99. if (!lc_language.isEmpty())
  100. return QLocale(QLatin1String(lc_language));
  101. return QLocale::c();
  102. }
  103. QLocale QBBSystemLocaleData::regionLocale()
  104. {
  105. if (!lc_region.isEmpty())
  106. return QLocale(QLatin1String(lc_region));
  107. return QLocale::c();
  108. }
  109. void QBBSystemLocaleData::installSocketNotifiers()
  110. {
  111. Q_ASSERT(!languageNotifier || !regionNotifier || !measurementNotifier || !hourNotifier);
  112. Q_ASSERT(QCoreApplication::instance());
  113. languageNotifier = new QSocketNotifier(languageFd, QSocketNotifier::Read, this);
  114. QObject::connect(languageNotifier, SIGNAL(activated(int)), this, SLOT(readLanguageLocale()));
  115. regionNotifier = new QSocketNotifier(regionFd, QSocketNotifier::Read, this);
  116. QObject::connect(regionNotifier, SIGNAL(activated(int)), this, SLOT(readRegionLocale()));
  117. measurementNotifier = new QSocketNotifier(measurementFd, QSocketNotifier::Read, this);
  118. QObject::connect(measurementNotifier, SIGNAL(activated(int)), this, SLOT(readMeasurementSystem()));
  119. hourNotifier = new QSocketNotifier(hourFd, QSocketNotifier::Read, this);
  120. QObject::connect(hourNotifier, SIGNAL(activated(int)), this, SLOT(readHourFormat()));
  121. }
  122. void QBBSystemLocaleData::readLanguageLocale()
  123. {
  124. lc_language = readPpsValue("_CS_LOCALE", languageFd);
  125. }
  126. void QBBSystemLocaleData::readRegionLocale()
  127. {
  128. lc_region = readPpsValue("region", regionFd);
  129. }
  130. void QBBSystemLocaleData::readMeasurementSystem()
  131. {
  132. QByteArray measurement = readPpsValue("uom", measurementFd);
  133. m_measurementSystem = (qstrcmp(measurement, "imperial") == 0) ? QLocale::ImperialSystem : QLocale::MetricSystem;
  134. }
  135. void QBBSystemLocaleData::readHourFormat()
  136. {
  137. QByteArray hourFormat = readPpsValue("hourFormat", hourFd);
  138. is24HourFormat = (qstrcmp(hourFormat, "24") == 0);
  139. }
  140. QByteArray QBBSystemLocaleData::readPpsValue(const char *ppsObject, int ppsFd)
  141. {
  142. QByteArray result;
  143. if (!ppsObject || ppsFd == -1)
  144. return result;
  145. // PPS objects are of unknown size, but must be read all at once.
  146. // Relying on the file size may not be a good idea since the size may change before reading.
  147. // Let's try with an initial size (512), and if the buffer is too small try with bigger one,
  148. // until we succeed or until other non buffer-size-related error occurs.
  149. // Using QVarLengthArray means the first try (of size == 512) uses a buffer on the stack - no allocation necessary.
  150. // Hopefully that covers most use cases.
  151. int bytes;
  152. QVarLengthArray<char, 512> buffer(512);
  153. for (;;) {
  154. errno = 0;
  155. bytes = qt_safe_read(ppsFd, buffer.data(), buffer.size() - 1);
  156. const bool bufferIsTooSmall = (bytes == -1 && errno == EMSGSIZE && buffer.size() < MAX_PPS_SIZE);
  157. if (!bufferIsTooSmall)
  158. break;
  159. buffer.resize(qMin(buffer.size()*2, MAX_PPS_SIZE));
  160. }
  161. // This method is called in the ctor(), so do not use qWarning to log warnings
  162. // if qt_safe_read fails to read the pps file
  163. // since the user code may install a message handler that invokes QLocale API again
  164. // (i.e QDate, QDateTime, ...) which will cause a deadlock.
  165. if (bytes == -1) {
  166. fprintf(stderr, "Failed to read pps object:%s, errno=%d\n", ppsObject, errno);
  167. return result;
  168. }
  169. // ensure data is null terminated
  170. buffer[bytes] = '\0';
  171. pps_decoder_t ppsDecoder;
  172. pps_decoder_initialize(&ppsDecoder, 0);
  173. if (pps_decoder_parse_pps_str(&ppsDecoder, buffer.data()) == PPS_DECODER_OK) {
  174. pps_decoder_push(&ppsDecoder, 0);
  175. const char *ppsBuff;
  176. if (pps_decoder_get_string(&ppsDecoder, ppsObject, &ppsBuff) == PPS_DECODER_OK) {
  177. result = ppsBuff;
  178. } else {
  179. int val;
  180. if (pps_decoder_get_int(&ppsDecoder, ppsObject, &val) == PPS_DECODER_OK)
  181. result = QByteArray::number(val);
  182. }
  183. }
  184. pps_decoder_cleanup(&ppsDecoder);
  185. return result;
  186. }
  187. QString QBBSystemLocaleData::getCorrectFormat(const QString &baseFormat, QLocale::FormatType formatType)
  188. {
  189. QString format = baseFormat;
  190. if (is24HourFormat) {
  191. if (format.contains(QStringLiteral("AP"), Qt::CaseInsensitive)) {
  192. format.replace(QStringLiteral("AP"), QStringLiteral(""), Qt::CaseInsensitive);
  193. format.replace(QStringLiteral("h"), QStringLiteral("H"), Qt::CaseSensitive);
  194. }
  195. } else {
  196. if (!format.contains(QStringLiteral("AP"), Qt::CaseInsensitive)) {
  197. format.contains(QStringLiteral("HH"), Qt::CaseSensitive) ?
  198. format.replace(QStringLiteral("HH"), QStringLiteral("hh"), Qt::CaseSensitive) :
  199. format.replace(QStringLiteral("H"), QStringLiteral("h"), Qt::CaseSensitive);
  200. formatType == QLocale::LongFormat ? format.append(QStringLiteral(" AP t")) : format.append(QStringLiteral(" AP"));
  201. }
  202. }
  203. return format;
  204. }
  205. Q_GLOBAL_STATIC(QBBSystemLocaleData, bbSysLocaleData)
  206. QLocale QSystemLocale::fallbackUiLocale() const
  207. {
  208. return bbSysLocaleData()->languageLocale();
  209. }
  210. QVariant QSystemLocale::query(QueryType type, QVariant in) const
  211. {
  212. QBBSystemLocaleData *d = bbSysLocaleData();
  213. QReadLocker locker(&d->lock);
  214. const QLocale &lc_language = d->languageLocale();
  215. const QLocale &lc_region = d->regionLocale();
  216. switch (type) {
  217. case DecimalPoint:
  218. return lc_region.decimalPoint();
  219. case GroupSeparator:
  220. return lc_region.groupSeparator();
  221. case NegativeSign:
  222. return lc_region.negativeSign();
  223. case PositiveSign:
  224. return lc_region.positiveSign();
  225. case DateFormatLong:
  226. return lc_region.dateFormat(QLocale::LongFormat);
  227. case DateFormatShort:
  228. return lc_region.dateFormat(QLocale::ShortFormat);
  229. case TimeFormatLong:
  230. return d->timeFormat(QLocale::LongFormat);
  231. case TimeFormatShort:
  232. return d->timeFormat(QLocale::ShortFormat);
  233. case DateTimeFormatLong:
  234. return d->dateTimeFormat(QLocale::LongFormat);
  235. case DateTimeFormatShort:
  236. return d->dateTimeFormat(QLocale::ShortFormat);
  237. case DayNameLong:
  238. return lc_language.dayName(in.toInt(), QLocale::LongFormat);
  239. case DayNameShort:
  240. return lc_language.dayName(in.toInt(), QLocale::ShortFormat);
  241. case MonthNameLong:
  242. return lc_language.monthName(in.toInt(), QLocale::LongFormat);
  243. case MonthNameShort:
  244. return lc_language.monthName(in.toInt(), QLocale::ShortFormat);
  245. case StandaloneMonthNameLong:
  246. return lc_language.standaloneMonthName(in.toInt(), QLocale::LongFormat);
  247. case StandaloneMonthNameShort:
  248. return lc_language.standaloneMonthName(in.toInt(), QLocale::ShortFormat);
  249. case DateToStringLong:
  250. return lc_region.toString(in.toDate(), QLocale::LongFormat);
  251. case DateToStringShort:
  252. return lc_region.toString(in.toDate(), QLocale::ShortFormat);
  253. case TimeToStringLong:
  254. return lc_region.toString(in.toTime(), d->timeFormat(QLocale::LongFormat).toString());
  255. case TimeToStringShort:
  256. return lc_region.toString(in.toTime(), d->timeFormat(QLocale::ShortFormat).toString());
  257. case DateTimeToStringShort:
  258. return lc_region.toString(in.toDateTime(), d->dateTimeFormat(QLocale::ShortFormat).toString());
  259. case DateTimeToStringLong:
  260. return lc_region.toString(in.toDateTime(), d->dateTimeFormat(QLocale::LongFormat).toString());
  261. case MeasurementSystem:
  262. return d->measurementSystem();
  263. case ZeroDigit:
  264. return lc_region.zeroDigit();
  265. case CountryId:
  266. return lc_region.country();
  267. case LanguageId:
  268. return lc_language.language();
  269. case AMText:
  270. return lc_language.amText();
  271. case PMText:
  272. return lc_language.pmText();
  273. default:
  274. break;
  275. }
  276. return QVariant();
  277. }
  278. #endif
  279. QT_END_NAMESPACE