File indexing completed on 2025-01-26 05:07:37
0001 /* 0002 SPDX-FileCopyrightText: 2014 Kai Uwe Broulik <kde@privat.broulik.de> 0003 SPDX-FileCopyrightText: 2014 Martin Klapetek <mklapetek@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "timezonemodel.h" 0009 #include "timezonesi18n.h" 0010 0011 #include <KLocalizedString> 0012 #include <QDBusConnection> 0013 #include <QStringMatcher> 0014 #include <QTimeZone> 0015 0016 TimeZoneFilterProxy::TimeZoneFilterProxy(QObject *parent) 0017 : QSortFilterProxyModel(parent) 0018 { 0019 m_stringMatcher.setCaseSensitivity(Qt::CaseInsensitive); 0020 } 0021 0022 bool TimeZoneFilterProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const 0023 { 0024 if (!sourceModel() || (m_filterString.isEmpty() && !m_onlyShowChecked)) { 0025 return true; 0026 } 0027 0028 const bool checked = sourceModel()->index(source_row, 0, source_parent).data(TimeZoneModel::CheckedRole).toBool(); 0029 if (m_onlyShowChecked && !checked) { 0030 return false; 0031 } 0032 0033 const QString city = sourceModel()->index(source_row, 0, source_parent).data(TimeZoneModel::CityRole).toString(); 0034 const QString region = sourceModel()->index(source_row, 0, source_parent).data(TimeZoneModel::RegionRole).toString(); 0035 const QString comment = sourceModel()->index(source_row, 0, source_parent).data(TimeZoneModel::CommentRole).toString(); 0036 0037 if (m_stringMatcher.indexIn(city) != -1 || m_stringMatcher.indexIn(region) != -1 || m_stringMatcher.indexIn(comment) != -1) { 0038 return true; 0039 } 0040 0041 return false; 0042 } 0043 0044 void TimeZoneFilterProxy::setFilterString(const QString &filterString) 0045 { 0046 m_filterString = filterString; 0047 m_stringMatcher.setPattern(filterString); 0048 Q_EMIT filterStringChanged(); 0049 invalidateFilter(); 0050 } 0051 0052 void TimeZoneFilterProxy::setOnlyShowChecked(const bool show) 0053 { 0054 if (m_onlyShowChecked == show) { 0055 return; 0056 } 0057 m_onlyShowChecked = show; 0058 Q_EMIT onlyShowCheckedChanged(); 0059 invalidateFilter(); 0060 } 0061 0062 //============================================================================= 0063 0064 TimeZoneModel::TimeZoneModel(QObject *parent) 0065 : QAbstractListModel(parent) 0066 , m_timezonesI18n(new TimezonesI18n(this)) 0067 { 0068 update(); 0069 0070 QDBusConnection::sessionBus().connect(QString(), 0071 QStringLiteral("/org/kde/kcmshell_clock"), // 0072 QStringLiteral("org.kde.kcmshell_clock"), 0073 QStringLiteral("clockUpdated"), 0074 this, 0075 SLOT(slotUpdate())); 0076 } 0077 0078 TimeZoneModel::~TimeZoneModel() 0079 { 0080 } 0081 0082 int TimeZoneModel::rowCount(const QModelIndex &parent) const 0083 { 0084 Q_UNUSED(parent); 0085 return m_data.count(); 0086 } 0087 0088 QVariant TimeZoneModel::data(const QModelIndex &index, int role) const 0089 { 0090 if (index.isValid()) { 0091 TimeZoneData currentData = m_data.at(index.row()); 0092 0093 switch (role) { 0094 case TimeZoneIdRole: 0095 return currentData.id; 0096 case RegionRole: 0097 return currentData.region; 0098 case CityRole: 0099 return currentData.city; 0100 case CommentRole: 0101 return currentData.comment; 0102 case CheckedRole: 0103 return currentData.checked; 0104 case IsLocalTimeZoneRole: 0105 return currentData.isLocalTimeZone; 0106 } 0107 } 0108 0109 return QVariant(); 0110 } 0111 0112 bool TimeZoneModel::setData(const QModelIndex &index, const QVariant &value, int role) 0113 { 0114 if (!index.isValid() || value.isNull()) { 0115 return false; 0116 } 0117 0118 if (role == CheckedRole) { 0119 m_data[index.row()].checked = value.toBool(); 0120 Q_EMIT dataChanged(index, index); 0121 0122 if (m_data[index.row()].checked) { 0123 m_selectedTimeZones.append(m_data[index.row()].id); 0124 m_offsetData.insert(m_data[index.row()].id, m_data[index.row()].offsetFromUtc); 0125 } else { 0126 m_selectedTimeZones.removeAll(m_data[index.row()].id); 0127 m_offsetData.remove(m_data[index.row()].id); 0128 } 0129 0130 sortTimeZones(); 0131 0132 Q_EMIT selectedTimeZonesChanged(); 0133 return true; 0134 } 0135 0136 return false; 0137 } 0138 0139 void TimeZoneModel::update() 0140 { 0141 beginResetModel(); 0142 m_data.clear(); 0143 0144 TimeZoneData local; 0145 local.isLocalTimeZone = true; 0146 local.id = QStringLiteral("Local"); 0147 local.region = i18nc("This means \"Local Timezone\"", "Local"); 0148 local.city = m_timezonesI18n->i18nCity(QTimeZone::systemTimeZoneId()); 0149 local.comment = i18n("System's local time zone"); 0150 local.checked = false; 0151 0152 m_data.append(local); 0153 0154 const QList<QByteArray> systemTimeZones = QTimeZone::availableTimeZoneIds(); 0155 0156 for (const auto &id : systemTimeZones) { 0157 const QTimeZone zone(id); 0158 0159 const QString continent = m_timezonesI18n->i18nContinents(QString::fromUtf8(QByteArrayView(id).mid(0, id.indexOf('/')))); 0160 0161 TimeZoneData newData; 0162 newData.isLocalTimeZone = false; 0163 newData.id = id; 0164 newData.city = m_timezonesI18n->i18nCity(id); 0165 newData.region = zone.country() == QLocale::AnyCountry ? QString() : continent + QLatin1Char('/') + m_timezonesI18n->i18nCountry(zone.country()); 0166 newData.comment = zone.comment(); 0167 newData.checked = false; 0168 newData.offsetFromUtc = zone.offsetFromUtc(QDateTime::currentDateTimeUtc()); 0169 m_data.append(newData); 0170 } 0171 0172 std::sort(m_data.begin() + 1, m_data.end(), [](const TimeZoneData &left, const TimeZoneData &right) { 0173 return left.city.compare(right.city) < 0; 0174 }); 0175 0176 endResetModel(); 0177 } 0178 0179 void TimeZoneModel::setSelectedTimeZones(const QStringList &selectedTimeZones) 0180 { 0181 m_selectedTimeZones = selectedTimeZones; 0182 for (int i = 0; i < m_data.size(); i++) { 0183 if (m_selectedTimeZones.contains(m_data.at(i).id)) { 0184 m_data[i].checked = true; 0185 m_offsetData.insert(m_data[i].id, m_data[i].offsetFromUtc); 0186 0187 QModelIndex index = createIndex(i, 0); 0188 Q_EMIT dataChanged(index, index); 0189 } 0190 } 0191 0192 sortTimeZones(); 0193 } 0194 0195 void TimeZoneModel::selectLocalTimeZone() 0196 { 0197 m_data[0].checked = true; 0198 Q_EMIT dataChanged(index(0, 0), index(0, 0), QList<int>{CheckedRole}); 0199 } 0200 0201 QString TimeZoneModel::localTimeZoneCity() 0202 { 0203 return m_data[0].city; 0204 } 0205 0206 void TimeZoneModel::slotUpdate() 0207 { 0208 update(); 0209 setProperty("selectedTimeZones", m_selectedTimeZones); 0210 } 0211 0212 QHash<int, QByteArray> TimeZoneModel::roleNames() const 0213 { 0214 return QHash<int, QByteArray>({ 0215 {TimeZoneIdRole, "timeZoneId"}, 0216 {RegionRole, "region"}, 0217 {CityRole, "city"}, 0218 {CommentRole, "comment"}, 0219 {CheckedRole, "checked"}, 0220 {IsLocalTimeZoneRole, "isLocalTimeZone"}, 0221 }); 0222 } 0223 0224 void TimeZoneModel::sortTimeZones() 0225 { 0226 std::sort(m_selectedTimeZones.begin(), m_selectedTimeZones.end(), [this](const QString &a, const QString &b) { 0227 return m_offsetData.value(a) < m_offsetData.value(b); 0228 }); 0229 }