on 65f91df help sign in
unity8/plugins/Wizard/timezonemodel.cpp
217 lines 6.2 kB history raw
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 */
17#include <QDebug>
19#include <glib.h>
20#include <glib-object.h>
21#include <timezonemap/tz.h>
23#include "LocalePlugin.h"
24#include "timezonemodel.h"
27TimeZoneLocationModel::TimeZoneLocationModel(QObject *parent):
28 QAbstractListModel(parent),
29 m_workerThread(new TimeZonePopulateWorker())
31 qRegisterMetaType<TzLocation>();
33 m_roleNames[Qt::DisplayRole] = "displayName";
34 m_roleNames[TimeZoneRole] = "timeZone";
35 m_roleNames[CityRole] = "city";
36 m_roleNames[CountryRole] = "country";
37 m_roleNames[OffsetRole] = "offset";
39 QObject::connect(m_workerThread,
40 &TimeZonePopulateWorker::resultReady,
41 this,
42 &TimeZoneLocationModel::processModelResult);
43 QObject::connect(m_workerThread,
44 &TimeZonePopulateWorker::finished,
45 this,
46 &TimeZoneLocationModel::store);
47 QObject::connect(m_workerThread,
48 &TimeZonePopulateWorker::finished,
49 m_workerThread,
50 &QObject::deleteLater);
52 init();
55void TimeZoneLocationModel::init()
57 beginResetModel();
58 m_workerThread->start();
61void TimeZoneLocationModel::store()
63 m_workerThread = nullptr;
64 endResetModel();
67void TimeZoneLocationModel::processModelResult(const TzLocation &location)
69 m_locations.append(location);
72int TimeZoneLocationModel::rowCount(const QModelIndex &parent) const
74 if (parent.isValid())
75 return 0;
76 return m_locations.count();
79QVariant TimeZoneLocationModel::data(const QModelIndex &index, int role) const
81 if (index.row() >= m_locations.count() || index.row() < 0)
82 return QVariant();
84 const TzLocation tz = m_locations.at(index.row());
86 const QString country(tz.full_country.isEmpty() ? tz.country : tz.full_country);
88 switch (role) {
89 case Qt::DisplayRole:
90 if (!tz.state.isEmpty())
91 return QStringLiteral("%1, %2, %3").arg(tz.city).arg(tz.state).arg(country);
92 else
93 return QStringLiteral("%1, %2").arg(tz.city).arg(country);
94 case SimpleRole:
95 return QStringLiteral("%1, %2").arg(tz.city).arg(country);
96 case TimeZoneRole:
97 return tz.timezone;
98 case CountryRole:
99 return tz.country;
100 case CityRole:
101 return tz.city;
102 case OffsetRole: {
103 QTimeZone tmp(tz.timezone.toLatin1());
104 return static_cast<double>(tmp.standardTimeOffset(QDateTime::currentDateTime())) / 3600;
105 }
106 default:
107 qWarning() << Q_FUNC_INFO << "Unknown role";
108 return QVariant();
109 }
112QHash<int, QByteArray> TimeZoneLocationModel::roleNames() const
114 return m_roleNames;
117void TimeZonePopulateWorker::run()
119 buildCityMap();
122void TimeZonePopulateWorker::buildCityMap()
124 TzDB *tzdb = tz_load_db();
125 GPtrArray *tz_locations = tz_get_locations(tzdb);
127 TimeZoneLocationModel::TzLocation tmpTz;
129 for (guint i = 0; i < tz_locations->len; ++i) {
130 auto tmp = static_cast<CcTimezoneLocation *>(g_ptr_array_index(tz_locations, i));
131 gchar *en_name, *country, *zone, *state, *full_country;
132 g_object_get (tmp, "en_name", &en_name,
133 "country", &country,
134 "zone", &zone,
135 "state", &state,
136 "full_country", &full_country,
137 nullptr);
138 // There are empty entries in the DB
139 if (g_strcmp0(en_name, "") != 0) {
140 tmpTz.city = en_name;
141 tmpTz.country = country;
142 tmpTz.timezone = zone;
143 tmpTz.state = state;
144 tmpTz.full_country = full_country;
146 Q_EMIT (resultReady(tmpTz));
147 }
148 g_free (en_name);
149 g_free (country);
150 g_free (zone);
151 g_free (state);
152 g_free (full_country);
153 }
155 g_ptr_array_free (tz_locations, TRUE);
156 tz_db_free(tzdb);
160TimeZoneFilterModel::TimeZoneFilterModel(QObject *parent)
161 : QSortFilterProxyModel(parent)
163 setDynamicSortFilter(false);
164 setSortLocaleAware(true);
165 setSortRole(TimeZoneLocationModel::CityRole);
166 m_stringMatcher.setCaseSensitivity(Qt::CaseInsensitive);
167 sort(0);
170bool TimeZoneFilterModel::filterAcceptsRow(int row, const QModelIndex &parentIndex) const
172 if (!sourceModel()) {
173 return true;
174 }
176 if (!m_filter.isEmpty()) { // filtering by freeform text input, cf setFilter(QString)
177 const QString city = sourceModel()->index(row, 0, parentIndex).data(TimeZoneLocationModel::CityRole).toString();
179 if (m_stringMatcher.indexIn(city) == 0) { // match at the beginning of the city name
180 return true;
181 }
182 } else if (!m_country.isEmpty()) { // filter by country code
183 const QString countryCode = sourceModel()->index(row, 0, parentIndex).data(TimeZoneLocationModel::CountryRole).toString();
184 return m_country.compare(countryCode, Qt::CaseInsensitive) == 0;
185 }
187 return false;
190QString TimeZoneFilterModel::filter() const
192 return m_filter;
195void TimeZoneFilterModel::setFilter(const QString &filter)
197 if (filter != m_filter) {
198 m_filter = filter;
199 m_stringMatcher.setPattern(m_filter);
200 Q_EMIT filterChanged();
201 invalidate();
202 }
205QString TimeZoneFilterModel::country() const
207 return m_country;
210void TimeZoneFilterModel::setCountry(const QString &country)
212 if (m_country == country)
213 return;
215 m_country = country;
216 Q_EMIT countryChanged(country);