/*
* Copyright 2013 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Author: Lars Uebernickel
*/
#include "timeformatter.h"
#include
#include
struct TimeFormatterPrivate
{
TimeFormatter *formatter;
QString format;
QString timeString;
qint64 time;
GDBusConnection *system_bus;
guint subscription_id;
GCancellable *cancellable;
};
static void
timedate1_properties_changed (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
Q_UNUSED(connection);
Q_UNUSED(sender_name);
Q_UNUSED(object_path);
Q_UNUSED(interface_name);
Q_UNUSED(signal_name);
TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
GVariant *changed;
GVariantIter *iter;
const gchar *name;
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)")))
return;
g_variant_get (parameters, "(s@a{sv}as)", NULL, &changed, &iter);
if (g_variant_lookup (changed, "Timezone", "s", NULL)) {
priv->formatter->update();
}
else {
while (g_variant_iter_next (iter, "&s", &name)) {
if (g_str_equal (name, "Timezone")) {
priv->formatter->update();
break;
}
}
}
g_variant_unref (changed);
g_variant_iter_free (iter);
}
static void
got_bus(GObject *object, GAsyncResult *result, gpointer user_data)
{
Q_UNUSED(object);
TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
GError *error = NULL;
priv->system_bus = g_bus_get_finish (result, &error);
if (priv->system_bus == NULL) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
qWarning("TimeFormatter: cannot connect to the system bus: %s", error->message);
g_error_free (error);
return;
}
/* Listen to the PropertiesChanged on the org.freedesktop.timedate1
* interface from any sender. In practice, this signal will only be sent
* from timedated (we can trust other processes on the system bus to behave
* nicely). That way, we don't have to watch timedated's well-known name
* and keep the process alive.
*/
priv->subscription_id = g_dbus_connection_signal_subscribe (priv->system_bus,
NULL, /* sender */
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
NULL,
"org.freedesktop.timedate1",
G_DBUS_SIGNAL_FLAGS_NONE,
timedate1_properties_changed,
priv, NULL);
}
TimeFormatter::TimeFormatter(QObject *parent): QObject(parent)
{
priv = new TimeFormatterPrivate;
priv->formatter = this;
priv->time = 0;
priv->format = "yyyy-MM-dd hh:mm";
priv->system_bus = NULL;
priv->subscription_id = 0;
priv->cancellable = g_cancellable_new ();
g_bus_get (G_BUS_TYPE_SYSTEM, priv->cancellable, got_bus, priv);
}
TimeFormatter::~TimeFormatter()
{
if (priv->system_bus) {
g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->subscription_id);
g_object_unref (priv->system_bus);
}
g_cancellable_cancel (priv->cancellable);
g_object_unref (priv->cancellable);
}
QString TimeFormatter::format() const
{
return priv->format;
}
QString TimeFormatter::timeString() const
{
return priv->timeString;
}
qint64 TimeFormatter::time() const
{
return priv->time;
}
void TimeFormatter::setFormat(const QString &format)
{
if (priv->format != format) {
priv->format = format;
Q_EMIT formatChanged(priv->format);
update();
}
}
void TimeFormatter::setTime(qint64 time)
{
if (priv->time != time) {
priv->time = time;
Q_EMIT timeChanged(priv->time);
update();
}
}
void TimeFormatter::update()
{
priv->timeString = formatTime();
Q_EMIT timeStringChanged(priv->timeString);
}
QString TimeFormatter::formatTime() const
{
return QDateTime::fromMSecsSinceEpoch(time() / 1000).toString(format());
}
GDateTimeFormatter::GDateTimeFormatter(QObject* parent)
: TimeFormatter(parent)
{
}
QString GDateTimeFormatter::formatTime() const
{
gchar* time_string;
GDateTime* datetime;
QByteArray formatBytes = format().toUtf8();
datetime = g_date_time_new_from_unix_local(time());
if (!datetime) {
return "";
}
time_string = g_date_time_format(datetime, formatBytes.constData());
QString formattedTime(QString::fromUtf8(time_string));
g_free(time_string);
g_date_time_unref(datetime);
return formattedTime;
}