-
-
Notifications
You must be signed in to change notification settings - Fork 106
/
main.cpp
178 lines (145 loc) · 6.35 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
SPDX-FileCopyrightText: 1998 Luca Montecchiani <m.luca@usa.net>
SPDX-FileCopyrightText: 2015 David Edmundson <davidedmundson@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "main.h"
#include <time.h>
#include <unistd.h>
#include <QVBoxLayout>
#include <KAboutData>
#include <KMessageBox>
#include <KPluginFactory>
#include <QDBusConnection>
#include "dtime.h"
#include "helper.h"
#include <KAuth/Action>
#include <KAuth/ExecuteJob>
#include "timedated_interface.h"
K_PLUGIN_CLASS_WITH_JSON(KclockModule, "kcm_clock.json")
KclockModule::KclockModule(QObject *parent, const KPluginMetaData &metaData)
: KCModule(parent, metaData)
{
auto reply = QDBusConnection::systemBus().call(QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DBus"),
QStringLiteral("/org/freedesktop/DBus"),
QStringLiteral("org.freedesktop.DBus"),
QStringLiteral("ListActivatableNames")));
if (!reply.arguments().isEmpty() && reply.arguments().constFirst().value<QStringList>().contains(QLatin1String("org.freedesktop.timedate1"))) {
m_haveTimedated = true;
}
QVBoxLayout *layout = new QVBoxLayout(widget());
layout->setContentsMargins(0, 0, 0, 0);
dtime = new Dtime(widget(), m_haveTimedated);
layout->addWidget(dtime);
connect(dtime, &Dtime::timeChanged, this, &KCModule::setNeedsSave);
setButtons(Help | Apply);
if (m_haveTimedated) {
setAuthActionName(QStringLiteral("org.freedesktop.timedate1.set-time"));
} else {
// auth action name will be automatically guessed from the KCM name
qWarning() << "Timedated not found, using legacy saving mode";
setAuthActionName(QStringLiteral("org.kde.kcontrol.kcmclock.save"));
}
}
bool KclockModule::kauthSave()
{
QVariantMap helperargs;
helperargs[QStringLiteral("ntp")] = true;
helperargs[QStringLiteral("ntpServers")] = dtime->ntpServers();
helperargs[QStringLiteral("ntpEnabled")] = dtime->ntpEnabled();
if (!dtime->ntpEnabled()) {
QDateTime newTime = dtime->userTime();
qDebug() << "Set date to " << dtime->userTime();
helperargs[QStringLiteral("date")] = true;
helperargs[QStringLiteral("newdate")] = QString::number(newTime.toSecsSinceEpoch());
helperargs[QStringLiteral("olddate")] = QString::number(QDateTime::currentSecsSinceEpoch());
}
QString selectedTimeZone = dtime->selectedTimeZone();
if (!selectedTimeZone.isEmpty()) {
helperargs[QStringLiteral("tz")] = true;
helperargs[QStringLiteral("tzone")] = selectedTimeZone;
} else {
helperargs[QStringLiteral("tzreset")] = true; // make the helper reset the timezone
}
Action action(authActionName());
action.setHelperId(QStringLiteral("org.kde.kcontrol.kcmclock"));
action.setArguments(helperargs);
ExecuteJob *job = action.execute();
bool rc = job->exec();
if (!rc) {
KMessageBox::error(widget(), i18n("Unable to authenticate/execute the action: %1, %2", job->error(), job->errorString()));
}
return rc;
}
bool KclockModule::timedatedSave()
{
OrgFreedesktopTimedate1Interface timedateIface(QStringLiteral("org.freedesktop.timedate1"),
QStringLiteral("/org/freedesktop/timedate1"),
QDBusConnection::systemBus());
bool rc = true;
// final arg in each method is "user-interaction" i.e whether it's OK for polkit to ask for auth
// 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
// timedated processes these in parallel and will return an error otherwise
auto reply = timedateIface.SetNTP(dtime->ntpEnabled(), true);
reply.waitForFinished();
if (reply.isError()) {
KMessageBox::error(widget(), i18n("Unable to change NTP settings"));
qWarning() << "Failed to enable NTP" << reply.error().name() << reply.error().message();
rc = false;
}
if (!dtime->ntpEnabled()) {
qint64 timeDiff = dtime->userTime().toMSecsSinceEpoch() - QDateTime::currentMSecsSinceEpoch();
//*1000 for milliseconds -> microseconds
auto reply = timedateIface.SetTime(timeDiff * 1000, true, true);
reply.waitForFinished();
if (reply.isError()) {
KMessageBox::error(widget(), i18n("Unable to set current time"));
qWarning() << "Failed to set current time" << reply.error().name() << reply.error().message();
rc = false;
}
}
QString selectedTimeZone = dtime->selectedTimeZone();
if (!selectedTimeZone.isEmpty()) {
auto reply = timedateIface.SetTimezone(selectedTimeZone, true);
reply.waitForFinished();
if (reply.isError()) {
KMessageBox::error(widget(), i18n("Unable to set timezone"));
qWarning() << "Failed to set timezone" << reply.error().name() << reply.error().message();
rc = false;
}
}
return rc;
}
void KclockModule::save()
{
widget()->setDisabled(true);
bool success = false;
if (m_haveTimedated) {
success = timedatedSave();
} else {
success = kauthSave();
}
if (success) {
QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/org/kde/kcmshell_clock"), //
QStringLiteral("org.kde.kcmshell_clock"),
QStringLiteral("clockUpdated"));
QDBusConnection::sessionBus().send(msg);
}
// NOTE: super nasty hack #1
// Try to work around time mismatch between KSystemTimeZones' update of local
// timezone and reloading of data, so that the new timezone is taken into account.
// The Ultimate solution to this would be if KSTZ emitted a signal when a new
// local timezone was found.
// setDisabled(false) happens in load(), since QTimer::singleShot is non-blocking
if (!m_haveTimedated) {
QTimer::singleShot(5000, this, &KclockModule::load);
} else {
load();
}
}
void KclockModule::load()
{
dtime->load();
widget()->setDisabled(false);
}
#include "main.moc"