在Linux上使用QT设置系统时钟

时间:2018-05-04 11:15:48

标签: linux qt

我们如何使用QT小部件应用程序以编程方式更改Linux系统上的系统时间?

3 个答案:

答案 0 :(得分:2)

你不能用纯Qt那样做。您需要使用Linux(或POSIX)特定的东西。

您可能不应该这样做,但更好的是将整个系统配置为使用NTP(例如,通过运行一些NTP客户端......)。大多数Linux发行版已经有了。

如果你真的想要设置系统时间(但你不应该 直接 来自 Qt 应用程序,因为Qt应用程序不应该以root身份运行,但请参阅this),请阅读time(7),然后adjtimex(2)& settimeofday(2)

你需要成为root用户,所以你不应该从Qt应用程序那样做。您可以使用setuid技术以root身份运行某些特定命令或程序。 Setuid很棘手(参见credentials(7)execve(2)setreuid(2) ...),如果误用(并且容易犯错误)可以打开一个巨人security hole,所以请阅读一些关于Linux编程,例如旧ALP

因此,如果您坚持这样做(并且可能是错误的),请在C中为此编写一个微小的特定程序并使其成为setuid并从您的Qt应用程序运行该setuid程序(例如使用QProcess)。

答案 1 :(得分:2)

您可以使用dbus与timedated守护程序https://www.freedesktop.org/wiki/Software/systemd/timedated/

进行交互

设定时间和日期。

Qt提供了一种从xml生成接口代码的方法 http://doc.qt.io/qt-5/qdbusxml2cpp.html。你可以通过内省得到xml。

我不喜欢生成的代码格式,所以我自己编写了接口代码

H:

#ifndef TIMEDATE1SERVICE_H
#define TIMEDATE1SERVICE_H

#include <QObject>
#include <QString>
#include <QVariant>
#include <QtDBus>

class Timedate1Interface: public QDBusAbstractInterface
{
    Q_OBJECT
    Q_PROPERTY(bool CanNTP READ CanNTP)
    Q_PROPERTY(bool LocalRTC READ LocalRTC)
    Q_PROPERTY(bool NTP READ NTP)
    Q_PROPERTY(bool NTPSynchronized READ NTPSynchronized)
    Q_PROPERTY(qulonglong RTCTimeUSec READ RTCTimeUSec)
    Q_PROPERTY(qulonglong TimeUSec READ TimeUSec)
    Q_PROPERTY(QString Timezone READ Timezone)

public:
    explicit Timedate1Interface(QObject *parent = nullptr);

    bool CanNTP() const;
    bool LocalRTC() const;
    bool NTP() const;
    bool NTPSynchronized() const;
    qulonglong RTCTimeUSec() const;
    qulonglong TimeUSec() const;
    QString Timezone() const;

    void SetLocalRTC(bool localRTC, bool fixSystem, bool userInteraction);
    void SetNTP(bool useNTP, bool userInteraction);
    void SetTime(qlonglong usecUTC, bool relative, bool userInteraction);
    void SetTimezone(const QString &timezone, bool userInteraction);
};

#endif // TIMEDATE1SERVICE_H

CPP:

#include "timedate1service.h"

Timedate1Interface::Timedate1Interface(QObject *parent)
    : QDBusAbstractInterface("org.freedesktop.timedate1", "/org/freedesktop/timedate1",
                             "org.freedesktop.timedate1", QDBusConnection::systemBus(), parent)
{

}

bool Timedate1Interface::CanNTP() const
{
    return qvariant_cast<bool>(property("CanNTP"));
}

bool Timedate1Interface::LocalRTC() const
{
    return qvariant_cast<bool>(property("LocalRTC"));
}

bool Timedate1Interface::NTP() const
{
    return qvariant_cast<bool>(property("NTP"));
}

bool Timedate1Interface::NTPSynchronized() const
{
    return qvariant_cast<bool>(property("NTPSynchronized"));
}

qulonglong Timedate1Interface::RTCTimeUSec() const
{
    return qvariant_cast<qulonglong>(property("RTCTimeUSec"));
}

qulonglong Timedate1Interface::TimeUSec() const
{
    return qvariant_cast<qulonglong>(property("TimeUSec"));
}

QString Timedate1Interface::Timezone() const
{
    return qvariant_cast<QString>(property("Timezone"));
}

void Timedate1Interface::SetLocalRTC(bool localRTC, bool fixSystem, bool userInteraction)
{
    call("SetLocalRTC", localRTC, fixSystem, userInteraction);
}

void Timedate1Interface::SetNTP(bool useNTP, bool userInteraction)
{
    call("SetNTP", useNTP, userInteraction);
}

void Timedate1Interface::SetTime(qlonglong usecUTC, bool relative, bool userInteraction)
{
    call("SetTime", usecUTC, relative , userInteraction);
}

void Timedate1Interface::SetTimezone(const QString &timezone, bool userInteraction)
{
    call("SetTimezone", timezone, userInteraction);
}

答案 2 :(得分:0)

我找到了一个简单的解决方案。由于我的系统极简主义,我不想使用像dbus这样的东西。作为根或者sudoer,这可以执行(相当自我解释) -

QString string = dateTime.toString("\"yyyy-MM-dd hh:mm\"");
QString dateTimeString ("date -s ");
dateTimeString.append(string);
int systemDateTimeStatus= system(dateTimeString.toStdString().c_str());
if (systemDateTimeStatus == -1)
{
    qDebug() << "Failed to change date time";
}
int systemHwClockStatus = system("/sbin/hwclock -w");
if (systemHwClockStatus == -1 )
{
    qDebug() << "Failed to sync hardware clock";
}