mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-06-11 08:57:21 +00:00
Keep the selected timezone visible in the wizard and update it before applying the system timezone. Filter by city or zone name and report timedatectl failures without discarding the staged choice.
121 lines
3.3 KiB
C++
121 lines
3.3 KiB
C++
// 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>
|
|
#include <QSet>
|
|
#include <QStringList>
|
|
#include <QStringMatcher>
|
|
#include <QTimeZone>
|
|
|
|
#include <algorithm>
|
|
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
|
|
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
|
|
{
|
|
Q_UNUSED(parent)
|
|
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()];
|
|
case DisplayNameRole:
|
|
return displayNameForId(m_data[index.row()]);
|
|
}
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
void TimeZoneModel::update()
|
|
{
|
|
beginResetModel();
|
|
m_data.clear();
|
|
|
|
QString localZone = QString::fromUtf8(QTimeZone::systemTimeZoneId());
|
|
if (localZone.isEmpty() || !QTimeZone(localZone.toUtf8()).isValid()) {
|
|
localZone = QStringLiteral("UTC");
|
|
}
|
|
QSet<QString> seenZones;
|
|
|
|
const QList<QByteArray> systemTimeZones = QTimeZone::availableTimeZoneIds();
|
|
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;
|
|
});
|
|
|
|
const int localIndex = m_data.indexOf(localZone);
|
|
if (localIndex > 0) {
|
|
m_data.move(localIndex, 0);
|
|
}
|
|
|
|
endResetModel();
|
|
}
|
|
|
|
QHash<int, QByteArray> TimeZoneModel::roleNames() const
|
|
{
|
|
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());
|
|
}
|