From aa9bc750eb72a180f15be144d2cc6621289f59f5 Mon Sep 17 00:00:00 2001 From: Zeno Albisser Date: Wed, 16 Feb 2011 14:18:22 +0100 Subject: Implemented QLocale::quoteString(...) Reviewed-by: Denis Dzyubenko Task-number: QTBUG-17096 --- src/corelib/tools/qlocale.cpp | 86 ++++++++++++++++++++++++++++++++++ src/corelib/tools/qlocale.h | 8 +++- src/corelib/tools/qlocale_p.h | 2 + tests/auto/qlocale/tst_qlocale.cpp | 16 +++++++ util/local_database/cldr2qlocalexml.py | 12 +++++ util/local_database/qlocalexml2cpp.py | 18 +++++-- 6 files changed, 138 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 985889c..10ad0cc 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -59,6 +59,7 @@ QT_END_NAMESPACE #include "qdatetime.h" #include "qstringlist.h" #include "qvariant.h" +#include "qstringbuilder.h" #if defined(Q_WS_WIN) # include "qt_windows.h" # include @@ -1313,6 +1314,33 @@ static QString macFormatCurrency(const QVariant &in) return QCFString::toQString(result); } +static QVariant macQuotationSymbol(QSystemLocale::QueryType type, const QVariant &in) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_6) + return QVariant(); + + QCFType locale = CFLocaleCopyCurrent(); + switch (type) { + case QSystemLocale::QuotationBegin: + if (in.toInt() == QLocale::StandardQuotation) + return QCFString::toQString(static_cast(CFLocaleGetValue(locale, kCFLocaleQuotationBeginDelimiterKey))); + else + return QCFString::toQString(static_cast(CFLocaleGetValue(locale, kCFLocaleAlternateQuotationBeginDelimiterKey))); + break; + case QSystemLocale::QuotationEnd: + if (in.toInt() == QLocale::StandardQuotation) + return QCFString::toQString(static_cast(CFLocaleGetValue(locale, kCFLocaleQuotationEndDelimiterKey))); + else + return QCFString::toQString(static_cast(CFLocaleGetValue(locale, kCFLocaleAlternateQuotationEndDelimiterKey))); + break; + default: + break; + } +#endif + return QVariant(); +} + static void getMacPreferredLanguageAndCountry(QString *language, QString *country) { QCFType languages = (CFArrayRef)CFPreferencesCopyValue( @@ -1400,6 +1428,10 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const return QVariant(macCurrencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()))); case FormatCurrency: return macFormatCurrency(in); + case QuotationBegin: + case QuotationEnd: { + return macQuotationSymbol(type,in); + } default: break; } @@ -1541,6 +1573,8 @@ Q_GLOBAL_STATIC(QLocalePrivate, globalLocalePrivate) \value PMText a string that represents the system PM designator associated with a 12-hour clock. \value CurrencySymbol a string that represents a currency in a format QLocale::CurrencyFormat. \value FormatCurrency a localized string representation of a number with a currency symbol. + \value QuotationBegin a QString specifying the start of a quotation. the in variant contains a QLocale::QuotationStyle + \value QuotationEnd a QString specifying the end of a quotation. the in variant contains a QLocale::QuotationStyle */ /*! @@ -2328,6 +2362,21 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l) locale specified; otherwise returns false. */ +/*! + \enum QLocale::QuotationStyle + + This enum defines a set of possible styles for locale specific quotation. + + \value StandardQuotation If this option is set, the standard quotation marks + will be used to quote strings. + \value AlternateQuotation If this option is set, the alternate quotation marks + will be used to quote strings. + + \since 4.8 + + \sa quoteString() +*/ + static const int locale_data_size = sizeof(locale_data)/sizeof(QLocalePrivate) - 1; static const QLocalePrivate *dataPointerHelper(quint16 index) @@ -2491,6 +2540,43 @@ QLocale::NumberOptions QLocale::numberOptions() const } /*! + \since 4.8 + + Returns \a str quoted according to the current locale. + + If \a AlternateQuotation is used for \a QuoatationStyle + but the locale does not provide an alternate quotation, + we will fallback to the parent locale. +*/ +QString QLocale::quoteString(const QString &str, QuotationStyle qs) const +{ + + return quoteString(&str, qs); +} + +/*! + \since 4.8 + + \overload +*/ +QString QLocale::quoteString(const QStringRef &str, QuotationStyle qs) const +{ +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant quotationBegin = systemLocale()->query(QSystemLocale::QuotationBegin, QVariant(qs)); + QVariant quotationEnd = systemLocale()->query(QSystemLocale::QuotationEnd, QVariant(qs)); + if (!quotationBegin.isNull() && !quotationEnd.isNull()) + return quotationBegin.toString() % str % quotationEnd.toString(); + } +#endif + + if (qs == StandardQuotation) + return QChar(d()->m_quotation_start) % str % QChar(d()->m_quotation_end); + else + return QChar(d()->m_alternate_quotation_start) % str % QChar(d()->m_alternate_quotation_end); +} + +/*! \nonreentrant Sets the global default locale to \a locale. These diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index 225ae9c..924cb7b 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -97,7 +97,9 @@ public: PMText, // QString FirstDayOfWeek, // Qt::DayOfWeek CurrencySymbol, // QString in: format - FormatCurrency // QString in: qlonglong, qulonglong or double + FormatCurrency, // QString in: qlonglong, qulonglong or double + QuotationBegin, // QString in: StandardQuotation or AlternateQuotation + QuotationEnd // QString in: StandardQuotation or AlternateQuotation }; virtual QVariant query(QueryType type, QVariant in) const; virtual QLocale fallbackLocale() const; @@ -707,6 +709,10 @@ public: void setNumberOptions(NumberOptions options); NumberOptions numberOptions() const; + enum QuotationStyle { StandardQuotation, AlternateQuotation }; + QString quoteString(const QString &str, QuotationStyle qs = StandardQuotation) const; + QString quoteString(const QStringRef &str, QuotationStyle qs = StandardQuotation) const; + //private: // this should be private, but can't be struct Data { quint16 index; diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index 283f722..1d286ab 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -164,6 +164,8 @@ public: quint16 m_decimal, m_group, m_list, m_percent, m_zero, m_minus, m_plus, m_exponential; + quint16 m_quotation_start, m_quotation_end; + quint16 m_alternate_quotation_start, m_alternate_quotation_end; quint16 m_short_date_format_idx, m_short_date_format_size; quint16 m_long_date_format_idx, m_long_date_format_size; diff --git a/tests/auto/qlocale/tst_qlocale.cpp b/tests/auto/qlocale/tst_qlocale.cpp index 3217e5e..250aac9 100644 --- a/tests/auto/qlocale/tst_qlocale.cpp +++ b/tests/auto/qlocale/tst_qlocale.cpp @@ -141,6 +141,7 @@ private slots: void ampm(); void currency(); + void quoteString(); private: QString m_decimal, m_thousand, m_sdate, m_ldate, m_time; @@ -1122,6 +1123,8 @@ void tst_QLocale::macDefaultLocale() QCOMPARE(locale.dayName(7), QString("Sunday")); QCOMPARE(locale.monthName(1), QString("January")); QCOMPARE(locale.monthName(12), QString("December")); + QCOMPARE(locale.quoteString("string"), QString::fromUtf8("\xe2\x80\x9c" "string" "\xe2\x80\x9d")); + QCOMPARE(locale.quoteString("string", QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\x98" "string" "\xe2\x80\x99")); } @@ -2153,5 +2156,18 @@ void tst_QLocale::currency() QCOMPARE(de_DE.toCurrencyString(double(-1234.56)), QString::fromUtf8("-1234,56\xc2\xa0\xe2\x82\xac")); } +void tst_QLocale::quoteString() +{ + const QString someText("text"); + const QLocale c(QLocale::C); + QCOMPARE(c.quoteString(someText), QString::fromUtf8("\x22" "text" "\x22")); + QCOMPARE(c.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\x27" "text" "\x27")); + + const QLocale de_CH("de_CH"); + QCOMPARE(de_CH.quoteString(someText), QString::fromUtf8("\xc2\xab" "text" "\xc2\xbb")); + QCOMPARE(de_CH.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\xb9" "text" "\xe2\x80\xba")); + +} + QTEST_APPLESS_MAIN(tst_QLocale) #include "tst_qlocale.moc" diff --git a/util/local_database/cldr2qlocalexml.py b/util/local_database/cldr2qlocalexml.py index b873565..0bc1664 100755 --- a/util/local_database/cldr2qlocalexml.py +++ b/util/local_database/cldr2qlocalexml.py @@ -199,6 +199,10 @@ def generateLocaleInfo(path): result['minus'] = get_number_in_system(path, "numbers/symbols/minusSign", numbering_system) result['plus'] = get_number_in_system(path, "numbers/symbols/plusSign", numbering_system) result['exp'] = get_number_in_system(path, "numbers/symbols/exponential", numbering_system).lower() + result['quotationStart'] = findEntry(path, "delimiters/quotationStart") + result['quotationEnd'] = findEntry(path, "delimiters/quotationEnd") + result['alternateQuotationStart'] = findEntry(path, "delimiters/alternateQuotationStart") + result['alternateQuotationEnd'] = findEntry(path, "delimiters/alternateQuotationEnd") result['am'] = findEntry(path, "dates/calendars/calendar[gregorian]/dayPeriods/dayPeriodContext[format]/dayPeriodWidth[wide]/dayPeriod[am]", draft) result['pm'] = findEntry(path, "dates/calendars/calendar[gregorian]/dayPeriods/dayPeriodContext[format]/dayPeriodWidth[wide]/dayPeriod[pm]", draft) result['longDateFormat'] = convert_date(findEntry(path, "dates/calendars/calendar[gregorian]/dateFormats/dateFormatLength[full]/dateFormat/pattern")) @@ -600,6 +604,10 @@ print \ 45\n\ 43\n\ 101\n\ + \"\n\ + \"\n\ + \'\n\ + \'\n\ AM\n\ PM\n\ mon\n\ @@ -644,6 +652,10 @@ for key in locale_keys: print " " + ordStr(l['minus']) + "" print " " + ordStr(l['plus']) + "" print " " + fixOrdStrExp(l['exp']) + "" + print " " + l['quotationStart'].encode('utf-8') + "" + print " " + l['quotationEnd'].encode('utf-8') + "" + print " " + l['alternateQuotationStart'].encode('utf-8') + "" + print " " + l['alternateQuotationEnd'].encode('utf-8') + "" print " " + l['am'].encode('utf-8') + "" print " " + l['pm'].encode('utf-8') + "" print " " + l['firstDayOfWeek'].encode('utf-8') + "" diff --git a/util/local_database/qlocalexml2cpp.py b/util/local_database/qlocalexml2cpp.py index 2f998f3..6b8fdb9 100755 --- a/util/local_database/qlocalexml2cpp.py +++ b/util/local_database/qlocalexml2cpp.py @@ -195,6 +195,10 @@ def convertToQtDayOfWeek(firstDay): qtDayOfWeek = {"mon":1, "tue":2, "wed":3, "thu":4, "fri":5, "sat":6, "sun":7} return qtDayOfWeek[firstDay] +def assertSingleChar(string): + assert len(string) == 1, "This string is not allowed to be longer than 1 character" + return string + class Locale: def __init__(self, elt): self.language = eltText(firstChildElt(elt, "language")) @@ -207,6 +211,10 @@ class Locale: self.minus = int(eltText(firstChildElt(elt, "minus"))) self.plus = int(eltText(firstChildElt(elt, "plus"))) self.exp = int(eltText(firstChildElt(elt, "exp"))) + self.quotationStart = ord(assertSingleChar(eltText(firstChildElt(elt, "quotationStart")))) + self.quotationEnd = ord(assertSingleChar(eltText(firstChildElt(elt, "quotationEnd")))) + self.alternateQuotationStart = ord(assertSingleChar(eltText(firstChildElt(elt, "alternateQuotationStart")))) + self.alternateQuotationEnd = ord(assertSingleChar(eltText(firstChildElt(elt, "alternateQuotationEnd")))) self.am = eltText(firstChildElt(elt, "am")) self.pm = eltText(firstChildElt(elt, "pm")) self.firstDayOfWeek = convertToQtDayOfWeek(eltText(firstChildElt(elt, "firstDayOfWeek"))) @@ -433,7 +441,7 @@ def main(): # Locale data data_temp_file.write("static const QLocalePrivate locale_data[] = {\n") - data_temp_file.write("// lang terr dec group list prcnt zero minus plus exp sDtFmt lDtFmt sTmFmt lTmFmt ssMonth slMonth sMonth lMonth sDays lDays am,len pm,len\n") + data_temp_file.write("// lang terr dec group list prcnt zero minus plus exp quotStart quotEnd altQuotStart altQuotEnd sDtFmt lDtFmt sTmFmt lTmFmt ssMonth slMonth sMonth lMonth sDays lDays am,len pm,len\n") locale_keys = locale_map.keys() compareLocaleKeys.default_map = default_map @@ -443,7 +451,7 @@ def main(): for key in locale_keys: l = locale_map[key] - data_temp_file.write(" { %6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s, {%s}, %s,%s,%s,%s,%6d,%6d,%6d }, // %s/%s\n" \ + data_temp_file.write(" { %6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s, {%s}, %s,%s,%s,%s,%6d,%6d,%6d }, // %s/%s\n" \ % (key[0], key[1], l.decimal, l.group, @@ -453,6 +461,10 @@ def main(): l.minus, l.plus, l.exp, + l.quotationStart, + l.quotationEnd, + l.alternateQuotationStart, + l.alternateQuotationEnd, date_format_data.append(l.shortDateFormat), date_format_data.append(l.longDateFormat), time_format_data.append(l.shortTimeFormat), @@ -481,7 +493,7 @@ def main(): l.firstDayOfWeek, l.language, l.country)) - data_temp_file.write(" { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, {0,0,0}, 0,0, 0,0, 0,0, 0,0, 0, 0, 0 } // trailing 0s\n") + data_temp_file.write(" { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, {0,0,0}, 0,0, 0,0, 0,0, 0,0, 0, 0, 0 } // trailing 0s\n") data_temp_file.write("};\n") data_temp_file.write("\n") -- cgit v0.12