on xenial help sign in
implement logic for the Language page
commit8131d9cf3bf03038ef2ce925dc27e76c064f9557 authorLukáš Tinkl <lukas.tinkl@canonical.com> dateWed 24 Jun 2015, 23:21 (11 years ago) parent5c2db7c
11 files changed+303−110
plugins/Wizard/CMakeLists.txt+1 plugins/Wizard/LocalePlugin.cpp+74 plugins/Wizard/LocalePlugin.h+60 plugins/Wizard/plugin.cpp+2 qml/Wizard/Page.qml+7−9 qml/Wizard/Pages/10-language.qml+153 qml/Wizard/Pages/10-welcome.qml−99 qml/Wizard/StackButton.qml+2−1 tests/mocks/Ubuntu/SystemSettings/CMakeLists.txt+1−1 tests/mocks/Wizard/CMakeLists.txt+1 tests/mocks/Wizard/mockplugin.cpp+2
plugins/Wizard/CMakeLists.txt+1
@@ -2,6 +2,7 @@ add_library(Wizard-qml MODULE
22 plugin.cpp
33 PageList.cpp
44 System.cpp
5+ LocalePlugin.cpp
56 timezonemodel.cpp
67)
78
plugins/Wizard/LocalePlugin.cppnew file+74
@@ -0,0 +1,74 @@
1+/*
2+ * Copyright (C) 2015 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include <QLocale>
18+#include <QStringList>
19+
20+#include "LocalePlugin.h"
21+
22+LocaleAttached::LocaleAttached(QObject* parent)
23+ : QObject(parent)
24+{
25+}
26+
27+QJsonObject LocaleAttached::languages() const
28+{
29+ QJsonObject result;
30+ for (int i = QLocale::C + 1; i < QLocale::LastLanguage; ++i) {
31+ QLocale loc(static_cast<QLocale::Language>(i));
32+ result.insert(loc.name().split('_').first(), QLocale::languageToString(loc.language()));
33+ }
34+
35+ return result;
36+}
37+
38+QJsonObject LocaleAttached::localesForLanguage(const QString &code) const
39+{
40+ QLocale tmp(code);
41+ const QList<QLocale> allLocales = QLocale::matchingLocales(tmp.language(), QLocale::AnyScript, QLocale::AnyCountry);
42+ QJsonObject result;
43+ for(const QLocale &loc: allLocales) {
44+ //qDebug() << "Matching locale:" << loc.name();
45+ result.insert(loc.name(), QStringLiteral("%1 (%2)").arg(QLocale::languageToString(loc.language())).arg(QLocale::countryToString(loc.country())));
46+ }
47+ return result;
48+}
49+
50+QJsonObject LocaleAttached::countries() const
51+{
52+ const QList<QLocale> allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
53+ QJsonObject result;
54+
55+ for(const QLocale &loc: allLocales) {
56+ const QString countryCode = loc.name().section('_', 1, 1);
57+ if (!countryCode.isEmpty() && countryCode.length() == 2) {
58+ result.insert(countryCode, QLocale::countryToString(loc.country()));
59+ }
60+ }
61+
62+ return result;
63+}
64+
65+
66+LocalePlugin::LocalePlugin(QObject* parent)
67+ : QObject(parent)
68+{
69+}
70+
71+LocaleAttached* LocalePlugin::qmlAttachedProperties(QObject* parent)
72+{
73+ return new LocaleAttached(parent);
74+}
plugins/Wizard/LocalePlugin.hnew file+60
@@ -0,0 +1,60 @@
1+/*
2+ * Copyright (C) 2015 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef LOCALE_PLUGIN_H
18+#define LOCALE_PLUGIN_H
19+
20+#include <QObject>
21+#include <QString>
22+#include <QJsonObject>
23+#include <QtQml>
24+
25+class LocaleAttached: public QObject
26+{
27+ Q_OBJECT
28+protected:
29+ explicit LocaleAttached(QObject *parent = 0);
30+
31+public:
32+ Q_INVOKABLE QJsonObject languages() const;
33+ Q_INVOKABLE QJsonObject localesForLanguage(const QString &code) const;
34+ Q_INVOKABLE QJsonObject countries() const;
35+
36+ friend class LocalePlugin;
37+};
38+
39+/**
40+ * A simplified wrapper around QLocale.
41+ *
42+ * The wrapper is implemented as an attached property, which makes it possible
43+ * to use it as if its methods were static:
44+ *
45+ * @code
46+ * var langs = LocalePlugin.languages();
47+ * @endcode
48+ */
49+class LocalePlugin: public QObject
50+{
51+ Q_OBJECT
52+public:
53+ explicit LocalePlugin(QObject *parent = 0);
54+
55+ static LocaleAttached* qmlAttachedProperties(QObject *parent);
56+};
57+
58+QML_DECLARE_TYPEINFO(LocalePlugin, QML_HAS_ATTACHED_PROPERTIES)
59+
60+#endif // LOCALE_PLUGIN_H
plugins/Wizard/plugin.cpp+2
@@ -18,6 +18,7 @@
1818#include "PageList.h"
1919#include "System.h"
2020#include "timezonemodel.h"
21+#include "LocalePlugin.h"
2122
2223#include <QtQml/qqml.h>
2324
@@ -35,4 +36,5 @@ void WizardPlugin::registerTypes(const char *uri)
3536 qmlRegisterSingletonType<System>(uri, 0, 1, "System", system_provider);
3637 qmlRegisterType<TimeZoneModel>(uri, 0, 1, "TimeZoneModel");
3738 qmlRegisterType<TimeZoneFilterModel>(uri, 0, 1, "TimeZoneFilterModel");
39+ qmlRegisterType<LocalePlugin>(uri, 0, 1, "LocalePlugin");
3840}
qml/Wizard/Page.qml+7−9
@@ -18,12 +18,12 @@ import QtQuick 2.3
1818import Ubuntu.Components 1.1
1919
2020Item {
21− readonly property real buttonMargin: units.gu(2)
21+ readonly property real buttonMargin: units.gu(3)
2222 readonly property real buttonWidth: (width - buttonMargin * 2) / 2 -
2323 buttonMargin / 2
24− readonly property real topMargin: units.gu(8)
25− readonly property real leftMargin: units.gu(2)
26− readonly property real rightMargin: units.gu(2)
24+ readonly property real topMargin: units.gu(11)
25+ readonly property real leftMargin: units.gu(3)
26+ readonly property real rightMargin: units.gu(3)
2727
2828 // If you want to skip a page, mark skipValid false while you figure out
2929 // whether to skip, then set it to true once you've determined the value
@@ -43,9 +43,7 @@ Item {
4343 visible: false
4444 anchors.fill: parent
4545
46− // We want larger than even fontSize: "x-large", so we use a Text instead
47− // of a Label.
48− Text {
46+ Label {
4947 id: titleLabel
5048 anchors {
5149 top: parent.top
@@ -58,7 +56,7 @@ Item {
5856 wrapMode: Text.Wrap
5957 text: title
6058 color: Theme.palette.normal.baseText
61− font.pixelSize: units.gu(4)
59+ fontSize: "x-large"
6260 }
6361
6462 Item {
@@ -82,7 +80,7 @@ Item {
8280 anchors {
8381 left: parent.left
8482 bottom: parent.bottom
85− leftMargin: buttonMargin
83+ leftMargin: leftMargin
8684 bottomMargin: buttonMargin
8785 }
8886 z: 1
qml/Wizard/Pages/10-language.qmlnew file+153
@@ -0,0 +1,153 @@
1+/*
2+ * Copyright (C) 2013, 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.3
18+import Ubuntu.Components 1.2
19+import Ubuntu.SystemSettings.LanguagePlugin 1.0
20+import Wizard 0.1
21+import ".." as LocalComponents
22+
23+LocalComponents.Page {
24+ objectName: "languagePage"
25+
26+ title: i18n.tr("Language")
27+ forwardButtonSourceComponent: forwardButton
28+
29+ property string selectedLanguage: ""
30+
31+ UbuntuLanguagePlugin {
32+ id: plugin
33+ }
34+
35+ Component.onCompleted: {
36+ populateModel(); // FIXME pass a list of detected languages here
37+ }
38+
39+ function populateModel(detectedLangs)
40+ {
41+ console.log("LanguagePage::populateModel: detected languages:" + detectedLangs);
42+ var allLangs = LocalePlugin.languages();
43+ if (!!detectedLangs) {
44+ addLanguagesToModel(detectedLangs);
45+ var remainingLangs = Object.keys(allLangs).filter(function(lang) {
46+ return (detectedLangs.indexOf(lang) === -1);
47+ });
48+ addLanguagesToModel(remainingLangs); // FIXME this assumes an array
49+ } else {
50+ addLanguagesToModel(allLangs);
51+ }
52+
53+ busyIndicator.running = false;
54+ busyIndicator.visible = false;
55+ }
56+
57+ function addLanguagesToModel(langs)
58+ {
59+ Object.keys(langs).map(function(code) { // prepare the object
60+ return { "code": code, "name": langs[code] };
61+ })
62+ .sort(function(a, b) { // sort by language name, not code
63+ return a.name.localeCompare(b.name);
64+ })
65+ .forEach(function(language) { // build the model
66+ model.append(
67+ { "language": language.name,
68+ "code": language.code
69+ }
70+ );
71+ });
72+ }
73+
74+ ActivityIndicator {
75+ id: busyIndicator;
76+
77+ anchors.centerIn: parent;
78+ running: true;
79+ }
80+
81+ Column {
82+ id: column
83+ anchors.fill: content
84+ spacing: units.gu(1)
85+
86+ ListView {
87+ id: languagesListView;
88+
89+ boundsBehavior: Flickable.StopAtBounds;
90+ clip: true;
91+ currentIndex: -1
92+
93+ anchors {
94+ left: parent.left;
95+ right: parent.right;
96+ topMargin: topMargin;
97+ }
98+
99+ height: column.height - column.spacing - topMargin
100+
101+ section {
102+ property: "language";
103+ criteria: ViewSection.FirstCharacter;
104+ }
105+
106+ model: ListModel {
107+ id: model;
108+ }
109+
110+ delegate: ListItem {
111+ id: itemDelegate;
112+
113+ readonly property bool isCurrent: index === ListView.view.currentIndex
114+
115+ Label {
116+ text: language;
117+
118+ anchors {
119+ left: parent.left;
120+ right: parent.right;
121+ verticalCenter: parent.verticalCenter;
122+ }
123+
124+ fontSize: "medium"
125+ font.weight: itemDelegate.isCurrent ? Font.Normal : Font.Light
126+ }
127+
128+ onClicked: {
129+ selectedLanguage = code
130+ ListView.view.currentIndex = index
131+ print("Selected language: " + selectedLanguage)
132+ print("Current index: " + ListView.view.currentIndex)
133+ }
134+ }
135+ }
136+ }
137+
138+ Component {
139+ id: forwardButton
140+ LocalComponents.StackButton {
141+ text: i18n.tr("Next")
142+ enabled: selectedLanguage !== ""
143+ onClicked: {
144+ if (selectedLanguage !== plugin.languageCodes[plugin.currentLanguage]) {
145+ //plugin.currentLanguage = listview.currentIndex; // setting system language by some magic index? wtf
146+ //System.updateSessionLanguage(selectedLanguage); // TODO
147+ i18n.language = i18n.language; // re-notify of change after above call (for qlocale change)
148+ }
149+ pageStack.next()
150+ }
151+ }
152+ }
153+}
qml/Wizard/Pages/10-welcome.qmldeleted−99
@@ -1,99 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.3
18−import Ubuntu.Components 1.1
19−import Ubuntu.Components.ListItems 0.1
20−import Ubuntu.SystemSettings.LanguagePlugin 1.0
21−import Wizard 0.1
22−import ".." as LocalComponents
23−
24−LocalComponents.Page {
25− objectName: "languagePage"
26−
27− title: i18n.tr("Hi!")
28− forwardButtonSourceComponent: forwardButton
29−
30− UbuntuLanguagePlugin {
31− id: plugin
32− }
33−
34− Column {
35− id: column
36− anchors.fill: content
37− spacing: units.gu(1)
38−
39− Label {
40− id: label1
41− anchors.left: parent.left
42− anchors.right: parent.right
43− wrapMode: Text.Wrap
44− text: i18n.tr("Welcome to your Ubuntu phone.")
45− }
46−
47− Label {
48− id: label2
49− anchors.left: parent.left
50− anchors.right: parent.right
51− wrapMode: Text.Wrap
52− text: i18n.tr("Let’s get started.")
53− }
54−
55− Item { // spacer
56− height: units.gu(2)
57− width: units.gu(1) // needed else it will be ignored
58− }
59−
60− ComboButton {
61− id: combo
62− objectName: "languageCombo"
63− anchors.left: parent.left
64− anchors.right: parent.right
65− text: listview.currentItem.text
66− onClicked: expanded = !expanded
67− expandedHeight: column.height - combo.y
68− UbuntuListView {
69− id: listview
70− model: plugin.languageNames
71− currentIndex: plugin.currentLanguage
72− delegate: Standard {
73− objectName: "languageDelegate" + index
74− text: modelData
75− onClicked: {
76− listview.currentIndex = index
77− combo.expanded = false
78− i18n.language = plugin.languageCodes[index]
79− }
80− }
81− }
82− }
83− }
84−
85− Component {
86− id: forwardButton
87− LocalComponents.StackButton {
88− text: i18n.tr("Continue")
89− onClicked: {
90− if (plugin.currentLanguage !== listview.currentIndex) {
91− plugin.currentLanguage = listview.currentIndex;
92− System.updateSessionLanguage(plugin.languageCodes[listview.currentIndex]);
93− i18n.language = i18n.language; // re-notify of change after above call (for qlocale change)
94− }
95− pageStack.next()
96− }
97− }
98− }
99−}
qml/Wizard/StackButton.qml+2−1
@@ -15,7 +15,7 @@
1515 */
1616
1717import QtQuick 2.3
18−import Ubuntu.Components 1.1
18+import Ubuntu.Components 1.2
1919
2020AbstractButton {
2121 id: stackButton
@@ -33,6 +33,7 @@ AbstractButton {
3333 anchors.left: parent.left
3434 anchors.right: parent.right
3535 color: enabled ? Theme.palette.selected.backgroundText : Qt.darker(Theme.palette.selected.backgroundText, 1.5)
36+ font.weight: Font.DemiBold
3637 text: {
3738 if (backArrow) {
3839 // Translators: This is the arrow for "Back" buttons
tests/mocks/Ubuntu/SystemSettings/CMakeLists.txt+1−1
@@ -1,2 +1,2 @@
1−add_subdirectory(LanguagePlugin)
1+#add_subdirectory(LanguagePlugin)
22add_subdirectory(SecurityPrivacy)
tests/mocks/Wizard/CMakeLists.txt+1
@@ -7,6 +7,7 @@ add_library(MockWizard-qml MODULE
77 MockSystem.cpp
88 ${CMAKE_SOURCE_DIR}/plugins/Wizard/PageList.cpp
99 ${CMAKE_SOURCE_DIR}/plugins/Wizard/timezonemodel.cpp
10+ ${CMAKE_SOURCE_DIR}/plugins/Wizard/LocalePlugin.cpp
1011)
1112
1213qt5_use_modules(MockWizard-qml Qml)
tests/mocks/Wizard/mockplugin.cpp+2
@@ -18,6 +18,7 @@
1818#include "MockSystem.h"
1919#include "PageList.h"
2020#include "timezonemodel.h"
21+#include "LocalePlugin.h"
2122
2223#include <QtQml/qqml.h>
2324
@@ -35,4 +36,5 @@ void MockWizardPlugin::registerTypes(const char *uri)
3536 qmlRegisterSingletonType<MockSystem>(uri, 0, 1, "System", system_provider);
3637 qmlRegisterType<TimeZoneModel>(uri, 0, 1, "TimeZoneModel");
3738 qmlRegisterType<TimeZoneFilterModel>(uri, 0, 1, "TimeZoneFilterModel");
39+ qmlRegisterType<LocalePlugin>(uri, 0, 1, "LocalePlugin");
3840}