File indexing completed on 2024-05-05 05:36:41
0001 /* 0002 0003 SPDX-FileCopyrightText: 2005 S.R.Haque <srhaque@iee.org>. 0004 SPDX-FileCopyrightText: 2009 David Faure <faure@kde.org> 0005 SPDX-FileCopyrightText: 2011-2015 Sebastian Kügler <sebas@kde.org> 0006 SPDX-FileCopyrightText: 2015 David Edmundson <davidedmundson@kde.org> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "timesettings.h" 0012 #include "timezonemodel.h" 0013 0014 #include <QDebug> 0015 #include <QtCore/QDate> 0016 0017 #include <QDBusConnection> 0018 #include <QDBusMessage> 0019 #include <QStandardItemModel> 0020 #include <QTimer> 0021 #include <QVariant> 0022 0023 #include <KConfigGroup> 0024 #include <KLocalizedString> 0025 #include <KPluginFactory> 0026 #include <KSharedConfig> 0027 #include <utility> 0028 0029 #include <QCoroDBus> 0030 #include <QCoroTask> 0031 0032 #include "timedated_interface.h" 0033 0034 #define FORMAT24H "HH:mm:ss" 0035 #define FORMAT12H "h:mm:ss ap" 0036 0037 K_PLUGIN_CLASS_WITH_JSON(TimeSettings, "kcm_mobile_time.json") 0038 0039 TimeSettings::TimeSettings(QObject *parent, const KPluginMetaData &metaData) 0040 : KQuickConfigModule(parent, metaData) 0041 , m_useNtp(true) 0042 { 0043 setButtons({}); 0044 0045 qDebug() << "time settings init"; 0046 m_timeZonesModel = nullptr; 0047 setTimeZone(QTimeZone::systemTimeZone().id()); 0048 0049 qmlRegisterAnonymousType<TimeZoneModel>("org.kde.timesettings", 1); 0050 qmlRegisterAnonymousType<TimeZoneFilterProxy>("org.kde.timesettings", 1); 0051 0052 initSettings(); 0053 initTimeZones(); 0054 qDebug() << "TimeSettings module loaded."; 0055 } 0056 0057 void TimeSettings::initTimeZones() 0058 { 0059 auto *filterModel = new TimeZoneFilterProxy(this); 0060 filterModel->setSourceModel(new TimeZoneModel(filterModel)); 0061 setTimeZonesModel(filterModel); 0062 } 0063 0064 void TimeSettings::initSettings() 0065 { 0066 m_localeConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::SimpleConfig); 0067 m_localeSettings = KConfigGroup(m_localeConfig, "Locale"); 0068 0069 setTimeFormat(m_localeSettings.readEntry("TimeFormat", QStringLiteral(FORMAT24H))); // FIXME?! 0070 0071 OrgFreedesktopTimedate1Interface timeDatedIface(QStringLiteral("org.freedesktop.timedate1"), 0072 QStringLiteral("/org/freedesktop/timedate1"), 0073 QDBusConnection::systemBus()); 0074 // the server list is not relevant for timesyncd, it fetches it from the network 0075 m_useNtp = timeDatedIface.nTP(); 0076 } 0077 0078 void TimeSettings::timeout() 0079 { 0080 setCurrentTime(QTime::currentTime()); 0081 setCurrentDate(QDate::currentDate()); 0082 notify(); 0083 } 0084 0085 QString TimeSettings::currentTimeText() 0086 { 0087 return m_currentTimeText; 0088 } 0089 0090 QTime TimeSettings::currentTime() const 0091 { 0092 return m_currentTime; 0093 } 0094 0095 void TimeSettings::setCurrentTime(const QTime ¤tTime) 0096 { 0097 if (m_currentTime != currentTime) { 0098 m_currentTime = currentTime; 0099 m_currentTimeText = QLocale().toString(QTime::currentTime(), m_timeFormat); 0100 emit currentTimeChanged(); 0101 } 0102 } 0103 0104 QDate TimeSettings::currentDate() const 0105 { 0106 return m_currentDate; 0107 } 0108 0109 void TimeSettings::setCurrentDate(const QDate ¤tDate) 0110 { 0111 if (m_currentDate != currentDate) { 0112 m_currentDate = currentDate; 0113 emit currentDateChanged(); 0114 } 0115 } 0116 0117 bool TimeSettings::useNtp() const 0118 { 0119 return m_useNtp; 0120 } 0121 0122 void TimeSettings::setUseNtp(bool ntp) 0123 { 0124 if (m_useNtp != ntp) { 0125 m_useNtp = ntp; 0126 saveTime(); 0127 emit useNtpChanged(); 0128 } 0129 } 0130 0131 void TimeSettings::saveTime() 0132 { 0133 auto timedateIface = std::make_shared<OrgFreedesktopTimedate1Interface>(QStringLiteral("org.freedesktop.timedate1"), 0134 QStringLiteral("/org/freedesktop/timedate1"), 0135 QDBusConnection::systemBus()); 0136 0137 // final arg in each method is "user-interaction" i.e whether it's OK for polkit to ask for auth 0138 0139 // we cannot send requests up front then block for all replies as we need NTP to be disabled before we can make a call to SetTime 0140 // timedated processes these in parallel and will return an error otherwise 0141 0142 auto reply = timedateIface->SetNTP(m_useNtp, true); 0143 auto r = reply; 0144 QCoro::connect(std::move(reply), this, [=, this]() { 0145 if (r.isError()) { 0146 m_errorString = i18n("Unable to change NTP settings"); 0147 emit errorStringChanged(); 0148 qWarning() << "Failed to enable NTP" << r.error().name() << r.error().message(); 0149 } 0150 0151 if (!useNtp()) { 0152 QDateTime userTime; 0153 userTime.setTime(currentTime()); 0154 userTime.setDate(currentDate()); 0155 qDebug() << "Setting userTime: " << userTime; 0156 qint64 timeDiff = userTime.toMSecsSinceEpoch() - QDateTime::currentMSecsSinceEpoch(); 0157 0158 //*1000 for milliseconds -> microseconds 0159 auto reply = timedateIface->SetTime(timeDiff * 1000, true, true); 0160 auto r = reply; 0161 QCoro::connect(std::move(reply), this, [=, this]() { 0162 if (r.isError()) { 0163 m_errorString = i18n("Unable to set current time"); 0164 emit errorStringChanged(); 0165 qWarning() << "Failed to set current time" << r.error().name() << r.error().message(); 0166 } 0167 }); 0168 } 0169 saveTimeZone(m_timezone); 0170 }); 0171 } 0172 0173 void TimeSettings::saveTimeZone(const QString &newtimezone) 0174 { 0175 qDebug() << "Saving timezone to config: " << newtimezone; 0176 OrgFreedesktopTimedate1Interface timedateIface(QStringLiteral("org.freedesktop.timedate1"), 0177 QStringLiteral("/org/freedesktop/timedate1"), 0178 QDBusConnection::systemBus()); 0179 0180 if (!newtimezone.isEmpty()) { 0181 qDebug() << "Setting timezone: " << newtimezone; 0182 auto reply = timedateIface.SetTimezone(newtimezone, true); 0183 auto r = reply; 0184 QCoro::connect(std::move(reply), this, [=, this]() { 0185 if (r.isError()) { 0186 m_errorString = i18n("Unable to set timezone"); 0187 emit errorStringChanged(); 0188 qWarning() << "Failed to set timezone" << r.error().name() << r.error().message(); 0189 } else { 0190 setTimeZone(newtimezone); 0191 emit timeZoneChanged(); 0192 notify(); 0193 } 0194 }); 0195 } 0196 } 0197 0198 QString TimeSettings::timeFormat() 0199 { 0200 return m_timeFormat; 0201 } 0202 0203 void TimeSettings::setTimeFormat(const QString &timeFormat) 0204 { 0205 if (m_timeFormat != timeFormat) { 0206 m_timeFormat = timeFormat; 0207 0208 m_localeSettings.writeEntry("TimeFormat", timeFormat, KConfigGroup::Notify); 0209 m_localeConfig->sync(); 0210 0211 QDBusMessage msg = 0212 QDBusMessage::createSignal(QStringLiteral("/org/kde/kcmshell_clock"), QStringLiteral("org.kde.kcmshell_clock"), QStringLiteral("clockUpdated")); 0213 QDBusConnection::sessionBus().send(msg); 0214 0215 qDebug() << "time format is now: " << QLocale().toString(QTime::currentTime(), m_timeFormat); 0216 emit timeFormatChanged(); 0217 timeout(); 0218 } 0219 } 0220 0221 QString TimeSettings::timeZone() 0222 { 0223 return m_timezone; 0224 } 0225 0226 void TimeSettings::setTimeZone(const QString &timezone) 0227 { 0228 if (m_timezone != timezone) { 0229 m_timezone = timezone; 0230 qDebug() << "timezone changed to: " << timezone; 0231 emit timeZoneChanged(); 0232 timeout(); 0233 } 0234 } 0235 0236 TimeZoneFilterProxy *TimeSettings::timeZonesModel() 0237 { 0238 return m_timeZonesModel; 0239 } 0240 0241 void TimeSettings::setTimeZonesModel(TimeZoneFilterProxy *timezones) 0242 { 0243 m_timeZonesModel = timezones; 0244 emit timeZonesModelChanged(); 0245 } 0246 0247 bool TimeSettings::twentyFour() 0248 { 0249 return timeFormat() == QStringLiteral(FORMAT24H); 0250 } 0251 0252 void TimeSettings::setTwentyFour(bool t) 0253 { 0254 if (twentyFour() != t) { 0255 if (t) { 0256 setTimeFormat(FORMAT24H); 0257 } else { 0258 setTimeFormat(FORMAT12H); 0259 } 0260 qDebug() << "T24 toggled: " << t << m_timeFormat; 0261 emit twentyFourChanged(); 0262 emit currentTimeChanged(); 0263 timeout(); 0264 } 0265 } 0266 0267 QString TimeSettings::errorString() 0268 { 0269 return m_errorString; 0270 } 0271 0272 void TimeSettings::notify() 0273 { 0274 const QDBusMessage msg = 0275 QDBusMessage::createSignal(QStringLiteral("/org/kde/kcmshell_clock"), QStringLiteral("org.kde.kcmshell_clock"), QStringLiteral("clockUpdated")); 0276 QDBusConnection::sessionBus().send(msg); 0277 } 0278 0279 #include "timesettings.moc"