on bcacecf help sign in
unity8/plugins/Utils/timeformatter.cpp
201 lines 5.9 kB history raw
1/*
2 * Copyright 2013 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Lars Uebernickel <lars.uebernickel@canonical.com>
17 */
19#include "timeformatter.h"
21#include <gio/gio.h>
22#include <QDateTime>
24struct TimeFormatterPrivate
26 TimeFormatter *formatter;
28 QString format;
29 QString timeString;
30 qint64 time;
32 GDBusConnection *system_bus;
33 guint subscription_id;
34 GCancellable *cancellable;
35};
37static void
38timedate1_properties_changed (GDBusConnection *connection,
39 const gchar *sender_name,
40 const gchar *object_path,
41 const gchar *interface_name,
42 const gchar *signal_name,
43 GVariant *parameters,
44 gpointer user_data)
46 Q_UNUSED(connection);
47 Q_UNUSED(sender_name);
48 Q_UNUSED(object_path);
49 Q_UNUSED(interface_name);
50 Q_UNUSED(signal_name);
52 TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
53 GVariant *changed;
54 GVariantIter *iter;
55 const gchar *name;
57 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)")))
58 return;
60 g_variant_get (parameters, "(s@a{sv}as)", nullptr, &changed, &iter);
62 if (g_variant_lookup (changed, "Timezone", "s", nullptr)) {
63 priv->formatter->update();
64 }
65 else {
66 while (g_variant_iter_next (iter, "&s", &name)) {
67 if (g_str_equal (name, "Timezone")) {
68 priv->formatter->update();
69 break;
70 }
71 }
72 }
74 g_variant_unref (changed);
75 g_variant_iter_free (iter);
78static void
79got_bus(GObject *object, GAsyncResult *result, gpointer user_data)
81 Q_UNUSED(object);
83 TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
84 GError *error = nullptr;
86 priv->system_bus = g_bus_get_finish (result, &error);
87 if (priv->system_bus == nullptr) {
88 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
89 qWarning("TimeFormatter: cannot connect to the system bus: %s", error->message);
90 g_error_free (error);
91 return;
92 }
94 /* Listen to the PropertiesChanged on the org.freedesktop.timedate1
95 * interface from any sender. In practice, this signal will only be sent
96 * from timedated (we can trust other processes on the system bus to behave
97 * nicely). That way, we don't have to watch timedated's well-known name
98 * and keep the process alive.
99 */
100 priv->subscription_id = g_dbus_connection_signal_subscribe (priv->system_bus,
101 nullptr, /* sender */
102 "org.freedesktop.DBus.Properties",
103 "PropertiesChanged",
104 nullptr,
105 "org.freedesktop.timedate1",
106 G_DBUS_SIGNAL_FLAGS_NONE,
107 timedate1_properties_changed,
108 priv, nullptr);
111TimeFormatter::TimeFormatter(QObject *parent): QObject(parent)
113 priv = new TimeFormatterPrivate;
114 priv->formatter = this;
115 priv->time = 0;
116 priv->format = "yyyy-MM-dd hh:mm";
117 priv->system_bus = nullptr;
118 priv->subscription_id = 0;
119 priv->cancellable = g_cancellable_new ();
121 g_bus_get (G_BUS_TYPE_SYSTEM, priv->cancellable, got_bus, priv);
124TimeFormatter::~TimeFormatter()
126 if (priv->system_bus) {
127 g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->subscription_id);
128 g_object_unref (priv->system_bus);
129 }
131 g_cancellable_cancel (priv->cancellable);
132 g_object_unref (priv->cancellable);
135QString TimeFormatter::format() const
137 return priv->format;
140QString TimeFormatter::timeString() const
142 return priv->timeString;
145qint64 TimeFormatter::time() const
147 return priv->time;
150void TimeFormatter::setFormat(const QString &format)
152 if (priv->format != format) {
153 priv->format = format;
154 Q_EMIT formatChanged(priv->format);
155 update();
156 }
159void TimeFormatter::setTime(qint64 time)
161 if (priv->time != time) {
162 priv->time = time;
163 Q_EMIT timeChanged(priv->time);
164 update();
165 }
168void TimeFormatter::update()
170 priv->timeString = formatTime();
171 Q_EMIT timeStringChanged(priv->timeString);
174QString TimeFormatter::formatTime() const
176 return QDateTime::fromMSecsSinceEpoch(time() / 1000).toString(format());
179GDateTimeFormatter::GDateTimeFormatter(QObject* parent)
180: TimeFormatter(parent)
184QString GDateTimeFormatter::formatTime() const
186 gchar* time_string;
187 GDateTime* datetime;
188 QByteArray formatBytes = format().toUtf8();
190 datetime = g_date_time_new_from_unix_local(time());
191 if (!datetime) {
192 return "";
193 }
195 time_string = g_date_time_format(datetime, formatBytes.constData());
196 QString formattedTime(QString::fromUtf8(time_string));
198 g_free(time_string);
199 g_date_time_unref(datetime);
200 return formattedTime;