on xenial help sign in
Removed TimeFormatter in favor of sdk LiveTimer+i18n.relativeDateTime
commit6d916f1f31e1f0f74faf7aa8990398bbaf25cef4 authorNick Dedekind <nick.dedekind@canonical.com> dateWed 15 Jul 2015, 12:37 (11 years ago) parente0d72bc
15 files changed+91−831
plugins/Utils/CMakeLists.txt−2 plugins/Utils/plugin.cpp−5 plugins/Utils/relativetimeformatter.cpp−260 plugins/Utils/relativetimeformatter.h−34 plugins/Utils/timeformatter.cpp−206 plugins/Utils/timeformatter.h−68 qml/Panel/Indicators/MenuItemFactory.qml+18−14 qml/Panel/Indicators/MessageMenuItemFactory.qml+30−22 tests/mocks/Utils/CMakeLists.txt−2 tests/mocks/Utils/Utils.qmltypes+31−28 tests/mocks/Utils/plugin.cpp−5 tests/plugins/Utils/CMakeLists.txt−1 tests/plugins/Utils/TimeFormatterTest.cpp−155 tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml+6−16 tests/qmltests/Panel/Indicators/tst_MessageMenuItemFactory.qml+6−13
plugins/Utils/CMakeLists.txt−2
@@ -13,8 +13,6 @@ set(QMLPLUGIN_SRC
1313 inputwatcher.cpp
1414 qlimitproxymodelqml.cpp
1515 unitysortfilterproxymodelqml.cpp
16− relativetimeformatter.cpp
17− timeformatter.cpp
1816 Timer.cpp
1917 unitymenumodelpaths.cpp
2018 windowkeysfilter.cpp
plugins/Utils/plugin.cpp−5
@@ -28,8 +28,6 @@
2828#include "inputwatcher.h"
2929#include "qlimitproxymodelqml.h"
3030#include "unitysortfilterproxymodelqml.h"
31−#include "relativetimeformatter.h"
32−#include "timeformatter.h"
3331#include "unitymenumodelpaths.h"
3432#include "windowkeysfilter.h"
3533#include "windowscreenshotprovider.h"
@@ -58,11 +56,8 @@ void UtilsPlugin::registerTypes(const char *uri)
5856 qmlRegisterType<QLimitProxyModelQML>(uri, 0, 1, "LimitProxyModel");
5957 qmlRegisterType<UnitySortFilterProxyModelQML>(uri, 0, 1, "UnitySortFilterProxyModel");
6058 qmlRegisterType<UnityMenuModelPaths>(uri, 0, 1, "UnityMenuModelPaths");
61− qmlRegisterType<TimeFormatter>(uri, 0, 1, "TimeFormatter");
6259 qmlRegisterType<WindowKeysFilter>(uri, 0, 1, "WindowKeysFilter");
63− qmlRegisterType<GDateTimeFormatter>(uri, 0, 1, "GDateTimeFormatter");
6460 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
65− qmlRegisterType<RelativeTimeFormatter>(uri, 0, 1, "RelativeTimeFormatter");
6661 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
6762 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
6863 qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
plugins/Utils/relativetimeformatter.cppdeleted−260
@@ -1,260 +0,0 @@
1−/*
2− * Copyright 2014 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− */
17−
18−// Local
19−#include "relativetimeformatter.h"
20−
21−// Qt
22−#include <QDateTime>
23−
24−// Other
25−#include <glib.h>
26−#include <glib/gi18n.h>
27−#include <locale.h>
28−#include <langinfo.h>
29−#include <string.h>
30−
31−RelativeTimeFormatter::RelativeTimeFormatter(QObject *parent)
32− : GDateTimeFormatter(parent)
33−{
34−}
35−
36− /* Check the system locale setting to see if the format is 24-hour
37− time or 12-hour time */
38−gboolean
39−is_locale_12h(void)
40−{
41− int i;
42− static const char *formats_24h[] = {"%H", "%R", "%T", "%OH", "%k", nullptr};
43− const char* t_fmt = nl_langinfo(T_FMT);
44−
45− for (i=0; formats_24h[i]!=nullptr; i++)
46− if (strstr(t_fmt, formats_24h[i]) != nullptr)
47− return FALSE;
48−
49− return TRUE;
50−}
51−
52−typedef enum
53−{
54− DATE_PROXIMITY_YESTERDAY,
55− DATE_PROXIMITY_TODAY,
56− DATE_PROXIMITY_TOMORROW,
57− DATE_PROXIMITY_LAST_WEEK,
58− DATE_PROXIMITY_NEXT_WEEK,
59− DATE_PROXIMITY_FAR
60−} date_proximity_t;
61−
62−static date_proximity_t
63−getDateProximity(GDateTime* now, GDateTime* time)
64−{
65− date_proximity_t prox = DATE_PROXIMITY_FAR;
66− gint now_year, now_month, now_day;
67− gint time_year, time_month, time_day;
68−
69− // does it happen today?
70− g_date_time_get_ymd(now, &now_year, &now_month, &now_day);
71− g_date_time_get_ymd(time, &time_year, &time_month, &time_day);
72− if ((now_year == time_year) && (now_month == time_month) && (now_day == time_day)) {
73− return DATE_PROXIMITY_TODAY;
74− }
75−
76− // did it happen yesterday?
77− GDateTime* yesterday = g_date_time_add_days(now, -1);
78− gint tom_year, tom_month, tom_day;
79− g_date_time_get_ymd(yesterday, &tom_year, &tom_month, &tom_day);
80− g_date_time_unref(yesterday);
81− if ((tom_year == time_year) && (tom_month == time_month) && (tom_day == time_day)) {
82− return DATE_PROXIMITY_YESTERDAY;
83− }
84−
85− // does it happen tomorrow?
86− GDateTime* tomorrow = g_date_time_add_days(now, 1);
87− g_date_time_get_ymd(tomorrow, &tom_year, &tom_month, &tom_day);
88− g_date_time_unref(tomorrow);
89− if ((tom_year == time_year) && (tom_month == time_month) && (tom_day == time_day)) {
90− return DATE_PROXIMITY_TOMORROW;
91− }
92−
93− // does it happen this week?
94− if (g_date_time_compare(time, now) < 0) {
95− GDateTime* last_week = g_date_time_add_days(now, -6);
96− GDateTime* last_week_bound = g_date_time_new_local(g_date_time_get_year(last_week),
97− g_date_time_get_month(last_week),
98− g_date_time_get_day_of_month(last_week),
99− 0, 0, 0);
100− if (g_date_time_compare(time, last_week_bound) >= 0)
101− prox = DATE_PROXIMITY_LAST_WEEK;
102−
103− g_date_time_unref(last_week);
104− g_date_time_unref(last_week_bound);
105− } else {
106− GDateTime* next_week = g_date_time_add_days(now, 6);
107− GDateTime* next_week_bound = g_date_time_new_local(g_date_time_get_year(next_week),
108− g_date_time_get_month(next_week),
109− g_date_time_get_day_of_month(next_week),
110− 23, 59, 59.9);
111− if (g_date_time_compare(time, next_week_bound) <= 0)
112− prox = DATE_PROXIMITY_NEXT_WEEK;
113−
114− g_date_time_unref(next_week);
115− g_date_time_unref(next_week_bound);
116− }
117−
118− return prox;
119−}
120−
121−const char*
122−dgettext_datetime(const char *text)
123−{
124− return dgettext("unity8", text);
125−}
126−
127−/**
128− * _ a time yesterday should be shown as (e.g. “Yesterday 3:55 PM”)
129− * _ a time today should be shown as just the time (e.g. “3:55 PM”)
130− * _ a time tomorrow should be shown as(e.g. “Tomorrow 3:55 PM”)
131− * _ a time any other day this week should be shown as the short version of the
132− * day and time (e.g. “Wed 3:55 PM”)
133− * weekday (e.g. “Friday”)
134− * _ a time after this week should be shown as the short version of the day,
135− * date, and time (e.g. “Wed 21 Apr 3:55 PM”)
136− * _ in addition, when presenting the times of upcoming events, the time should
137− * be followed by the timezone if it is different from the one the computer
138− * is currently set to. For example, “Wed 3:55 PM UTC−5”.
139− *
140− * TODO - keep inline with indicator-datetime
141− */
142−char* generate_full_format_string_at_time (GDateTime* now,
143− GDateTime* then)
144−{
145− GString* ret = g_string_new (nullptr);
146−
147− if (then != nullptr) {
148− const date_proximity_t prox = getDateProximity(now, then);
149−
150− if (is_locale_12h()) {
151− switch (prox) {
152− case DATE_PROXIMITY_YESTERDAY:
153− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
154− This format string is used for showing, on a 12-hour clock, times that happen yesterday.
155− (\u2003 is a unicode em space which is slightly wider than a normal space.)
156− en_US example: "Yesterday\u2003%l:%M %p" --> "Yesterday 1:00 PM" */
157− g_string_assign (ret, dgettext_datetime("Yesterday\u2003%l:%M %p"));
158− break;
159−
160− case DATE_PROXIMITY_TODAY:
161− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
162− This format string is used for showing, on a 12-hour clock, times that happened today.
163− en_US example: "%l:%M %p" --> "1:00 PM" */
164− g_string_assign (ret, dgettext_datetime("%l:%M %p"));
165− break;
166−
167− case DATE_PROXIMITY_TOMORROW:
168− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
169− This format string is used for showing, on a 12-hour clock, events/appointments that happen tomorrow.
170− (\u2003 is a unicode em space which is slightly wider than a normal space.)
171− en_US example: "Tomorrow\u2003%l:%M %p" --> "Tomorrow 1:00 PM" */
172− g_string_assign (ret, dgettext_datetime("Tomorrow\u2003%l:%M %p"));
173− break;
174−
175− case DATE_PROXIMITY_LAST_WEEK:
176− case DATE_PROXIMITY_NEXT_WEEK:
177− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
178− This format string is used for showing, on a 12-hour clock, times that happened in the last week.
179− (\u2003 is a unicode em space which is slightly wider than a normal space.)
180− en_US example: "%a\u2003%l:%M %p" --> "Fri 1:00 PM" */
181− g_string_assign (ret, dgettext_datetime("%a\u2003%l:%M %p"));
182− break;
183−
184− case DATE_PROXIMITY_FAR:
185− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
186− This format string is used for showing, on a 12-hour clock, times that happened before a week from now.
187− (\u2003 is a unicode em space which is slightly wider than a normal space.)
188− en_US example: "%a %d %b\u2003%l:%M %p" --> "Fri Oct 31 1:00 PM"
189− en_GB example: "%a %b %d\u2003%l:%M %p" --> "Fri 31 Oct 1:00 PM" */
190− g_string_assign (ret, dgettext_datetime("%a %d %b\u2003%l:%M %p"));
191− break;
192− }
193− } else {
194− switch (prox) {
195−
196− case DATE_PROXIMITY_YESTERDAY:
197− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
198− This format string is used for showing, on a 24-hour clock, times that happen yesterday.
199− (\u2003 is a unicode em space which is slightly wider than a normal space.)
200− en_US example: "Yesterday\u2003%l:%M %p" --> "Yesterday 13:00" */
201− g_string_assign (ret, dgettext_datetime("Yesterday\u2003%H:%M"));
202− break;
203−
204− case DATE_PROXIMITY_TODAY:
205− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
206− This format string is used for showing, on a 24-hour clock, times that happened today.
207− en_US example: "%H:%M" --> "13:00" */
208− g_string_assign (ret, dgettext_datetime("%H:%M"));
209− break;
210−
211− case DATE_PROXIMITY_TOMORROW:
212− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
213− This format string is used for showing, on a 24-hour clock, events/appointments that happen tomorrow.
214− (\u2003 is a unicode em space which is slightly wider than a normal space.)
215− en_US example: "Tomorrow\u2003%l:%M %p" --> "Tomorrow 13:00" */
216− g_string_assign (ret, dgettext_datetime("Tomorrow\u2003%H:%M"));
217− break;
218−
219− case DATE_PROXIMITY_LAST_WEEK:
220− case DATE_PROXIMITY_NEXT_WEEK:
221− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
222− This format string is used for showing, on a 24-hour clock, times that happened in the last week.
223− (\u2003 is a unicode em space which is slightly wider than a normal space.)
224− en_US example: "%a\u2003%H:%M" --> "Fri 13:00" */
225− g_string_assign (ret, dgettext_datetime("%a\u2003%H:%M"));
226− break;
227−
228− case DATE_PROXIMITY_FAR:
229− /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
230− This format string is used for showing, on a 24-hour clock, times that happened before a week from now.
231− (\u2003 is a unicode em space which is slightly wider than a normal space.)
232− en_US example: "%a %d %b\u2003%H:%M" --> "Fri Oct 31 13:00"
233− en_GB example: "%a %b %d\u2003%H:%M" --> "Fri 31 Oct 13:00" */
234− g_string_assign (ret, dgettext_datetime("%a %d %b\u2003%H:%M"));
235− break;
236− }
237− }
238− }
239−
240− return g_string_free (ret, FALSE);
241−}
242−
243−QString RelativeTimeFormatter::format() const
244−{
245− GDateTime* now = g_date_time_new_now_local();
246− if (!now) { return QString(); }
247−
248− GDateTime* then = g_date_time_new_from_unix_local(time());
249− if (!then) { return QString(); }
250−
251− char* time_format = generate_full_format_string_at_time(now, then);
252−
253− QString str(QString::fromUtf8(time_format));
254− g_free(time_format);
255−
256− g_date_time_unref(now);
257− g_date_time_unref(then);
258−
259− return str;
260−}
plugins/Utils/relativetimeformatter.hdeleted−34
@@ -1,34 +0,0 @@
1−/*
2− * Copyright 2014 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− */
17−
18−#ifndef RELATIVETIMEFORMATTER_H
19−#define RELATIVETIMEFORMATTER_H
20−
21−#include "timeformatter.h"
22−
23−// TODO - move this to the sdk
24−// https://blueprints.launchpad.net/ubuntu-ui-toolkit/+spec/time-formatter
25−class RelativeTimeFormatter : public GDateTimeFormatter
26−{
27− Q_OBJECT
28−public:
29− RelativeTimeFormatter(QObject *parent = 0);
30−
31− QString format() const override;
32−};
33−
34−#endif // RELATIVETIMEFORMATTER_H
plugins/Utils/timeformatter.cppdeleted−206
@@ -1,206 +0,0 @@
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− */
18−
19−#include "timeformatter.h"
20−
21−#include <gio/gio.h>
22−#include <QDateTime>
23−
24−struct TimeFormatterPrivate
25−{
26− TimeFormatter *formatter;
27−
28− QString format;
29− QString timeString;
30− qint64 time;
31−
32− GDBusConnection *system_bus;
33− guint subscription_id;
34− GCancellable *cancellable;
35−};
36−
37−static void
38−timedate1_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)
45−{
46− Q_UNUSED(connection);
47− Q_UNUSED(sender_name);
48− Q_UNUSED(object_path);
49− Q_UNUSED(interface_name);
50− Q_UNUSED(signal_name);
51−
52− TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
53− GVariant *changed;
54− GVariantIter *iter;
55− const gchar *name;
56−
57− if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)")))
58− return;
59−
60− g_variant_get (parameters, "(s@a{sv}as)", nullptr, &changed, &iter);
61−
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− }
73−
74− g_variant_unref (changed);
75− g_variant_iter_free (iter);
76−}
77−
78−static void
79−got_bus(GObject *object, GAsyncResult *result, gpointer user_data)
80−{
81− Q_UNUSED(object);
82−
83− TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
84− GError *error = nullptr;
85−
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− }
93−
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);
109−}
110−
111−TimeFormatter::TimeFormatter(QObject *parent): QObject(parent)
112−{
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 ();
120−
121− g_bus_get (G_BUS_TYPE_SYSTEM, priv->cancellable, got_bus, priv);
122−}
123−
124−TimeFormatter::TimeFormatter(const QString &initialFormat, QObject *parent): TimeFormatter(parent)
125−{
126− priv->format = initialFormat;
127−}
128−
129−TimeFormatter::~TimeFormatter()
130−{
131− if (priv->system_bus) {
132− g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->subscription_id);
133− g_object_unref (priv->system_bus);
134− }
135−
136− g_cancellable_cancel (priv->cancellable);
137− g_object_unref (priv->cancellable);
138−}
139−
140−QString TimeFormatter::format() const
141−{
142− return priv->format;
143−}
144−
145−QString TimeFormatter::timeString() const
146−{
147− return priv->timeString;
148−}
149−
150−qint64 TimeFormatter::time() const
151−{
152− return priv->time;
153−}
154−
155−void TimeFormatter::setFormat(const QString &format)
156−{
157− if (priv->format != format) {
158− priv->format = format;
159− Q_EMIT formatChanged(priv->format);
160− update();
161− }
162−}
163−
164−void TimeFormatter::setTime(qint64 time)
165−{
166− if (priv->time != time) {
167− priv->time = time;
168− Q_EMIT timeChanged(priv->time);
169− update();
170− }
171−}
172−
173−void TimeFormatter::update()
174−{
175− priv->timeString = formatTime();
176− Q_EMIT timeStringChanged(priv->timeString);
177−}
178−
179−QString TimeFormatter::formatTime() const
180−{
181− return QDateTime::fromMSecsSinceEpoch(time() / 1000).toString(format());
182−}
183−
184−GDateTimeFormatter::GDateTimeFormatter(QObject* parent)
185−: TimeFormatter("%d-%m-%Y %I:%M%p", parent)
186−{
187−}
188−
189−QString GDateTimeFormatter::formatTime() const
190−{
191− gchar* time_string;
192− GDateTime* datetime;
193− QByteArray formatBytes = format().toUtf8();
194−
195− datetime = g_date_time_new_from_unix_local(time());
196− if (!datetime) {
197− return "";
198− }
199−
200− time_string = g_date_time_format(datetime, formatBytes.constData());
201− QString formattedTime(QString::fromUtf8(time_string));
202−
203− g_free(time_string);
204− g_date_time_unref(datetime);
205− return formattedTime;
206−}
plugins/Utils/timeformatter.hdeleted−68
@@ -1,68 +0,0 @@
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− */
18−
19−#ifndef TIME_FORMATTER_H
20−#define TIME_FORMATTER_H
21−
22−#include <QObject>
23−
24−// TODO - bug #1260728
25−class TimeFormatter : public QObject
26−{
27− Q_OBJECT
28− Q_PROPERTY(QString format READ format WRITE setFormat NOTIFY formatChanged)
29− Q_PROPERTY(QString timeString READ timeString NOTIFY timeStringChanged)
30− Q_PROPERTY(qint64 time READ time WRITE setTime NOTIFY timeChanged)
31−
32−public:
33− TimeFormatter(QObject *parent = 0);
34− virtual ~TimeFormatter();
35−
36− virtual QString format() const;
37− QString timeString() const;
38− qint64 time() const;
39−
40− void setFormat(const QString &format);
41− void setTime(qint64 time);
42−
43− void update();
44−
45−Q_SIGNALS:
46− void formatChanged(const QString &format);
47− void timeStringChanged(const QString &timeString);
48− void timeChanged(qint64 time);
49−
50−protected:
51− TimeFormatter(const QString &initialFormat, QObject *parent = 0);
52−
53− virtual QString formatTime() const;
54−
55−private:
56− struct TimeFormatterPrivate *priv;
57−};
58−
59−class GDateTimeFormatter : public TimeFormatter
60−{
61−public:
62− GDateTimeFormatter(QObject *parent = 0);
63−
64−protected:
65− QString formatTime() const override;
66−};
67−
68−#endif
qml/Panel/Indicators/MenuItemFactory.qml+18−14
@@ -346,20 +346,23 @@ Item {
346346 id: alarmMenu;
347347
348348 Menus.EventMenu {
349+ id: alarmItem
349350 objectName: "alarmMenu"
350351 property QtObject menuData: null
351352 property var menuModel: menuFactory.menuModel
352353 property int menuIndex: -1
353354 property var extendedData: menuData && menuData.ext || undefined
354− // TODO - bug #1260728
355− property var timeFormatter: Utils.GDateTimeFormatter {
356− time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
357− format: getExtendedProperty(extendedData, "xCanonicalTimeFormat", "")
355+
356+ property string serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) / 1000)
357+ LiveTimer {
358+ frequency: LiveTimer.Relative
359+ relativeTime: alarmItem.serverTime
360+ onTrigger: alarmItem.serverTime = new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) / 1000)
358361 }
359362
360363 text: menuData && menuData.label || ""
361364 iconSource: menuData && menuData.icon || "image://theme/alarm-clock"
362− time: timeFormatter.timeString
365+ time: i18n.relativeDateTime(serverTime)
363366 enabled: menuData && menuData.sensitive || false
364367 highlightWhenPressed: false
365368
@@ -375,8 +378,7 @@ Item {
375378
376379 function loadAttributes() {
377380 if (!menuModel || menuIndex == -1) return;
378− menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64',
379− 'x-canonical-time-format': 'string'});
381+ menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64'});
380382 }
381383 }
382384 }
@@ -385,20 +387,23 @@ Item {
385387 id: appointmentMenu;
386388
387389 Menus.EventMenu {
390+ id: appointmentItem
388391 objectName: "appointmentMenu"
389392 property QtObject menuData: null
390393 property var menuModel: menuFactory.menuModel
391394 property int menuIndex: -1
392395 property var extendedData: menuData && menuData.ext || undefined
393− // TODO - bug #1260728
394− property var timeFormatter: Utils.GDateTimeFormatter {
395− time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
396− format: getExtendedProperty(extendedData, "xCanonicalTimeFormat", "")
396+
397+ property string serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) / 1000)
398+ LiveTimer {
399+ frequency: LiveTimer.Relative
400+ relativeTime: appointmentItem.serverTime
401+ onTrigger: appointmentItem.serverTime = new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) / 1000)
397402 }
398403
399404 text: menuData && menuData.label || ""
400405 iconSource: menuData && menuData.icon || "image://theme/calendar"
401− time: timeFormatter.timeString
406+ time: i18n.relativeDateTime(serverTime)
402407 eventColor: getExtendedProperty(extendedData, "xCanonicalColor", Qt.rgba(0.0, 0.0, 0.0, 0.0))
403408 enabled: menuData && menuData.sensitive || false
404409 highlightWhenPressed: false
@@ -416,8 +421,7 @@ Item {
416421 function loadAttributes() {
417422 if (!menuModel || menuIndex == -1) return;
418423 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-color': 'string',
419− 'x-canonical-time': 'int64',
420− 'x-canonical-time-format': 'string'});
424+ 'x-canonical-time': 'int64'});
421425 }
422426 }
423427 }
qml/Panel/Indicators/MessageMenuItemFactory.qml+30−22
@@ -35,12 +35,16 @@ Loader {
3535 signal menuSelected
3636 signal menuDeselected
3737
38− property var extendedData: menuData && menuData.ext || undefined
39− property var actionsDescription: getExtendedProperty(extendedData, "xCanonicalMessageActions", undefined)
40−
41− // TODO - bug #1260728
42− property var timeFormatter: Utils.RelativeTimeFormatter {
43− time: getExtendedProperty(extendedData, "xCanonicalTime", 0) / 1000000
38+ QtObject {
39+ id: priv
40+ property var extendedData: menuData && menuData.ext || undefined
41+ property var actionsDescription: getExtendedProperty(extendedData, "xCanonicalMessageActions", undefined)
42+ property string time: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) / 1000000)
43+ }
44+ LiveTimer {
45+ frequency: LiveTimer.Relative
46+ relativeTime: priv.time
47+ onTrigger: priv.time = new Date(getExtendedProperty(priv.extendedData, "xCanonicalTime", 0) / 1000000)
4448 }
4549
4650 onMenuModelChanged: {
@@ -50,7 +54,7 @@ Loader {
5054 loadAttributes();
5155 }
5256
53− sourceComponent: loadMessage(actionsDescription)
57+ sourceComponent: loadMessage(priv.actionsDescription)
5458
5559 function loadMessage(actions)
5660 {
@@ -100,11 +104,11 @@ Loader {
100104 objectName: "simpleTextMessage"
101105 // text
102106 title: menuData && menuData.label || ""
103− time: timeFormatter.timeString
104− body: getExtendedProperty(extendedData, "xCanonicalText", "")
107+ time: i18n.relativeDateTime(priv.time)
108+ body: getExtendedProperty(priv.extendedData, "xCanonicalText", "")
105109 // icons
106− avatar: getExtendedProperty(extendedData, "icon", "image://theme/contact")
107− icon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "image://theme/message")
110+ avatar: getExtendedProperty(priv.extendedData, "icon", "image://theme/contact")
111+ icon: getExtendedProperty(priv.extendedData, "xCanonicalAppIcon", "image://theme/message")
108112 // actions
109113 enabled: menuData && menuData.sensitive || false
110114 removable: !selected
@@ -133,7 +137,9 @@ Loader {
133137 Menus.TextMessageMenu {
134138 id: message
135139 objectName: "textMessage"
136− property var replyActionDescription: actionsDescription && actionsDescription.length > 0 ? actionsDescription[0] : undefined
140+ property var replyActionDescription: priv.actionsDescription && priv.actionsDescription.length > 0 ?
141+ priv.actionsDescription[0] :
142+ undefined
137143
138144 property var replyAction: QMenuModel.UnityMenuAction {
139145 model: menuModel
@@ -143,13 +149,13 @@ Loader {
143149
144150 // text
145151 title: menuData && menuData.label || ""
146− time: timeFormatter.timeString
147− body: getExtendedProperty(extendedData, "xCanonicalText", "")
152+ time: i18n.relativeDateTime(priv.time)
153+ body: getExtendedProperty(priv.extendedData, "xCanonicalText", "")
148154 replyButtonText: getExtendedProperty(replyActionDescription, "label", "Send")
149155 replyHintText: i18n.ctr("Label: Hint in message indicator line edit", "Reply")
150156 // icons
151− avatar: getExtendedProperty(extendedData, "icon", "image://theme/contact")
152− icon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "image://theme/message")
157+ avatar: getExtendedProperty(priv.extendedData, "icon", "image://theme/contact")
158+ icon: getExtendedProperty(priv.extendedData, "xCanonicalAppIcon", "image://theme/message")
153159 // actions
154160 replyEnabled: replyAction.valid && replyAction.enabled
155161 enabled: menuData && menuData.sensitive || false
@@ -183,8 +189,10 @@ Loader {
183189 Menus.SnapDecisionMenu {
184190 id: message
185191 objectName: "snapDecision"
186− property var activateActionDescription: actionsDescription && actionsDescription.length > 0 ? actionsDescription[0] : undefined
187− property var replyActionDescription: actionsDescription && actionsDescription.length > 1 ? actionsDescription[1] : undefined
192+ property var activateActionDescription: priv.actionsDescription && priv.actionsDescription.length > 0 ?
193+ priv.actionsDescription[0] : undefined
194+ property var replyActionDescription: priv.actionsDescription && priv.actionsDescription.length > 1 ?
195+ priv.actionsDescription[1] : undefined
188196
189197 property var activateAction: QMenuModel.UnityMenuAction {
190198 model: menuModel
@@ -199,13 +207,13 @@ Loader {
199207
200208 // text
201209 title: menuData && menuData.label || ""
202− time: timeFormatter.timeString
203− body: getExtendedProperty(extendedData, "xCanonicalText", "")
210+ time: i18n.relativeDateTime(priv.time)
211+ body: getExtendedProperty(priv.extendedData, "xCanonicalText", "")
204212 actionButtonText: getExtendedProperty(activateActionDescription, "label", "Call back")
205213 replyButtonText: getExtendedProperty(replyActionDescription, "label", "Send")
206214 // icons
207− avatar: getExtendedProperty(extendedData, "icon", "image://theme/contact")
208− icon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "image://theme/missed-call")
215+ avatar: getExtendedProperty(priv.extendedData, "icon", "image://theme/contact")
216+ icon: getExtendedProperty(priv.extendedData, "xCanonicalAppIcon", "image://theme/missed-call")
209217 // actions
210218 actionEnabled: activateAction.valid && activateAction.enabled
211219 replyEnabled: replyAction.valid && replyAction.enabled
tests/mocks/Utils/CMakeLists.txt−2
@@ -12,8 +12,6 @@ set(QMLPLUGIN_SRC
1212 ${CMAKE_SOURCE_DIR}/plugins/Utils/inputwatcher.cpp
1313 ${CMAKE_SOURCE_DIR}/plugins/Utils/qlimitproxymodelqml.cpp
1414 ${CMAKE_SOURCE_DIR}/plugins/Utils/unitysortfilterproxymodelqml.cpp
15− ${CMAKE_SOURCE_DIR}/plugins/Utils/relativetimeformatter.cpp
16− ${CMAKE_SOURCE_DIR}/plugins/Utils/timeformatter.cpp
1715 ${CMAKE_SOURCE_DIR}/plugins/Utils/unitymenumodelpaths.cpp
1816 ${CMAKE_SOURCE_DIR}/plugins/Utils/windowkeysfilter.cpp
1917 ${CMAKE_SOURCE_DIR}/plugins/Utils/windowscreenshotprovider.cpp
tests/mocks/Utils/Utils.qmltypes+31−28
@@ -4,9 +4,18 @@ import QtQuick.tooling 1.1
44// It is used for QML tooling purposes only.
55//
66// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable Utils 0.1 plugins'
7+// 'qmlplugindump -notrelocatable Utils 0.1 tests/mocks'
88
99Module {
10+ Component {
11+ name: "Constants"
12+ prototype: "QObject"
13+ exports: ["Utils/Constants 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Property { name: "indicatorValueTimeout"; type: "int"; isReadonly: true }
18+ }
1019 Component {
1120 name: "EasingCurve"
1221 prototype: "QObject"
@@ -17,6 +26,22 @@ Module {
1726 Property { name: "progress"; type: "double" }
1827 Property { name: "value"; type: "double"; isReadonly: true }
1928 }
29+ Component {
30+ name: "InputWatcher"
31+ prototype: "QObject"
32+ exports: ["Utils/InputWatcher 0.1"]
33+ exportMetaObjectRevisions: [0]
34+ Property { name: "target"; type: "QObject"; isPointer: true }
35+ Property { name: "targetPressed"; type: "bool"; isReadonly: true }
36+ Signal {
37+ name: "targetChanged"
38+ Parameter { name: "value"; type: "QObject"; isPointer: true }
39+ }
40+ Signal {
41+ name: "targetPressedChanged"
42+ Parameter { name: "value"; type: "bool" }
43+ }
44+ }
2045 Component {
2146 name: "QAbstractProxyModel"
2247 prototype: "QAbstractItemModel"
@@ -59,33 +84,6 @@ Module {
5984 Method { name: "clear" }
6085 Method { name: "invalidate" }
6186 }
62− Component {
63− name: "RelativeTimeFormatter"
64− prototype: "TimeFormatter"
65− exports: ["Utils/RelativeTimeFormatter 0.1"]
66− exportMetaObjectRevisions: [0]
67− }
68− Component {
69− name: "TimeFormatter"
70− prototype: "QObject"
71− exports: ["Utils/GDateTimeFormatter 0.1", "Utils/TimeFormatter 0.1"]
72− exportMetaObjectRevisions: [0, 0]
73− Property { name: "format"; type: "string" }
74− Property { name: "timeString"; type: "string"; isReadonly: true }
75− Property { name: "time"; type: "qlonglong" }
76− Signal {
77− name: "formatChanged"
78− Parameter { name: "format"; type: "string" }
79− }
80− Signal {
81− name: "timeStringChanged"
82− Parameter { name: "timeString"; type: "string" }
83− }
84− Signal {
85− name: "timeChanged"
86− Parameter { name: "time"; type: "qlonglong" }
87− }
88− }
8987 Component {
9088 name: "UnityMenuModelPaths"
9189 prototype: "QObject"
@@ -160,6 +158,11 @@ Module {
160158 isCreatable: false
161159 isSingleton: true
162160 exportMetaObjectRevisions: [0]
161+ Property { name: "geometry"; type: "QVariantMap" }
162+ Signal {
163+ name: "geometryChanged"
164+ Parameter { name: "geometry"; type: "QVariantMap" }
165+ }
163166 Method {
164167 name: "saveGeometry"
165168 Parameter { name: "windowId"; type: "string" }
tests/mocks/Utils/plugin.cpp−5
@@ -30,8 +30,6 @@
3030#include <inputwatcher.h>
3131#include <qlimitproxymodelqml.h>
3232#include <unitysortfilterproxymodelqml.h>
33−#include <relativetimeformatter.h>
34−#include <timeformatter.h>
3533#include <unitymenumodelpaths.h>
3634#include <windowkeysfilter.h>
3735#include <windowscreenshotprovider.h>
@@ -58,11 +56,8 @@ void FakeUtilsPlugin::registerTypes(const char *uri)
5856 qmlRegisterType<QLimitProxyModelQML>(uri, 0, 1, "LimitProxyModel");
5957 qmlRegisterType<UnitySortFilterProxyModelQML>(uri, 0, 1, "UnitySortFilterProxyModel");
6058 qmlRegisterType<UnityMenuModelPaths>(uri, 0, 1, "UnityMenuModelPaths");
61− qmlRegisterType<TimeFormatter>(uri, 0, 1, "TimeFormatter");
6259 qmlRegisterType<WindowKeysFilter>(uri, 0, 1, "WindowKeysFilter");
63− qmlRegisterType<GDateTimeFormatter>(uri, 0, 1, "GDateTimeFormatter");
6460 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
65− qmlRegisterType<RelativeTimeFormatter>(uri, 0, 1, "RelativeTimeFormatter");
6661 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
6762 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
6863 qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
tests/plugins/Utils/CMakeLists.txt−1
@@ -7,7 +7,6 @@ include_directories(
77foreach(util_test
88 QLimitProxyModel
99 UnitySortFilterProxyModel
10− TimeFormatter
1110 HomeKeyWatcher
1211)
1312 add_executable(${util_test}TestExec ${util_test}Test.cpp ModelTest.cpp)
tests/plugins/Utils/TimeFormatterTest.cppdeleted−155
@@ -1,155 +0,0 @@
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 Lesser 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 Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser 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− */
18−
19−#include "timeformatter.h"
20−#include "relativetimeformatter.h"
21−
22−#include <locale.h>
23−
24−#include <QtTest>
25−#include <QDebug>
26−
27−class TimeFormatterTest : public QObject
28−{
29− Q_OBJECT
30−private:
31− void addTestData(QList<int> daysToAdd = QList<int>()) {
32− QTest::addColumn<QDateTime>("time");
33−
34− Q_FOREACH(int dayToAdd, daysToAdd) {
35− QDateTime time = QDateTime::currentDateTime().addDays(dayToAdd);
36− QDateTime am(time); am.setTime(QTime(1, 1, 1));
37− QDateTime midday(time); midday.setTime(QTime(12, 0, 0));
38− QDateTime pm(time); pm.setTime(QTime(17, 59, 59));
39−
40− QTest::newRow(QString("%1day-am").arg(dayToAdd).toLatin1()) << am;
41− QTest::newRow(QString("%1day-midday").arg(dayToAdd).toLatin1()) << midday;
42− QTest::newRow(QString("%1day-pm").arg(dayToAdd).toLatin1()) << pm;
43− }
44−
45− }
46−
47−private Q_SLOTS:
48− void testTimeFormatter_Format_data() { addTestData(QList<int>() << 0); }
49− void testTimeFormatter_Format()
50− {
51− QFETCH(QDateTime, time);
52− const QString format = "hh:mm dd.MM.yy";
53−
54− TimeFormatter formatter;
55− formatter.setTime(time.toMSecsSinceEpoch() * 1000);
56− formatter.setFormat(format);
57−
58− QCOMPARE(formatter.timeString(), time.toString(format));
59− }
60−
61− void tesGDatetTimeFormatter_Format_data() { addTestData(QList<int>() << 0); }
62− void tesGDatetTimeFormatter_Format()
63− {
64− QFETCH(QDateTime, time);
65− const QString format = "%d-%m-%Y %I:%M%p";
66−
67− GDateTimeFormatter formatter;
68− formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
69− formatter.setFormat(format);
70−
71− QCOMPARE(formatter.timeString(), time.toString("dd-MM-yyyy hh:mmAP"));
72− }
73−
74− void tesRelativeTimeFormatter_FarBack_data() { addTestData(QList<int>() << -200 << -20 << -7); }
75− void tesRelativeTimeFormatter_FarBack()
76− {
77− QFETCH(QDateTime, time);
78−
79− RelativeTimeFormatter formatter;
80− formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
81−
82− QCOMPARE(formatter.timeString(), time.toString("ddd dd MMM\u2003HH:mm"));
83− }
84−
85− void tesRelativeTimeFormatter_WeekBack_data() { addTestData(QList<int>() << -6 << -2); }
86− void tesRelativeTimeFormatter_WeekBack()
87− {
88− QFETCH(QDateTime, time);
89−
90− RelativeTimeFormatter formatter;
91− formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
92−
93− QCOMPARE(formatter.timeString(), time.toString("ddd\u2003HH:mm"));
94− }
95−
96− void tesRelativeTimeFormatter_Yesterday_data() { addTestData(QList<int>() << -1); }
97− void tesRelativeTimeFormatter_Yesterday()
98− {
99− QFETCH(QDateTime, time);
100−
101− RelativeTimeFormatter formatter;
102− formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
103−
104− QCOMPARE(formatter.timeString(), QString("Yesterday\u2003%1").arg(time.toString("HH:mm")));
105− }
106−
107− void tesRelativeTimeFormatter_Today_data() { addTestData(QList<int>() << 0); }
108− void tesRelativeTimeFormatter_Today()
109− {
110− QFETCH(QDateTime, time);
111−
112− RelativeTimeFormatter formatter;
113− formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
114−
115− QCOMPARE(formatter.timeString(), time.toString("HH:mm"));
116− }
117−
118− void tesRelativeTimeFormatter_Tomorrow_data() { addTestData(QList<int>() << 1); }
119− void tesRelativeTimeFormatter_Tomorrow()
120− {
121− QFETCH(QDateTime, time);
122−
123− RelativeTimeFormatter formatter;
124− formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
125−
126− QCOMPARE(formatter.timeString(), QString("Tomorrow\u2003%1").arg(time.toString("HH:mm")));
127− }
128−
129−
130− void tesRelativeTimeFormatter_WeekForward_data() { addTestData(QList<int>() << 2 << 6); }
131− void tesRelativeTimeFormatter_WeekForward()
132− {
133− QFETCH(QDateTime, time);
134−
135− RelativeTimeFormatter formatter;
136− formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
137−
138− QCOMPARE(formatter.timeString(), time.toString("ddd\u2003HH:mm"));
139− }
140−
141− void tesRelativeTimeFormatter_FarForward_data() { addTestData(QList<int>() << 7 << 20 << 200); }
142− void tesRelativeTimeFormatter_FarForward()
143− {
144− QFETCH(QDateTime, time);
145−
146− RelativeTimeFormatter formatter;
147− formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
148−
149− QCOMPARE(formatter.timeString(), time.toString("ddd dd MMM\u2003HH:mm"));
150− }
151−};
152−
153−QTEST_GUILESS_MAIN(TimeFormatterTest)
154−
155−#include "TimeFormatterTest.moc"
tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml+6−16
@@ -50,10 +50,6 @@ Item {
5050 }
5151 }
5252
53− Utils.GDateTimeFormatter {
54− id: timeFormatter
55− }
56−
5753 UT.UnityTestCase {
5854 name: "MenuItemFactory"
5955 when: windowShown
@@ -374,9 +370,9 @@ Item {
374370 function test_create_alarmMenu_data() {
375371 return [
376372 {label: "testLabel1", enabled: true, icon: "file:///testIcon1", color: Qt.rgba(0, 0, 0, 0),
377− time: new Date(2014, 04, 14), timeFormat: "%a %d %b %l:%M %p"},
373+ time: new Date(2014, 04, 14)},
378374 {label: "testLabel2", enabled: false, icon: "file:///testIcon2", color: Qt.rgba(1, 0, 0, 0),
379− time: new Date(2015, 11, 31), timeFormat: "%A" },
375+ time: new Date(2015, 11, 31) },
380376 ];
381377 }
382378
@@ -386,11 +382,8 @@ Item {
386382 menuData.sensitive = data.enabled;
387383 menuData.icon = data.icon;
388384 menuData.ext = {
389− 'xCanonicalTime': data.time.getTime() / 1000,
390− 'xCanonicalTimeFormat': data.timeFormat
385+ 'xCanonicalTime': data.time.getTime() * 1000
391386 };
392− timeFormatter.format = data.timeFormat;
393− timeFormatter.time = data.time.getTime() / 1000;
394387
395388 loader.data = menuData;
396389 loader.sourceComponent = factory.load(menuData);
@@ -399,7 +392,7 @@ Item {
399392
400393 compare(loader.item.text, data.label, "Label does not match data");
401394 compare(loader.item.iconSource, data.icon, "Icon does not match data");
402− compare(loader.item.time, timeFormatter.timeString, "Time does not match data");
395+ compare(loader.item.time, i18n.relativeDateTime(data.time), "Time does not match data");
403396 compare(loader.item.enabled, data.enabled, "Enabled does not match data");
404397 }
405398
@@ -419,11 +412,8 @@ Item {
419412 menuData.icon = data.icon;
420413 menuData.ext = {
421414 'xCanonicalColor': data.colour,
422− 'xCanonicalTime': data.time.getTime() / 1000,
423− 'xCanonicalTimeFormat': data.timeFormat
415+ 'xCanonicalTime': data.time.getTime() * 1000
424416 };
425− timeFormatter.format = data.timeFormat;
426− timeFormatter.time = data.time.getTime() / 1000;
427417
428418 loader.data = menuData;
429419 loader.sourceComponent = factory.load(menuData);
@@ -432,7 +422,7 @@ Item {
432422
433423 compare(loader.item.text, data.label, "Label does not match data");
434424 compare(loader.item.iconSource, data.icon, "Icon does not match data");
435− compare(loader.item.time, timeFormatter.timeString, "Time does not match data");
425+ compare(loader.item.time, i18n.relativeDateTime(data.time), "Time does not match data");
436426 compare(loader.item.eventColor, data.color, "Colour does not match data");
437427 compare(loader.item.enabled, data.enabled, "Enabled does not match data");
438428 }
tests/qmltests/Panel/Indicators/tst_MessageMenuItemFactory.qml+6−13
@@ -32,10 +32,6 @@ Item {
3232 menuIndex: 0
3333 }
3434
35− Utils.RelativeTimeFormatter {
36− id: timeFormatter
37− }
38−
3935 UT.UnityTestCase {
4036 name: "MessageMenuItemFactory"
4137 when: windowShown
@@ -82,17 +78,16 @@ Item {
8278 menuData.label = data.title;
8379 menuData.sensitive = data.enabled;
8480 menuData.ext = {
85− 'xCanonicalTime': data.time.getTime()*1000,
81+ 'xCanonicalTime': data.time.getTime()*1000000,
8682 'xCanonicalText': data.body,
8783 'icon': data.avatar,
8884 'xCanonicalAppIcon': data.icon,
8985 };
9086 factory.menuData = menuData;
91− timeFormatter.time = data.time.getTime()/1000;
9287
9388 tryCompare(factory.item, "objectName", "simpleTextMessage");
9489 compare(factory.item.title, data.title, "Title does not match data");
95− compare(factory.item.time, timeFormatter.timeString, "Time does not match data");
90+ compare(factory.item.time, i18n.relativeDateTime(data.time), "Time does not match data");
9691 compare(factory.item.body, data.body, "Message does not match data");
9792 compare(factory.item.avatar, data.avatar, "Avatar does not match data");
9893 compare(factory.item.icon, data.icon, "App icon does not match data");
@@ -111,7 +106,7 @@ Item {
111106 menuData.label = data.title;
112107 menuData.sensitive = data.enabled;
113108 menuData.ext = {
114− 'xCanonicalTime': data.time.getTime()*1000,
109+ 'xCanonicalTime': data.time.getTime()*1000000,
115110 'xCanonicalText': data.body,
116111 'icon': data.avatar,
117112 'xCanonicalAppIcon': data.icon,
@@ -123,11 +118,10 @@ Item {
123118 ]
124119 };
125120 factory.menuData = menuData;
126− timeFormatter.time = data.time.getTime()/1000;
127121
128122 tryCompare(factory.item, "objectName", "textMessage");
129123 compare(factory.item.title, data.title, "Title does not match data");
130− compare(factory.item.time, timeFormatter.timeString, "Time does not match data");
124+ compare(factory.item.time, i18n.relativeDateTime(data.time), "Time does not match data");
131125 compare(factory.item.body, data.body, "Message does not match data");
132126 compare(factory.item.avatar, data.avatar, "Avatar does not match data");
133127 compare(factory.item.icon, data.icon, "App icon does not match data");
@@ -147,7 +141,7 @@ Item {
147141 menuData.label = data.title;
148142 menuData.sensitive = data.enabled;
149143 menuData.ext = {
150− 'xCanonicalTime': data.time.getTime()*1000,
144+ 'xCanonicalTime': data.time.getTime()*1000000,
151145 'xCanonicalText': data.body,
152146 'icon': data.avatar,
153147 'xCanonicalAppIcon': data.icon,
@@ -162,11 +156,10 @@ Item {
162156 ]
163157 };
164158 factory.menuData = menuData;
165− timeFormatter.time = data.time.getTime()/1000;
166159
167160 tryCompare(factory.item, "objectName", "snapDecision");
168161 compare(factory.item.title, data.title, "Title does not match data");
169− compare(factory.item.time, timeFormatter.timeString, "Time does not match data");
162+ compare(factory.item.time, i18n.relativeDateTime(data.time), "Time does not match data");
170163 compare(factory.item.body, data.body, "Message does not match data");
171164 compare(factory.item.avatar, data.avatar, "Avatar does not match data");
172165 compare(factory.item.icon, data.icon, "App icon does not match data");