From 09fe2cd62df80373e602d47c570ae317a60a5293 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 8 Mar 2011 17:32:24 +0100 Subject: Using list patterns to get a string from list in QLocale. Reviewed-by: Denis Dzyubenko Task-number: QTBUG-17097 --- src/corelib/tools/qlocale.cpp | 39 ++++++++++++++++++++++++++++++++++ src/corelib/tools/qlocale.h | 4 +++- src/corelib/tools/qlocale_p.h | 4 ++++ src/corelib/tools/qlocale_unix.cpp | 2 ++ tests/auto/qlocale/tst_qlocale.cpp | 35 ++++++++++++++++++++++++++++++ tests/manual/qlocale/miscellaneous.cpp | 11 ++++++++++ tests/manual/qlocale/miscellaneous.h | 3 +++ util/local_database/cldr2qlocalexml.py | 20 +++++++++++++++++ util/local_database/qlocalexml2cpp.py | 23 +++++++++++++++++--- 9 files changed, 137 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 58ac867..c3d15d8 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -820,6 +820,45 @@ QString QLocale::quoteString(const QStringRef &str, QuotationStyle style) const } /*! + \since 4.8 + + Returns a string according to the current locale. +*/ +QString QLocale::createSeparatedList(const QStringList &strl) const +{ +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res; + res = systemLocale()->query(QSystemLocale::ListToSeparatedString, QVariant::fromValue(strl)); + + if (!res.isNull()) + return res.toString(); + } +#endif + + const int size = strl.size(); + if (size == 1) + return strl.at(0); + else if (size == 2) { + QString format = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_two_idx, d()->m_list_pattern_part_two_size); + return format.arg(strl.at(0), strl.at(1)); + } + else if (size > 2) { + QString formatStart = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_start_idx, d()->m_list_pattern_part_start_size); + QString formatMid = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_mid_idx, d()->m_list_pattern_part_mid_size); + QString formatEnd = getLocaleData(list_pattern_part_data + d()->m_list_pattern_part_end_idx, d()->m_list_pattern_part_end_size); + QString result = formatStart.arg(strl.at(0), strl.at(1)); + int i; + for (i = 2; i < size - 1; ++i) + result = formatMid.arg(result, strl.at(i)); + result = formatEnd.arg(result, strl.at(size - 1)); + return result; + } + + return QString(); +} + +/*! \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 d5c41d0..4cee162 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -113,7 +113,8 @@ public: UILanguages, // QStringList StringToStandardQuotation, // QString in: QStringRef to quote StringToAlternateQuotation, // QString in: QStringRef to quote - ScriptId // uint + ScriptId, // uint + ListToSeparatedString // QString }; virtual QVariant query(QueryType type, QVariant in) const; virtual QLocale fallbackLocale() const; @@ -751,6 +752,7 @@ public: QString quoteString(const QString &str, QuotationStyle style = StandardQuotation) const; QString quoteString(const QStringRef &str, QuotationStyle style = StandardQuotation) const; + QString createSeparatedList(const QStringList &strl) 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 1f73982..ab7fde6 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -180,6 +180,10 @@ public: quint16 m_quotation_start, m_quotation_end; quint16 m_alternate_quotation_start, m_alternate_quotation_end; + quint16 m_list_pattern_part_start_idx, m_list_pattern_part_start_size; + quint16 m_list_pattern_part_mid_idx, m_list_pattern_part_mid_size; + quint16 m_list_pattern_part_end_idx, m_list_pattern_part_end_size; + quint16 m_list_pattern_part_two_idx, m_list_pattern_part_two_size; quint16 m_short_date_format_idx, m_short_date_format_size; quint16 m_long_date_format_idx, m_long_date_format_size; quint16 m_short_time_format_idx, m_short_time_format_size; diff --git a/src/corelib/tools/qlocale_unix.cpp b/src/corelib/tools/qlocale_unix.cpp index 3701b2b..117e2e4 100644 --- a/src/corelib/tools/qlocale_unix.cpp +++ b/src/corelib/tools/qlocale_unix.cpp @@ -214,6 +214,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const return lc_messages.quoteString(in.value()); case StringToAlternateQuotation: return lc_messages.quoteString(in.value(), QLocale::AlternateQuotation); + case ListToSeparatedString: + return lc_messages.createSeparatedList(in.value()); default: break; } diff --git a/tests/auto/qlocale/tst_qlocale.cpp b/tests/auto/qlocale/tst_qlocale.cpp index cb69d54..b6c66d5 100644 --- a/tests/auto/qlocale/tst_qlocale.cpp +++ b/tests/auto/qlocale/tst_qlocale.cpp @@ -144,6 +144,7 @@ private slots: void quoteString(); void uiLanguages(); void weekendDays(); + void listPatterns(); private: QString m_decimal, m_thousand, m_sdate, m_ldate, m_time; @@ -2236,5 +2237,39 @@ void tst_QLocale::weekendDays() QCOMPARE(c.weekendEnd(), Qt::Sunday); } +void tst_QLocale::listPatterns() +{ + QStringList sl1; + QStringList sl2; + sl2 << "aaa"; + QStringList sl3; + sl3 << "aaa" << "bbb"; + QStringList sl4; + sl4 << "aaa" << "bbb" << "ccc"; + QStringList sl5; + sl5 << "aaa" << "bbb" << "ccc" << "ddd"; + + const QLocale c(QLocale::C); + QCOMPARE(c.createSeparatedList(sl1), QString("")); + QCOMPARE(c.createSeparatedList(sl2), QString("aaa")); + QCOMPARE(c.createSeparatedList(sl3), QString("aaa, bbb")); + QCOMPARE(c.createSeparatedList(sl4), QString("aaa, bbb, ccc")); + QCOMPARE(c.createSeparatedList(sl5), QString("aaa, bbb, ccc, ddd")); + + const QLocale en_US("en_US"); + QCOMPARE(en_US.createSeparatedList(sl1), QString("")); + QCOMPARE(en_US.createSeparatedList(sl2), QString("aaa")); + QCOMPARE(en_US.createSeparatedList(sl3), QString("aaa and bbb")); + QCOMPARE(en_US.createSeparatedList(sl4), QString("aaa, bbb, and ccc")); + QCOMPARE(en_US.createSeparatedList(sl5), QString("aaa, bbb, ccc, and ddd")); + + const QLocale zh_CN("zh_CN"); + QCOMPARE(zh_CN.createSeparatedList(sl1), QString("")); + QCOMPARE(zh_CN.createSeparatedList(sl2), QString("aaa")); + QCOMPARE(zh_CN.createSeparatedList(sl3), QString::fromUtf8("aaa" "\xe5\x92\x8c" "bbb")); + QCOMPARE(zh_CN.createSeparatedList(sl4), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe5\x92\x8c" "ccc")); + QCOMPARE(zh_CN.createSeparatedList(sl5), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe3\x80\x81" "ccc" "\xe5\x92\x8c" "ddd")); +} + QTEST_APPLESS_MAIN(tst_QLocale) #include "tst_qlocale.moc" diff --git a/tests/manual/qlocale/miscellaneous.cpp b/tests/manual/qlocale/miscellaneous.cpp index 0b2250a..a9694bf 100644 --- a/tests/manual/qlocale/miscellaneous.cpp +++ b/tests/manual/qlocale/miscellaneous.cpp @@ -49,6 +49,7 @@ MiscWidget::MiscWidget() createLineEdit("Alternate quotes:", &alternateQuotedTextLabel, &alternateQuotedText); textToQuote->setText("some text"); createLineEdit("Text direction:", &textDirectionLabel, &textDirection); + createLineEdit("List to seperated string:", &listToSeparatedStringLabel, &listToSeparatedStringText); l->addWidget(textToQuoteLabel, 0, 0); l->addWidget(textToQuote, 0, 1); @@ -58,6 +59,8 @@ MiscWidget::MiscWidget() l->addWidget(alternateQuotedText, 1, 3); l->addWidget(textDirectionLabel, 2, 0); l->addWidget(textDirection, 2, 1, 1, 3); + l->addWidget(listToSeparatedStringLabel, 3, 0); + l->addWidget(listToSeparatedStringText, 3, 1, 1, 3); connect(textToQuote, SIGNAL(textChanged(QString)), this, SLOT(updateQuotedText(QString))); @@ -72,10 +75,18 @@ void MiscWidget::updateQuotedText(QString str) alternateQuotedText->setText(locale().quoteString(str, QLocale::AlternateQuotation)); } +void MiscWidget::updateListToSeparatedStringText() +{ + QStringList test; + test << "aaa" << "bbb" << "ccc" << "ddd"; + listToSeparatedStringText->setText(locale().createSeparatedList(test)); +} + void MiscWidget::localeChanged(QLocale locale) { setLocale(locale); updateQuotedText(textToQuote->text()); + updateListToSeparatedStringText(); textDirection->setText(locale.textDirection() == Qt::LeftToRight ? "Left To Right" : "Right To Left"); } diff --git a/tests/manual/qlocale/miscellaneous.h b/tests/manual/qlocale/miscellaneous.h index 33d8ef9..3b635b8 100644 --- a/tests/manual/qlocale/miscellaneous.h +++ b/tests/manual/qlocale/miscellaneous.h @@ -56,14 +56,17 @@ private: QLabel *standardQuotedTextLabel; QLabel *alternateQuotedTextLabel; QLabel *textDirectionLabel; + QLabel *listToSeparatedStringLabel; QLineEdit *textToQuote; QLineEdit *standardQuotedText; QLineEdit *alternateQuotedText; QLineEdit *textDirection; + QLineEdit *listToSeparatedStringText; private slots: void localeChanged(QLocale locale); void updateQuotedText(QString str); + void updateListToSeparatedStringText(); }; #endif // MISCELLANEOUS_H diff --git a/util/local_database/cldr2qlocalexml.py b/util/local_database/cldr2qlocalexml.py index fb0e5db..a67971b 100755 --- a/util/local_database/cldr2qlocalexml.py +++ b/util/local_database/cldr2qlocalexml.py @@ -82,6 +82,14 @@ def parse_number_format(patterns, data): result.append(pattern) return result +def parse_list_pattern_part_format(pattern): + # this is a very limited parsing of the format for list pattern part only. + result = "" + result = pattern.replace("{0}", "%1") + result = result.replace("{1}", "%2") + result = result.replace("{2}", "%3") + return result + def ordStr(c): if len(c) == 1: return str(ord(c)) @@ -215,6 +223,10 @@ def generateLocaleInfo(path): result['quotationEnd'] = findEntry(path, "delimiters/quotationEnd") result['alternateQuotationStart'] = findEntry(path, "delimiters/alternateQuotationStart") result['alternateQuotationEnd'] = findEntry(path, "delimiters/alternateQuotationEnd") + result['listPatternPartStart'] = parse_list_pattern_part_format(findEntry(path, "listPatterns/listPattern/listPatternPart[start]")) + result['listPatternPartMiddle'] = parse_list_pattern_part_format(findEntry(path, "listPatterns/listPattern/listPatternPart[middle]")) + result['listPatternPartEnd'] = parse_list_pattern_part_format(findEntry(path, "listPatterns/listPattern/listPatternPart[end]")) + result['listPatternPartTwo'] = parse_list_pattern_part_format(findEntry(path, "listPatterns/listPattern/listPatternPart[2]")) 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")) @@ -689,6 +701,10 @@ print \ \"\n\ \'\n\ \'\n\ + %1, %2\n\ + %1, %2\n\ + %1, %2\n\ + %1, %2\n\ AM\n\ PM\n\ mon\n\ @@ -741,6 +757,10 @@ for key in locale_keys: print " " + l['quotationEnd'].encode('utf-8') + "" print " " + l['alternateQuotationStart'].encode('utf-8') + "" print " " + l['alternateQuotationEnd'].encode('utf-8') + "" + print " " + l['listPatternPartStart'].encode('utf-8') + "" + print " " + l['listPatternPartMiddle'].encode('utf-8') + "" + print " " + l['listPatternPartEnd'].encode('utf-8') + "" + print " " + l['listPatternPartTwo'].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 b8e4e89..e646999 100755 --- a/util/local_database/qlocalexml2cpp.py +++ b/util/local_database/qlocalexml2cpp.py @@ -251,6 +251,10 @@ class Locale: 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.listPatternPartStart = eltText(firstChildElt(elt, "listPatternPartStart")) + self.listPatternPartMiddle = eltText(firstChildElt(elt, "listPatternPartMiddle")) + self.listPatternPartEnd = eltText(firstChildElt(elt, "listPatternPartEnd")) + self.listPatternPartTwo = eltText(firstChildElt(elt, "listPatternPartTwo")) self.am = eltText(firstChildElt(elt, "am")) self.pm = eltText(firstChildElt(elt, "pm")) self.firstDayOfWeek = convertToQtDayOfWeek(eltText(firstChildElt(elt, "firstDayOfWeek"))) @@ -494,6 +498,7 @@ def main(): data_temp_file.write("\n") + list_pattern_part_data = StringData() date_format_data = StringData() time_format_data = StringData() months_data = StringData() @@ -507,7 +512,7 @@ def main(): # Locale data data_temp_file.write("static const QLocalePrivate locale_data[] = {\n") - data_temp_file.write("// lang script 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") + data_temp_file.write("// lang script terr dec group list prcnt zero minus plus exp quotStart quotEnd altQuotStart altQuotEnd lpStart lpMid lpEnd lpTwo 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 @@ -516,7 +521,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,%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,%6d,%6d }, // %s/%s/%s\n" \ + data_temp_file.write(" { %6d,%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}, %s,%s,%s,%s,%6d,%6d,%6d,%6d,%6d }, // %s/%s/%s\n" \ % (key[0], key[1], key[2], l.decimal, l.group, @@ -530,6 +535,10 @@ def main(): l.quotationEnd, l.alternateQuotationStart, l.alternateQuotationEnd, + list_pattern_part_data.append(l.listPatternPartStart), + list_pattern_part_data.append(l.listPatternPartMiddle), + list_pattern_part_data.append(l.listPatternPartEnd), + list_pattern_part_data.append(l.listPatternPartTwo), date_format_data.append(l.shortDateFormat), date_format_data.append(l.longDateFormat), time_format_data.append(l.shortTimeFormat), @@ -561,11 +570,19 @@ def main(): l.language, l.script, 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, 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, 0,0, 0,0, 0,0, 0, 0, 0, 0, 0 } // trailing 0s\n") data_temp_file.write("};\n") data_temp_file.write("\n") + # List patterns data + #check_static_char_array_length("list_pattern_part", list_pattern_part_data.data) + data_temp_file.write("static const ushort list_pattern_part_data[] = {\n") + data_temp_file.write(wrap_list(list_pattern_part_data.data)) + data_temp_file.write("\n};\n") + + data_temp_file.write("\n") + # Date format data #check_static_char_array_length("date_format", date_format_data.data) data_temp_file.write("static const ushort date_format_data[] = {\n") -- cgit v0.12