2023-04-01 07:09:57 +00:00
|
|
|
// SPDX-FileCopyrightText: 2014 Kai Uwe Broulik <kde@privat.broulik.de>
|
|
|
|
|
// SPDX-FileCopyrightText: 2014 Martin Klapetek <mklapetek@kde.org>
|
|
|
|
|
// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
|
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
|
|
#include "timezonemodel.h"
|
|
|
|
|
|
|
|
|
|
#include <KLocalizedString>
|
|
|
|
|
|
|
|
|
|
#include <QDebug>
|
2026-05-11 08:03:20 +00:00
|
|
|
#include <QSet>
|
|
|
|
|
#include <QStringList>
|
2023-04-01 07:09:57 +00:00
|
|
|
#include <QStringMatcher>
|
|
|
|
|
#include <QTimeZone>
|
|
|
|
|
|
2026-05-11 08:03:20 +00:00
|
|
|
#include <algorithm>
|
|
|
|
|
|
2023-04-01 07:09:57 +00:00
|
|
|
TimeZoneFilterProxy::TimeZoneFilterProxy(QObject *parent)
|
|
|
|
|
: QSortFilterProxyModel(parent)
|
|
|
|
|
{
|
|
|
|
|
m_stringMatcher.setCaseSensitivity(Qt::CaseInsensitive);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TimeZoneFilterProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
|
|
|
|
{
|
|
|
|
|
if (!sourceModel() || m_filterString.isEmpty()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2026-05-11 08:03:20 +00:00
|
|
|
const QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
|
|
|
|
|
const QString id = index.data(TimeZoneModel::TimeZoneIdRole).toString();
|
|
|
|
|
const QString displayName = index.data(TimeZoneModel::DisplayNameRole).toString();
|
|
|
|
|
return m_stringMatcher.indexIn(id) != -1 || m_stringMatcher.indexIn(displayName) != -1;
|
2023-04-01 07:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TimeZoneFilterProxy::setFilterString(const QString &filterString)
|
|
|
|
|
{
|
|
|
|
|
m_filterString = filterString;
|
|
|
|
|
m_stringMatcher.setPattern(filterString);
|
|
|
|
|
Q_EMIT filterStringChanged();
|
|
|
|
|
invalidateFilter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TimeZoneModel::TimeZoneModel(QObject *parent)
|
|
|
|
|
: QAbstractListModel(parent)
|
|
|
|
|
{
|
|
|
|
|
update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TimeZoneModel::~TimeZoneModel()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int TimeZoneModel::rowCount(const QModelIndex &parent) const
|
|
|
|
|
{
|
2024-08-17 13:48:22 +00:00
|
|
|
Q_UNUSED(parent)
|
2023-04-01 07:09:57 +00:00
|
|
|
return m_data.count();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariant TimeZoneModel::data(const QModelIndex &index, int role) const
|
|
|
|
|
{
|
|
|
|
|
if (index.isValid()) {
|
|
|
|
|
switch (role) {
|
|
|
|
|
case TimeZoneIdRole:
|
|
|
|
|
return m_data[index.row()];
|
2026-05-11 08:03:20 +00:00
|
|
|
case DisplayNameRole:
|
|
|
|
|
return displayNameForId(m_data[index.row()]);
|
2023-04-01 07:09:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TimeZoneModel::update()
|
|
|
|
|
{
|
|
|
|
|
beginResetModel();
|
|
|
|
|
m_data.clear();
|
|
|
|
|
|
2026-05-11 08:03:20 +00:00
|
|
|
QString localZone = QString::fromUtf8(QTimeZone::systemTimeZoneId());
|
|
|
|
|
if (localZone.isEmpty() || !QTimeZone(localZone.toUtf8()).isValid()) {
|
|
|
|
|
localZone = QStringLiteral("UTC");
|
|
|
|
|
}
|
|
|
|
|
QSet<QString> seenZones;
|
2023-04-01 07:09:57 +00:00
|
|
|
|
|
|
|
|
const QList<QByteArray> systemTimeZones = QTimeZone::availableTimeZoneIds();
|
2026-05-11 08:03:20 +00:00
|
|
|
for (const QByteArray &timeZoneId : systemTimeZones) {
|
|
|
|
|
const QString zone = QString::fromUtf8(timeZoneId);
|
|
|
|
|
if (!seenZones.contains(zone)) {
|
|
|
|
|
seenZones.insert(zone);
|
|
|
|
|
m_data.append(zone);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::sort(m_data.begin(), m_data.end(), [](const QString &left, const QString &right) {
|
|
|
|
|
return QString::localeAwareCompare(left, right) < 0;
|
|
|
|
|
});
|
2023-04-01 07:09:57 +00:00
|
|
|
|
2026-05-11 08:03:20 +00:00
|
|
|
const int localIndex = m_data.indexOf(localZone);
|
|
|
|
|
if (localIndex > 0) {
|
|
|
|
|
m_data.move(localIndex, 0);
|
2023-04-01 07:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
endResetModel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QHash<int, QByteArray> TimeZoneModel::roleNames() const
|
|
|
|
|
{
|
2026-05-11 08:03:20 +00:00
|
|
|
return {{TimeZoneIdRole, "timeZoneId"}, {DisplayNameRole, "displayName"}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString TimeZoneModel::displayNameForId(const QString &timeZoneId) const
|
|
|
|
|
{
|
|
|
|
|
QString displayName = timeZoneId;
|
|
|
|
|
displayName.replace(QLatin1Char('_'), QLatin1Char(' '));
|
|
|
|
|
|
|
|
|
|
const QStringList parts = displayName.split(QLatin1Char('/'), Qt::SkipEmptyParts);
|
|
|
|
|
if (parts.size() <= 1) {
|
|
|
|
|
return displayName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return i18nc("timezone city and region", "%1 (%2)", parts.mid(1).join(QStringLiteral(" / ")), parts.first());
|
2023-04-01 07:09:57 +00:00
|
|
|
}
|