on 55ecae8 help sign in
unity8/plugins/Wizard/timezonemodel.cpp
228 lines 6.6 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"
26TimeZoneLocationModel::TimeZoneLocationModel(QObject *parent):
27 QAbstractListModel(parent),
28 m_workerThread(new TimeZonePopulateWorker())
30 qRegisterMetaType<TzLocationWizard>();
32 m_roleNames[Qt::DisplayRole] = "displayName";
33 m_roleNames[TimeZoneRole] = "timeZone";
34 m_roleNames[CityRole] = "city";
35 m_roleNames[CountryRole] = "country";
36 m_roleNames[OffsetRole] = "offset";
37 m_roleNames[LatitudeRole] = "latitude";
38 m_roleNames[LongitudeRole] = "longitude";
40 QObject::connect(m_workerThread,
41 &TimeZonePopulateWorker::resultReady,
42 this,
43 &TimeZoneLocationModel::processModelResult);
44 QObject::connect(m_workerThread,
45 &TimeZonePopulateWorker::finished,
46 this,
47 &TimeZoneLocationModel::store);
48 QObject::connect(m_workerThread,
49 &TimeZonePopulateWorker::finished,
50 m_workerThread,
51 &QObject::deleteLater);
53 init();
56void TimeZoneLocationModel::init()
58 beginResetModel();
59 m_workerThread->start();
62void TimeZoneLocationModel::store()
64 m_workerThread = nullptr;
65 endResetModel();
68void TimeZoneLocationModel::processModelResult(const TzLocationWizard &location)
70 m_locations.append(location);
73int TimeZoneLocationModel::rowCount(const QModelIndex &parent) const
75 if (parent.isValid())
76 return 0;
77 return m_locations.count();
80QVariant TimeZoneLocationModel::data(const QModelIndex &index, int role) const
82 if (index.row() >= m_locations.count() || index.row() < 0)
83 return QVariant();
85 const TzLocationWizard tz = m_locations.at(index.row());
87 const QString country(tz.full_country.isEmpty() ? tz.country : tz.full_country);
89 switch (role) {
90 case Qt::DisplayRole:
91 if (!tz.state.isEmpty())
92 return QStringLiteral("%1, %2, %3").arg(tz.city).arg(tz.state).arg(country);
93 else
94 return QStringLiteral("%1, %2").arg(tz.city).arg(country);
95 case SimpleRole:
96 return QStringLiteral("%1, %2").arg(tz.city).arg(country);
97 case TimeZoneRole:
98 return tz.timezone;
99 case CountryRole:
100 return tz.country;
101 case CityRole:
102 return tz.city;
103 case OffsetRole: {
104 QTimeZone tmp(tz.timezone.toLatin1());
105 return static_cast<double>(tmp.standardTimeOffset(QDateTime::currentDateTime())) / 3600;
106 }
107 case LatitudeRole:
108 return tz.latitude;
109 case LongitudeRole:
110 return tz.longitude;
111 default:
112 qWarning() << Q_FUNC_INFO << "Unknown role";
113 return QVariant();
114 }
117QHash<int, QByteArray> TimeZoneLocationModel::roleNames() const
119 return m_roleNames;
122void TimeZonePopulateWorker::run()
124 buildCityMap();
127void TimeZonePopulateWorker::buildCityMap()
129 TzDB *tzdb = tz_load_db();
130 GPtrArray *tz_locations = tz_get_locations(tzdb);
132 TimeZoneLocationModel::TzLocationWizard tmpTz;
134 for (guint i = 0; i < tz_locations->len; ++i) {
135 auto tmp = static_cast<CcTimezoneLocation *>(g_ptr_array_index(tz_locations, i));
136 gchar *en_name, *country, *zone, *state, *full_country;
137 gdouble latitude;
138 gdouble longitude;
139 g_object_get (tmp, "en_name", &en_name,
140 "country", &country,
141 "zone", &zone,
142 "state", &state,
143 "full_country", &full_country,
144 "latitude", &latitude,
145 "longitude", &longitude,
146 nullptr);
147 // There are empty entries in the DB
148 if (g_strcmp0(en_name, "") != 0) {
149 tmpTz.city = en_name;
150 tmpTz.country = country;
151 tmpTz.timezone = zone;
152 tmpTz.state = state;
153 tmpTz.full_country = full_country;
154 tmpTz.latitude = latitude;
155 tmpTz.longitude = longitude;
157 Q_EMIT (resultReady(tmpTz));
158 }
159 g_free (en_name);
160 g_free (country);
161 g_free (zone);
162 g_free (state);
163 g_free (full_country);
164 }
166 g_ptr_array_free (tz_locations, TRUE);
167 tz_db_free(tzdb);
171TimeZoneFilterModel::TimeZoneFilterModel(QObject *parent)
172 : QSortFilterProxyModel(parent)
174 setDynamicSortFilter(false);
175 setSortLocaleAware(true);
176 setSortRole(TimeZoneLocationModel::CityRole);
177 m_stringMatcher.setCaseSensitivity(Qt::CaseInsensitive);
178 sort(0);
181bool TimeZoneFilterModel::filterAcceptsRow(int row, const QModelIndex &parentIndex) const
183 if (!sourceModel()) {
184 return true;
185 }
187 if (!m_filter.isEmpty()) { // filtering by freeform text input, cf setFilter(QString)
188 const QString city = sourceModel()->index(row, 0, parentIndex).data(TimeZoneLocationModel::CityRole).toString();
190 if (m_stringMatcher.indexIn(city) == 0) { // match at the beginning of the city name
191 return true;
192 }
193 } else if (!m_country.isEmpty()) { // filter by country code
194 const QString countryCode = sourceModel()->index(row, 0, parentIndex).data(TimeZoneLocationModel::CountryRole).toString();
195 return m_country.compare(countryCode, Qt::CaseInsensitive) == 0;
196 }
198 return false;
201QString TimeZoneFilterModel::filter() const
203 return m_filter;
206void TimeZoneFilterModel::setFilter(const QString &filter)
208 if (filter != m_filter) {
209 m_filter = filter;
210 m_stringMatcher.setPattern(m_filter);
211 Q_EMIT filterChanged();
212 invalidate();
213 }
216QString TimeZoneFilterModel::country() const
218 return m_country;
221void TimeZoneFilterModel::setCountry(const QString &country)
223 if (m_country == country)
224 return;
226 m_country = country;
227 Q_EMIT countryChanged(country);