on xenial help sign in
add timezone selection page
commit3d7025ad26172fa53841c009d39a14072e88eafd authorLukáš Tinkl <lukas.tinkl@canonical.com> dateMon 22 Jun 2015, 20:05 (11 years ago) parent1332e4c
8 files changed+207−10
plugins/Wizard/PageList.cpp+4−4 plugins/Wizard/System.cpp+1−2 plugins/Wizard/plugin.cpp+1 plugins/Wizard/timezonemodel.cpp+41−3 plugins/Wizard/timezonemodel.h+25−1 qml/Wizard/Pages/45-timezone.qml+131 tests/mocks/Wizard/CMakeLists.txt+1 tests/mocks/Wizard/mockplugin.cpp+3
plugins/Wizard/PageList.cpp+4−4
@@ -40,20 +40,20 @@ PageList::PageList(QObject *parent)
4040 m_index(-1),
4141 m_pages()
4242{
43− QString qmlSuffix = ".qml";
44− QString disabledSuffix = ".disabled";
43+ const QString qmlSuffix = ".qml";
44+ const QString disabledSuffix = ".disabled";
4545 QSet<QString> disabledPages;
4646 QStringList dataDirs;
4747
4848 if (!isRunningInstalled() && getenv("UNITY_TEST_ENV") == nullptr) {
49− dataDirs = QStringList() << qmlDirectory();
49+ dataDirs << qmlDirectory();
5050 } else {
5151 dataDirs = shellDataDirs();
5252 }
5353
5454 Q_FOREACH(const QString &dataDir, dataDirs) {
5555 QDir dir(dataDir + "/Wizard/Pages");
56− QStringList entries = dir.entryList(QStringList("[0-9]*"), QDir::Files | QDir::Readable);
56+ const QStringList entries = dir.entryList(QStringList("[0-9]*"), QDir::Files | QDir::Readable);
5757 Q_FOREACH(const QString &entry, entries) {
5858 if (!m_pages.contains(entry) && entry.endsWith(qmlSuffix))
5959 m_pages.insert(entry, dir.absoluteFilePath(entry));
plugins/Wizard/System.cpp+1−2
@@ -25,8 +25,7 @@
2525#include <QProcess>
2626
2727System::System()
28− : QObject(),
29− m_fsWatcher()
28+ : QObject()
3029{
3130 // Register the argument needed for UpdateActivationEnvironment below
3231 qDBusRegisterMetaType<QMap<QString,QString>>();
plugins/Wizard/plugin.cpp+1
@@ -34,4 +34,5 @@ void WizardPlugin::registerTypes(const char *uri)
3434 qmlRegisterType<PageList>(uri, 0, 1, "PageList");
3535 qmlRegisterSingletonType<System>(uri, 0, 1, "System", system_provider);
3636 qmlRegisterType<TimeZoneModel>(uri, 0, 1, "TimeZoneModel");
37+ qmlRegisterType<TimeZoneFilterModel>(uri, 0, 1, "TimeZoneFilterModel");
3738}
plugins/Wizard/timezonemodel.cpp+41−3
@@ -25,7 +25,7 @@
2525TimeZoneModel::TimeZoneModel(QObject *parent)
2626 : QAbstractListModel(parent)
2727{
28− QMetaObject::invokeMethod(this, "init");
28+ init();
2929}
3030
3131QString TimeZoneModel::selectedZoneId() const
@@ -72,8 +72,10 @@ QVariant TimeZoneModel::data(const QModelIndex &index, int role) const
7272 }
7373 case Comment:
7474 return tz.comment();
75+ case Time:
76+ return QDateTime::currentDateTime().toTimeZone(tz).toString("H:mm");
7577 default:
76− qWarning() << Q_FUNC_INFO << "Unsupported data role";
78+ qWarning() << Q_FUNC_INFO << "Unsupported data role" << role;
7779 break;
7880 }
7981 }
@@ -83,7 +85,7 @@ QVariant TimeZoneModel::data(const QModelIndex &index, int role) const
8385
8486QHash<int, QByteArray> TimeZoneModel::roleNames() const
8587{
86− return {{IdRole, "id"}, {Abbreviation, "abbreviation"}, {Country, "country"}, {City, "city"}, {Comment, "comment"}};
88+ return {{IdRole, "id"}, {Abbreviation, "abbreviation"}, {Country, "country"}, {City, "city"}, {Comment, "comment"}, {Time, "time"}};
8789}
8890
8991void TimeZoneModel::init()
@@ -92,3 +94,39 @@ void TimeZoneModel::init()
9294 m_zoneIds = QTimeZone::availableTimeZoneIds();
9395 endResetModel();
9496}
97+
98+
99+TimeZoneFilterModel::TimeZoneFilterModel(QObject *parent)
100+ : QSortFilterProxyModel(parent)
101+{
102+ m_stringMatcher.setCaseSensitivity(Qt::CaseInsensitive);
103+}
104+
105+bool TimeZoneFilterModel::filterAcceptsRow(int row, const QModelIndex &parentIndex) const
106+{
107+ if (!sourceModel() || m_filter.isEmpty()) {
108+ return true;
109+ }
110+
111+ const QString city = sourceModel()->index(row, 0, parentIndex).data(TimeZoneModel::City).toString();
112+ const QString country = sourceModel()->index(row, 0, parentIndex).data(TimeZoneModel::Country).toString();
113+
114+ if (m_stringMatcher.indexIn(city) != -1 || m_stringMatcher.indexIn(country) != -1) {
115+ return true;
116+ }
117+
118+ return false;
119+}
120+
121+QString TimeZoneFilterModel::filter() const
122+{
123+ return m_filter;
124+}
125+
126+void TimeZoneFilterModel::setFilter(const QString &filter)
127+{
128+ m_filter = filter;
129+ m_stringMatcher.setPattern(m_filter);
130+ Q_EMIT filterChanged();
131+ invalidate();
132+}
plugins/Wizard/timezonemodel.h+25−1
@@ -18,18 +18,42 @@
1818#define TIMEZONEMODEL_H
1919
2020#include <QAbstractListModel>
21+#include <QSortFilterProxyModel>
22+
23+class TimeZoneFilterModel : public QSortFilterProxyModel
24+{
25+ Q_OBJECT
26+ Q_PROPERTY(QString filter READ filter WRITE setFilter NOTIFY filterChanged)
27+
28+public:
29+ explicit TimeZoneFilterModel(QObject *parent = 0);
30+ ~TimeZoneFilterModel() = default;
31+ bool filterAcceptsRow(int row, const QModelIndex &parentIndex) const override;
32+
33+ QString filter() const;
34+ void setFilter(const QString &filter);
35+
36+Q_SIGNALS:
37+ void filterChanged();
38+
39+private:
40+ QString m_filter;
41+ QStringMatcher m_stringMatcher;
42+};
2143
2244class TimeZoneModel: public QAbstractListModel
2345{
2446 Q_OBJECT
2547 Q_PROPERTY(QString selectedZoneId READ selectedZoneId WRITE setSelectedZoneId NOTIFY selectedZoneIdChanged)
48+ Q_ENUMS(Roles)
2649public:
2750 enum Roles {
2851 IdRole = Qt::UserRole + 1,
2952 Abbreviation,
3053 Country,
3154 City,
32− Comment
55+ Comment,
56+ Time
3357 };
3458
3559 explicit TimeZoneModel(QObject *parent = nullptr);
qml/Wizard/Pages/45-timezone.qmlnew file+131
@@ -0,0 +1,131 @@
1+/*
2+ * Copyright (C) 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 QtQuick.Layouts 1.1
19+import Ubuntu.Components 1.2
20+import Wizard 0.1
21+import ".." as LocalComponents
22+
23+LocalComponents.Page {
24+ id: tzPage
25+ objectName: "tzPage"
26+
27+ title: i18n.tr("Time Zone")
28+ forwardButtonSourceComponent: forwardButton
29+
30+ readonly property alias selectedTimeZone: tzModel.selectedZoneId
31+
32+ TimeZoneModel {
33+ id: tzModel
34+ }
35+
36+ TimeZoneFilterModel {
37+ id: tzFilterModel
38+ sourceModel: tzModel
39+ filter: searchField.text
40+ }
41+
42+ Component {
43+ id: tzComponent
44+ ListItem {
45+ id: tz
46+ objectName: "tz"
47+ property QtObject tzData: null
48+
49+ Label {
50+ id: cityLabel
51+ text: tzData.city
52+ anchors.left: parent.left
53+ anchors.top: parent.top
54+ }
55+ Label {
56+ id: timeLabel
57+ text: tzData.time
58+ anchors.right: parent.right
59+ anchors.top: parent.top
60+ }
61+ Label {
62+ id: abbrevLabel
63+ text: tzData.abbreviation
64+ anchors.right: parent.right
65+ anchors.top: timeLabel.bottom
66+ }
67+ }
68+ }
69+
70+ Column {
71+ id: column
72+ spacing: units.gu(2)
73+ anchors.leftMargin: leftMargin
74+ anchors.rightMargin: rightMargin
75+ anchors.top: content.top
76+ anchors.bottom: content.bottom
77+ anchors.left: tzPage.left
78+ anchors.right: tzPage.right
79+
80+ TextField {
81+ id: searchField
82+ anchors.left: parent.left
83+ anchors.right: parent.right
84+ placeholderText: i18n.tr("Enter your city")
85+ }
86+
87+ Flickable {
88+ anchors.left: parent.left
89+ anchors.right: parent.right
90+ anchors.topMargin: topMargin
91+ height: column.height - searchField.height - column.spacing - topMargin
92+ contentHeight: contentItem.childrenRect.height
93+ clip: true
94+ flickDeceleration: 1500 * units.gridUnit / 8
95+ maximumFlickVelocity: 2500 * units.gridUnit / 8
96+ boundsBehavior: (contentHeight > height) ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
97+
98+ Column {
99+ anchors.left: parent.left
100+ anchors.right: parent.right
101+
102+ Repeater {
103+ id: mainMenu
104+
105+ model: tzFilterModel
106+
107+ delegate: Loader {
108+ id: loader
109+ anchors.left: parent.left
110+ anchors.right: parent.right
111+ height: units.gu(6)
112+ asynchronous: true
113+ sourceComponent: tzComponent
114+
115+ onLoaded: {
116+ item.tzData = Qt.binding(function() { return model; });
117+ }
118+ }
119+ }
120+ }
121+ }
122+ }
123+
124+ Component {
125+ id: forwardButton
126+ LocalComponents.StackButton {
127+ text: i18n.tr("Next")
128+ onClicked: pageStack.next()
129+ }
130+ }
131+}
tests/mocks/Wizard/CMakeLists.txt+1
@@ -6,6 +6,7 @@ add_library(MockWizard-qml MODULE
66 mockplugin.cpp
77 MockSystem.cpp
88 ${CMAKE_SOURCE_DIR}/plugins/Wizard/PageList.cpp
9+ ${CMAKE_SOURCE_DIR}/plugins/Wizard/timezonemodel.cpp
910)
1011
1112qt5_use_modules(MockWizard-qml Qml)
tests/mocks/Wizard/mockplugin.cpp+3
@@ -17,6 +17,7 @@
1717#include "mockplugin.h"
1818#include "MockSystem.h"
1919#include "PageList.h"
20+#include "timezonemodel.h"
2021
2122#include <QtQml/qqml.h>
2223
@@ -32,4 +33,6 @@ void MockWizardPlugin::registerTypes(const char *uri)
3233 Q_ASSERT(uri == QLatin1String("Wizard"));
3334 qmlRegisterType<PageList>(uri, 0, 1, "PageList");
3435 qmlRegisterSingletonType<MockSystem>(uri, 0, 1, "System", system_provider);
36+ qmlRegisterType<TimeZoneModel>(uri, 0, 1, "TimeZoneModel");
37+ qmlRegisterType<TimeZoneFilterModel>(uri, 0, 1, "TimeZoneFilterModel");
3538}