Merge lp:~nick-dedekind/ubuntu-ui-toolkit/lp1378821.time-translation into lp:ubuntu-ui-toolkit

Proposed by Nick Dedekind
Status: Superseded
Proposed branch: lp:~nick-dedekind/ubuntu-ui-toolkit/lp1378821.time-translation
Merge into: lp:ubuntu-ui-toolkit
Diff against target: 905 lines (+718/-24)
10 files modified
debian/changelog (+7/-0)
modules/Ubuntu/Components/plugin/plugin.cpp (+2/-2)
modules/Ubuntu/Components/plugin/plugin.pro (+5/-2)
modules/Ubuntu/Components/plugin/timeformatter.cpp (+199/-0)
modules/Ubuntu/Components/plugin/timeformatter.h (+61/-0)
modules/Ubuntu/Components/plugin/timeformatter_p.h (+177/-0)
po/ubuntu-ui-toolkit.pot (+133/-19)
tests/unit/tst_components/dateExt.js (+67/-0)
tests/unit/tst_components/tst_components.pro (+2/-1)
tests/unit/tst_components/tst_timeformatter.qml (+65/-0)
To merge this branch: bzr merge lp:~nick-dedekind/ubuntu-ui-toolkit/lp1378821.time-translation
Reviewer Review Type Date Requested Status
Cris Dywan Needs Fixing
Zoltan Balogh Needs Fixing
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+246191@code.launchpad.net

Commit message

Move the time formatter to SDK.

Description of the change

Move the time formatter to SDK.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

You need to update the .api file here.

Revision history for this message
Zoltan Balogh (bzoltan) wrote :

Please re-target the MR to the rtm or the staging branch.

review: Needs Fixing
Revision history for this message
Cris Dywan (kalikiana) wrote :

First and foremost, let's have an API proposal for this. Adding new API to the UITK means it will stay for a few years and if we just drop code like this we get in trouble (thumbnailer anyone?).

Second, we already have i18n for localization features. It seems to me like we'd want to extend that instead of a whole new component.

Third, how urgent is this? Who's using this aside from Unity? API should only be added to UITK if it's useful for several apps, otherwise there's little benefit and we still pay the cost of maintenance.

review: Needs Fixing
Revision history for this message
Albert Astals Cid (aacid) wrote :

Are you telling me you can't really see the use case for this in multiple apps? Phone? Calendar? Email?

Revision history for this message
Michał Sawicz (saviq) wrote :

FWIW, see the linked spec for use cases for this:

https://blueprints.launchpad.net/ubuntu-ui-toolkit/+spec/time-formatter

Revision history for this message
Cris Dywan (kalikiana) wrote :

Albert, when I asked in IRC I was told Unity was the only currently known use case. It's not about whether I can envision use cases but we need to know who will use the API so that we know if it actually solves the problem.

Thanks for the blueprint!
The point "Timestamps displayed differently depending on the available space" needs clarification. Is this explicitly to be done by the application or part of the formatter?

Please extend API proposal 1 https://docs.google.com/a/canonical.com/document/d/1qDcfbu9aAj7uU9qzjXCOJn8zGexBnXwZCgO8pLDsO5M/edit# to incorporate the relative time formatter. This makes more sense to Tim and I than an entierely new component which only has one feature. I imagine it could be as simple as i18n.relativeTime(timestamp) and i18n.absoluteTime(timestamp) - the unit test don't currently cover the latter but the spec lists it as a use case.
A short brainstorming meeting might be helpful, if you're interested we should arrange one in IRC.

1120. By Nick Dedekind

live timer

1121. By Nick Dedekind

fixed time translation

1122. By Nick Dedekind

updated potfile

1123. By Nick Dedekind

LiveTimer & i18n.relativeDateTime tests

1124. By Nick Dedekind

version bumped

1125. By Nick Dedekind

merged with trunk

1126. By Nick Dedekind

updated potfile

1127. By Nick Dedekind

removed old file

1128. By Nick Dedekind

version bump

1129. By Nick Dedekind

updated api

1130. By Nick Dedekind

reverted old changelogs

1131. By Nick Dedekind

better frequency handling

1132. By Nick Dedekind

whitespace

1133. By Nick Dedekind

unsubscribe live timer on destruction

Unmerged revisions

1133. By Nick Dedekind

unsubscribe live timer on destruction

1132. By Nick Dedekind

whitespace

1131. By Nick Dedekind

better frequency handling

1130. By Nick Dedekind

reverted old changelogs

1129. By Nick Dedekind

updated api

1128. By Nick Dedekind

version bump

1127. By Nick Dedekind

removed old file

1126. By Nick Dedekind

updated potfile

1125. By Nick Dedekind

merged with trunk

1124. By Nick Dedekind

version bumped

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2014-12-17 09:52:56 +0000
+++ debian/changelog 2015-01-12 17:27:26 +0000
@@ -348,6 +348,13 @@
348348
349 -- Zoltán Balogh <zoltan@bakter.hu> Fri, 10 Oct 2014 11:19:10 +0300349 -- Zoltán Balogh <zoltan@bakter.hu> Fri, 10 Oct 2014 11:19:10 +0300
350350
351ubuntu-ui-toolkit (1.1.1279.2-0ubuntu1) UNRELEASED; urgency=medium
352
353 [ Nick Dedekind ]
354 * Added time formatter
355
356 -- Nick Dedekind <nick.dedekind@canonical.com> Mon, 15 Dec 2014 09:57:12 +0000
357
351ubuntu-ui-toolkit (1.1.1279.1+14.10.20141014-0ubuntu1) 14.09; urgency=low358ubuntu-ui-toolkit (1.1.1279.1+14.10.20141014-0ubuntu1) 14.09; urgency=low
352359
353 [ Ubuntu daily release ]360 [ Ubuntu daily release ]
354361
=== modified file 'modules/Ubuntu/Components/plugin/plugin.cpp'
--- modules/Ubuntu/Components/plugin/plugin.cpp 2014-12-03 14:43:27 +0000
+++ modules/Ubuntu/Components/plugin/plugin.cpp 2015-01-12 17:27:26 +0000
@@ -35,6 +35,7 @@
35#include "inversemouseareatype.h"35#include "inversemouseareatype.h"
36#include "qquickclipboard.h"36#include "qquickclipboard.h"
37#include "qquickmimedata.h"37#include "qquickmimedata.h"
38#include "timeformatter.h"
38#include "ucubuntuanimation.h"39#include "ucubuntuanimation.h"
39#include "ucfontutils.h"40#include "ucfontutils.h"
40#include "ucarguments.h"41#include "ucarguments.h"
@@ -166,11 +167,10 @@
166 qmlRegisterType<QSortFilterProxyModelQML>(uri, 1, 1, "SortFilterModel");167 qmlRegisterType<QSortFilterProxyModelQML>(uri, 1, 1, "SortFilterModel");
167 qmlRegisterUncreatableType<FilterBehavior>(uri, 1, 1, "FilterBehavior", "Not instantiable");168 qmlRegisterUncreatableType<FilterBehavior>(uri, 1, 1, "FilterBehavior", "Not instantiable");
168 qmlRegisterUncreatableType<SortBehavior>(uri, 1, 1, "SortBehavior", "Not instantiable");169 qmlRegisterUncreatableType<SortBehavior>(uri, 1, 1, "SortBehavior", "Not instantiable");
169
170 // ListItem and related types, released to 1.2
171 qmlRegisterType<UCListItem, 2>(uri, 1, 2, "ListItem");170 qmlRegisterType<UCListItem, 2>(uri, 1, 2, "ListItem");
172 qmlRegisterType<UCListItemDivider>();171 qmlRegisterType<UCListItemDivider>();
173 qmlRegisterType<UCListItemActions, 2>(uri, 1, 2, "ListItemActions");172 qmlRegisterType<UCListItemActions, 2>(uri, 1, 2, "ListItemActions");
173 qmlRegisterType<TimeFormatter>(uri, 1, 1, "TimeFormatter");
174}174}
175175
176void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)176void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
177177
=== modified file 'modules/Ubuntu/Components/plugin/plugin.pro'
--- modules/Ubuntu/Components/plugin/plugin.pro 2014-12-03 14:43:27 +0000
+++ modules/Ubuntu/Components/plugin/plugin.pro 2015-01-12 17:27:26 +0000
@@ -72,7 +72,9 @@
72 uclistitemactions.h \72 uclistitemactions.h \
73 uclistitemactions_p.h \73 uclistitemactions_p.h \
74 propertychange_p.h \74 propertychange_p.h \
75 uclistitemstyle.h75 uclistitemstyle.h \
76 timeformatter.h \
77 timeformatter_p.h
7678
77SOURCES += plugin.cpp \79SOURCES += plugin.cpp \
78 uctheme.cpp \80 uctheme.cpp \
@@ -114,7 +116,8 @@
114 uclistitemactionsattached.cpp \116 uclistitemactionsattached.cpp \
115 uclistitemattached.cpp \117 uclistitemattached.cpp \
116 propertychange_p.cpp \118 propertychange_p.cpp \
117 uclistitemstyle.cpp119 uclistitemstyle.cpp \
120 timeformatter.cpp
118121
119# adapters122# adapters
120SOURCES += adapters/alarmsadapter_organizer.cpp123SOURCES += adapters/alarmsadapter_organizer.cpp
121124
=== added file 'modules/Ubuntu/Components/plugin/timeformatter.cpp'
--- modules/Ubuntu/Components/plugin/timeformatter.cpp 1970-01-01 00:00:00 +0000
+++ modules/Ubuntu/Components/plugin/timeformatter.cpp 2015-01-12 17:27:26 +0000
@@ -0,0 +1,199 @@
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#include "timeformatter.h"
18#include "timeformatter_p.h"
19
20TimeFormatterShared* TimeFormatterShared::s_timeformatter = NULL;
21
22TimeFormatterShared::TimeFormatterShared()
23{
24 QDBusConnection::systemBus().connect("org.freedesktop.timedate1",
25 "/org/freedesktop/timedate1",
26 "org.freedesktop.DBus.Properties",
27 "PropertiesChanged",
28 this,
29 SLOT(timedate1PropertiesChanged(QString, QVariantMap, QStringList)));
30}
31
32QString TimeFormatterPrivate::relativeTime(const QDateTime &datetime)
33{
34 QDateTime now = m_timeSource ? m_timeSource->property("time").toDateTime() : QDateTime::currentDateTime();
35 const date_proximity_t prox = getDateProximity(now, datetime);
36
37 switch (prox) {
38 case DATE_PROXIMITY_NOW:
39 m_proximityTimer.setInterval(1000);
40 if (!m_proximityTimer.isActive()) m_proximityTimer.start();
41
42 /* TRANSLATORS: Time based "this is happening/happened now" */
43 return UbuntuI18n::instance().tr("Now");
44
45 case DATE_PROXIMITY_HOUR:
46 {
47 m_proximityTimer.setInterval(1000);
48 if (!m_proximityTimer.isActive()) m_proximityTimer.start();
49
50 qint64 diff = datetime.toMSecsSinceEpoch() - now.toMSecsSinceEpoch();
51 qint64 minutes = qRound(float(diff) / 60000);
52 if (minutes < 0) {
53 if (minutes == -1) return UbuntuI18n::instance().tr("%1 minute ago").arg(qAbs(minutes));
54 return UbuntuI18n::instance().tr("%1 minutes ago").arg(qAbs(minutes));
55 }
56 if (minutes == 1) return UbuntuI18n::instance().tr("%1 minute").arg(qAbs(minutes));
57 return UbuntuI18n::instance().tr("%1 minutes").arg(qAbs(minutes));
58 }
59
60 case DATE_PROXIMITY_TODAY:
61 /* en_US example: "1:00 PM" */
62 m_proximityTimer.stop();
63 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
64 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
65 return datetime.toString(isLocale12h() ? UbuntuI18n::instance().tr("h:mm ap"):
66 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
67 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
68 UbuntuI18n::instance().tr("HH:mm"));
69
70 case DATE_PROXIMITY_YESTERDAY:
71 /* en_US example: "Yesterday 13:00" */
72 m_proximityTimer.stop();
73 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
74 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
75 return datetime.toString(isLocale12h() ? UbuntuI18n::instance().tr("'Yesterday\u2003'h:mm ap") :
76 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
77 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
78 UbuntuI18n::instance().tr("'Yesterday\u2003'HH:mm"));
79
80 case DATE_PROXIMITY_TOMORROW:
81 /* en_US example: "Tomorrow 1:00 PM" */
82 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
83 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
84 return datetime.toString(isLocale12h() ? UbuntuI18n::instance().tr("'Tomorrow\u2003'h:mm ap") :
85 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
86 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
87 UbuntuI18n::instance().tr("'Tomorrow\u2003'HH:mm"));
88
89 case DATE_PROXIMITY_LAST_WEEK:
90 case DATE_PROXIMITY_NEXT_WEEK:
91 /* en_US example: "Fri 1:00 PM" */
92 m_proximityTimer.stop();
93 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
94 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
95 return datetime.toString(isLocale12h() ? UbuntuI18n::instance().tr("ddd'\u2003'h:mm ap") :
96 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
97 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
98 UbuntuI18n::instance().tr("ddd'\u2003'HH:mm"));
99
100 case DATE_PROXIMITY_FAR:
101 default:
102 m_proximityTimer.stop();
103 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
104 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
105 return datetime.toString(isLocale12h() ? UbuntuI18n::instance().tr("ddd d MMM'\u2003'h:mm ap") :
106 /* TRANSLATORS: Please translated these to your locale datetime format using the format specified by
107 https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2 */
108 UbuntuI18n::instance().tr("ddd d MMM'\u2003'HH:mm"));
109 }
110 m_proximityTimer.stop();
111 return datetime.toString(Qt::DefaultLocaleShortDate);
112}
113
114TimeFormatter::TimeFormatter(QObject *parent)
115 : QObject(parent)
116 , d(new TimeFormatterPrivate)
117{
118 connect(TimeFormatterShared::s_timeformatter, &TimeFormatterShared::updated, this, &TimeFormatter::update);
119 connect(&d->m_proximityTimer, &QTimer::timeout, this, &TimeFormatter::update);
120}
121
122TimeFormatter::~TimeFormatter()
123{
124}
125
126QString TimeFormatter::format() const
127{
128 return d->m_format;
129}
130
131QString TimeFormatter::timeString() const
132{
133 return d->m_timeString;
134}
135
136qint64 TimeFormatter::millisecondsSinceEpoc() const
137{
138 return d->m_millisecondsSinceEpoc;
139}
140
141bool TimeFormatter::relative() const
142{
143 return d->m_relative;
144}
145
146QObject* TimeFormatter::timeSource() const
147{
148 return d->m_timeSource;
149}
150
151void TimeFormatter::setFormat(const QString &format)
152{
153 if (d->m_format != format) {
154 d->m_format = format;
155 Q_EMIT formatChanged(d->m_format);
156 update();
157 }
158}
159
160void TimeFormatter::setMilliSeccondsSinceEpoc(qint64 millisecondsSinceEpoc)
161{
162 if (d->m_millisecondsSinceEpoc != millisecondsSinceEpoc) {
163 d->m_millisecondsSinceEpoc = millisecondsSinceEpoc;
164 Q_EMIT millisecondsSinceEpocChanged(d->m_millisecondsSinceEpoc);
165 update();
166 }
167}
168
169void TimeFormatter::setRelative(bool relative)
170{
171 if (d->m_relative != relative) {
172 if (!relative) d->m_proximityTimer.stop();
173 d->m_relative = relative;
174 Q_EMIT relativeChanged(d->m_relative);
175 update();
176 }
177}
178
179void TimeFormatter::setTimeSource(QObject* timeSource)
180{
181 if (timeSource != d->m_timeSource) {
182 d->m_timeSource = timeSource;
183 Q_EMIT timeSourceChanged(d->m_timeSource);
184 update();
185 }
186}
187
188void TimeFormatter::update()
189{
190 if (format().isEmpty() && !d->m_relative) return;
191
192 QDateTime datetime(QDateTime::fromMSecsSinceEpoch(millisecondsSinceEpoc()));
193 QString timeString = d->m_relative ? d->relativeTime(datetime) : datetime.toString(format());
194
195 if (d->m_timeString != timeString) {
196 d->m_timeString = timeString;
197 Q_EMIT timeStringChanged(d->m_timeString);
198 }
199}
0200
=== added file 'modules/Ubuntu/Components/plugin/timeformatter.h'
--- modules/Ubuntu/Components/plugin/timeformatter.h 1970-01-01 00:00:00 +0000
+++ modules/Ubuntu/Components/plugin/timeformatter.h 2015-01-12 17:27:26 +0000
@@ -0,0 +1,61 @@
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#ifndef TIME_FORMATTER_H
18#define TIME_FORMATTER_H
19
20#include <QObject>
21
22// TODO - bug #1260728
23class TimeFormatter : public QObject
24{
25 Q_OBJECT
26 Q_PROPERTY(QString format READ format WRITE setFormat NOTIFY formatChanged)
27 Q_PROPERTY(QString timeString READ timeString NOTIFY timeStringChanged)
28 Q_PROPERTY(qint64 millisecondsSinceEpoc READ millisecondsSinceEpoc WRITE setMilliSeccondsSinceEpoc NOTIFY millisecondsSinceEpocChanged)
29 Q_PROPERTY(bool relative READ relative WRITE setRelative NOTIFY relativeChanged)
30
31 /* for testing */
32 Q_PROPERTY(QObject* timeSource READ timeSource WRITE setTimeSource NOTIFY timeSourceChanged)
33public:
34 TimeFormatter(QObject *parent = 0);
35 virtual ~TimeFormatter();
36
37 virtual QString format() const;
38 QString timeString() const;
39 qint64 millisecondsSinceEpoc() const;
40 bool relative() const;
41 QObject* timeSource() const;
42
43 void setFormat(const QString &format);
44 void setMilliSeccondsSinceEpoc(qint64 millisecondsSinceEpoc);
45 void setRelative(bool relative);
46 void setTimeSource(QObject* timeSource);
47
48 void update();
49
50Q_SIGNALS:
51 void formatChanged(const QString &format);
52 void timeStringChanged(const QString &timeString);
53 void millisecondsSinceEpocChanged(qint64 millisecondsSinceEpoc);
54 void relativeChanged(bool relative);
55 void timeSourceChanged(QObject* timeSource);
56
57private:
58 class TimeFormatterPrivate *d;
59};
60
61#endif
062
=== added file 'modules/Ubuntu/Components/plugin/timeformatter_p.h'
--- modules/Ubuntu/Components/plugin/timeformatter_p.h 1970-01-01 00:00:00 +0000
+++ modules/Ubuntu/Components/plugin/timeformatter_p.h 2015-01-12 17:27:26 +0000
@@ -0,0 +1,177 @@
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#ifndef TIMEFORMATTER_P_H
18#define TIMEFORMATTER_P_H
19
20#include "i18n.h"
21
22#include <QDateTime>
23#include <QDBusConnection>
24#include <QLocale>
25#include <QObject>
26#include <QTimer>
27
28/* Check the system locale setting to see if the format is 24-hour
29 time or 12-hour time */
30inline bool isLocale12h(void)
31{
32 QString strTimeFormat = QLocale::system().timeFormat();
33 QStringList includes; includes << "AP"; includes << "ap";
34 QStringList excludes; excludes << "H"; excludes << "HH";
35
36 Q_FOREACH(const QString& exclude, excludes) {
37 if (strTimeFormat.contains(exclude)) {
38 return false;
39 }
40 }
41
42 Q_FOREACH(const QString& include, includes) {
43 if (strTimeFormat.contains(include)) {
44 return true;
45 }
46 }
47
48 return false;
49}
50
51typedef enum
52{
53 DATE_PROXIMITY_NOW,
54 DATE_PROXIMITY_HOUR,
55 DATE_PROXIMITY_TODAY,
56 DATE_PROXIMITY_YESTERDAY,
57 DATE_PROXIMITY_TOMORROW,
58 DATE_PROXIMITY_LAST_WEEK,
59 DATE_PROXIMITY_NEXT_WEEK,
60 DATE_PROXIMITY_FAR
61} date_proximity_t;
62
63inline date_proximity_t getDateProximity(const QDateTime& now, const QDateTime& time)
64{
65 int now_day = now.date().day();
66 int now_month = now.date().month();
67 int now_year = now.date().year();
68
69 int time_day = time.date().day();
70 int time_month = time.date().month();
71 int time_year = time.date().year();
72
73 qint64 diff = time.toMSecsSinceEpoch() - now.toMSecsSinceEpoch();
74 if (qAbs(diff) < 30000) return DATE_PROXIMITY_NOW;
75 else if (qAbs(diff) < 3600000) return DATE_PROXIMITY_HOUR;
76
77 // does it happen today?
78 if ((now_year == time_year) && (now_month == time_month) && (now_day == time_day)) {
79 return DATE_PROXIMITY_TODAY;
80 }
81
82 // did it happen yesterday?
83 QDateTime yesterday(now.addDays(-1));
84 int yesterday_day = yesterday.date().day();
85 int yesterday_month = yesterday.date().month();
86 int yesterday_year = yesterday.date().year();
87 if ((yesterday_year == time_year) && (yesterday_month == time_month) && (yesterday_day == time_day)) {
88 return DATE_PROXIMITY_YESTERDAY;
89 }
90
91 // does it happen tomorrow?
92 QDateTime tomorrow(now.addDays(1));
93 int tomorrow_day = tomorrow.date().day();
94 int tomorrow_month = tomorrow.date().month();
95 int tomorrow_year = tomorrow.date().year();
96 if ((tomorrow_year == time_year) && (tomorrow_month == time_month) && (tomorrow_day == time_day)) {
97 return DATE_PROXIMITY_TOMORROW;
98 }
99
100 if (time < now) {
101 QDateTime lastWeek(now.addDays(-6));
102 QDateTime lastWeekBound(lastWeek.date(), QTime(0, 0, 0, 0));
103
104 // does it happen last week?
105 if (time >= lastWeekBound) {
106 return DATE_PROXIMITY_LAST_WEEK;
107 }
108 } else {
109
110 QDateTime nextWeek(now.addDays(6));
111 QDateTime nextWeekBound(nextWeek.date(), QTime(23, 59, 59, 999));
112
113 // does it happen this week?
114 if (time <= nextWeekBound) {
115 return DATE_PROXIMITY_NEXT_WEEK;
116 }
117 }
118
119 return DATE_PROXIMITY_FAR;
120}
121
122class TimeFormatterShared : public QObject
123{
124 Q_OBJECT
125public:
126 TimeFormatterShared();
127
128 ~TimeFormatterShared()
129 {
130 s_timeformatter = NULL;
131 }
132
133public Q_SLOTS:
134 void timedate1PropertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList&)
135 {
136 if (interface != "org.freedesktop.timedate1") return;
137 if (changed.contains("Timezone")) {
138 Q_EMIT updated();
139 }
140 }
141
142Q_SIGNALS:
143 void updated();
144
145public:
146 static TimeFormatterShared* s_timeformatter;
147};
148
149class TimeFormatterPrivate
150{
151public:
152 TimeFormatterPrivate()
153 : m_format(QLocale::system().dateTimeFormat())
154 , m_millisecondsSinceEpoc(0)
155 , m_relative(false)
156 , m_timeSource(NULL)
157 {
158 if (!TimeFormatterShared::s_timeformatter) { TimeFormatterShared::s_timeformatter = new TimeFormatterShared(); }
159 m_shared.reset(TimeFormatterShared::s_timeformatter);
160
161 m_proximityTimer.setSingleShot(false);
162 }
163
164 QString relativeTime(const QDateTime &datetime);
165
166 QString m_format;
167 QString m_timeString;
168 qint64 m_millisecondsSinceEpoc;
169 bool m_relative;
170 date_proximity_t m_lastProximity;
171 QObject* m_timeSource;
172 QTimer m_proximityTimer;
173
174 QSharedPointer<TimeFormatterShared> m_shared;
175};
176
177#endif // TIMEFORMATTER_P_H
0178
=== modified file 'po/ubuntu-ui-toolkit.pot'
--- po/ubuntu-ui-toolkit.pot 2014-11-06 15:50:17 +0000
+++ po/ubuntu-ui-toolkit.pot 2015-01-12 17:27:26 +0000
@@ -8,19 +8,28 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: ubuntu-ui-toolkit\n"9"Project-Id-Version: ubuntu-ui-toolkit\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2014-11-05 14:29+0100\n"11"POT-Creation-Date: 2014-12-17 16:18+0000\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
15"Language: \n"15"Language: \n"
16"MIME-Version: 1.0\n"16"MIME-Version: 1.0\n"
17"Content-Type: text/plain; charset=CHARSET\n"17"Content-Type: text/plain; charset=UTF-8\n"
18"Content-Transfer-Encoding: 8bit\n"18"Content-Transfer-Encoding: 8bit\n"
1919
20#: Ubuntu/Components/ListItems/Empty.qml:41320#: Ubuntu/Components/ListItems/Empty.qml:397
21msgid "Delete"21msgid "Delete"
22msgstr ""22msgstr ""
2323
24#: Ubuntu/Components/plugin/adapters/dbuspropertywatcher_p.cpp:51
25msgid "No service/path specified"
26msgstr ""
27
28#: Ubuntu/Components/plugin/adapters/dbuspropertywatcher_p.cpp:69
29#, qt-format
30msgid "Invalid bus type: %1."
31msgstr ""
32
24#: Ubuntu/Components/plugin/statesaverbackend_p.cpp:17633#: Ubuntu/Components/plugin/statesaverbackend_p.cpp:176
25#, qt-format34#, qt-format
26msgid ""35msgid ""
@@ -33,13 +42,98 @@
33msgid "property \"%1\" does not exist or is not writable for object %2"42msgid "property \"%1\" does not exist or is not writable for object %2"
34msgstr ""43msgstr ""
3544
36#: Ubuntu/Components/plugin/ucalarm.cpp:4245#. TRANSLATORS: Time based "this is happening/happened now"
37#: Ubuntu/Components/plugin/ucalarm.cpp:13646#: Ubuntu/Components/plugin/timeformatter.cpp:43
47msgid "Now"
48msgstr ""
49
50#: Ubuntu/Components/plugin/timeformatter.cpp:53
51#, qt-format
52msgid "%1 minute ago"
53msgstr ""
54
55#: Ubuntu/Components/plugin/timeformatter.cpp:54
56#, qt-format
57msgid "%1 minutes ago"
58msgstr ""
59
60#: Ubuntu/Components/plugin/timeformatter.cpp:56
61#, qt-format
62msgid "%1 minute"
63msgstr ""
64
65#: Ubuntu/Components/plugin/timeformatter.cpp:57
66#, qt-format
67msgid "%1 minutes"
68msgstr ""
69
70#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
71#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
72#: Ubuntu/Components/plugin/timeformatter.cpp:65
73msgid "h:mm ap"
74msgstr ""
75
76#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
77#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
78#: Ubuntu/Components/plugin/timeformatter.cpp:68
79msgid "HH:mm"
80msgstr ""
81
82#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
83#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
84#: Ubuntu/Components/plugin/timeformatter.cpp:75
85msgid "'Yesterday 'h:mm ap"
86msgstr ""
87
88#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
89#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
90#: Ubuntu/Components/plugin/timeformatter.cpp:78
91msgid "'Yesterday 'HH:mm"
92msgstr ""
93
94#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
95#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
96#: Ubuntu/Components/plugin/timeformatter.cpp:84
97msgid "'Tomorrow 'h:mm ap"
98msgstr ""
99
100#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
101#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
102#: Ubuntu/Components/plugin/timeformatter.cpp:87
103msgid "'Tomorrow 'HH:mm"
104msgstr ""
105
106#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
107#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
108#: Ubuntu/Components/plugin/timeformatter.cpp:95
109msgid "ddd' 'h:mm ap"
110msgstr ""
111
112#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
113#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
114#: Ubuntu/Components/plugin/timeformatter.cpp:98
115msgid "ddd' 'HH:mm"
116msgstr ""
117
118#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
119#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
120#: Ubuntu/Components/plugin/timeformatter.cpp:105
121msgid "ddd d MMM' 'h:mm ap"
122msgstr ""
123
124#. TRANSLATORS: Please translated these to your locale datetime format using the format specified by
125#. https://qt-project.org/doc/qt-5-snapshot/qdatetime.html#fromString-2
126#: Ubuntu/Components/plugin/timeformatter.cpp:108
127msgid "ddd d MMM' 'HH:mm"
128msgstr ""
129
130#: Ubuntu/Components/plugin/ucalarm.cpp:41
131#: Ubuntu/Components/plugin/ucalarm.cpp:641
38msgid "Alarm"132msgid "Alarm"
39msgstr ""133msgstr ""
40134
41#: Ubuntu/Components/plugin/ucalarm.cpp:684135#: Ubuntu/Components/plugin/ucalarm.cpp:633
42#: Ubuntu/Components/plugin/ucalarm.cpp:716136#: Ubuntu/Components/plugin/ucalarm.cpp:665
43msgid "Alarm has a pending operation."137msgid "Alarm has a pending operation."
44msgstr ""138msgstr ""
45139
@@ -66,10 +160,29 @@
66msgid "%1 is expecting additional arguments: %2"160msgid "%1 is expecting additional arguments: %2"
67msgstr ""161msgstr ""
68162
69#: Ubuntu/Components/plugin/ucmousefilters.cpp:1064163#: Ubuntu/Components/plugin/uclistitemactions.cpp:155
164msgid "actionsDelegate not set!"
165msgstr ""
166
167#: Ubuntu/Components/plugin/uclistitem.cpp:1040
168#: Ubuntu/Components/plugin/uclistitem.cpp:1074
169msgid "leadingActions and trailingActions cannot share the same object!"
170msgstr ""
171
172#: Ubuntu/Components/plugin/ucmousefilters.cpp:1065
70msgid "Ignoring AfterItem priority for InverseMouse filters."173msgid "Ignoring AfterItem priority for InverseMouse filters."
71msgstr ""174msgstr ""
72175
176#: Ubuntu/Components/plugin/ucserviceproperties.cpp:62
177msgid "Changing connection parameters forbidden."
178msgstr ""
179
180#: Ubuntu/Components/plugin/ucserviceproperties.cpp:145
181#, qt-format
182msgid ""
183"Binding detected on property '%1' will be removed by the service updates."
184msgstr ""
185
73#: Ubuntu/Components/plugin/ucstatesaver.cpp:46186#: Ubuntu/Components/plugin/ucstatesaver.cpp:46
74msgid "Warning: attachee must have an ID. State will not be saved."187msgid "Warning: attachee must have an ID. State will not be saved."
75msgstr ""188msgstr ""
@@ -87,23 +200,24 @@
87"State saving disabled for %1, class %2"200"State saving disabled for %1, class %2"
88msgstr ""201msgstr ""
89202
90#: Ubuntu/Components/plugin/uctheme.cpp:233203#: Ubuntu/Components/plugin/uctheme.cpp:240
91msgid "Theme not found: "204#, qt-format
205msgid "Theme not found: \"%1\""
92msgstr ""206msgstr ""
93207
94#: Ubuntu/Components/Popups/ComposerSheet.qml:80208#: Ubuntu/Components/Popups/ComposerSheet.qml:78
95msgid "Cancel"209msgid "Cancel"
96msgstr ""210msgstr ""
97211
98#: Ubuntu/Components/Popups/ComposerSheet.qml:90212#: Ubuntu/Components/Popups/ComposerSheet.qml:88
99msgid "Confirm"213msgid "Confirm"
100msgstr ""214msgstr ""
101215
102#: Ubuntu/Components/Popups/DefaultSheet.qml:89216#: Ubuntu/Components/Popups/DefaultSheet.qml:85
103msgid "Close"217msgid "Close"
104msgstr ""218msgstr ""
105219
106#: Ubuntu/Components/Popups/DefaultSheet.qml:99220#: Ubuntu/Components/Popups/DefaultSheet.qml:95
107msgid "Done"221msgid "Done"
108msgstr ""222msgstr ""
109223
@@ -111,19 +225,19 @@
111msgid "Select All"225msgid "Select All"
112msgstr ""226msgstr ""
113227
114#: Ubuntu/Components/TextInputPopover.qml:33228#: Ubuntu/Components/TextInputPopover.qml:34
115msgid "Cut"229msgid "Cut"
116msgstr ""230msgstr ""
117231
118#: Ubuntu/Components/TextInputPopover.qml:42232#: Ubuntu/Components/TextInputPopover.qml:46
119msgid "Copy"233msgid "Copy"
120msgstr ""234msgstr ""
121235
122#: Ubuntu/Components/TextInputPopover.qml:49236#: Ubuntu/Components/TextInputPopover.qml:56
123msgid "Paste"237msgid "Paste"
124msgstr ""238msgstr ""
125239
126#: Ubuntu/Components/Themes/Ambiance/ProgressBarStyle.qml:57240#: Ubuntu/Components/Themes/Ambiance/ProgressBarStyle.qml:62
127msgid "In Progress"241msgid "In Progress"
128msgstr ""242msgstr ""
129243
@@ -135,6 +249,6 @@
135msgid "Pull to refresh..."249msgid "Pull to refresh..."
136msgstr ""250msgstr ""
137251
138#: Ubuntu/Components/ToolbarItems.qml:142252#: Ubuntu/Components/ToolbarItems.qml:145
139msgid "Back"253msgid "Back"
140msgstr ""254msgstr ""
141255
=== added file 'tests/unit/tst_components/dateExt.js'
--- tests/unit/tst_components/dateExt.js 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_components/dateExt.js 2015-01-12 17:27:26 +0000
@@ -0,0 +1,67 @@
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 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
17.pragma library
18
19Date.msPerMinute = 60e3
20Date.msPerHour = 3600e3
21Date.msPerDay = 86400e3
22Date.msPerWeek = Date.msPerDay * 7
23
24Date.leapYear = function(year) {
25 return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
26}
27
28Date.prototype.addMinutes = function(minutes) {
29 var date = new Date(this)
30 date.setTime(date.getTime() + Date.msPerMinute * minutes)
31 return date
32}
33
34Date.prototype.addHours = function(hours) {
35 var date = new Date(this)
36 date.setTime(date.getTime() + Date.msPerHour * hours)
37 return date
38}
39
40Date.prototype.addDays = function(days) {
41 var date = new Date(this)
42 date.setTime(date.getTime() + Date.msPerDay * days)
43 return date
44}
45
46Date.prototype.addMonths = function(months) {
47 var date = new Date(this)
48 date.setMonth(date.getMonth() + months)
49 return date
50}
51
52Date.prototype.weekStart = function(weekStartDay) {
53 var date = this.midnight()
54 var day = date.getDay(), n = 0
55 while (day != weekStartDay) {
56 if (day == 0) day = 6
57 else day = day - 1
58 n = n + 1
59 }
60 return date.addDays(-n)
61}
62
63Date.prototype.midday = function() {
64 var date = new Date(this)
65 date.setHours(12,0,0,0);
66 return date
67}
068
=== modified file 'tests/unit/tst_components/tst_components.pro'
--- tests/unit/tst_components/tst_components.pro 2012-12-04 08:11:38 +0000
+++ tests/unit/tst_components/tst_components.pro 2015-01-12 17:27:26 +0000
@@ -6,4 +6,5 @@
66
7SOURCES += tst_components.cpp7SOURCES += tst_components.cpp
88
9OTHER_FILES += $$system(ls *.qml)9OTHER_FILES += $$system(ls *.qml) \
10 dateExt.js
1011
=== added file 'tests/unit/tst_components/tst_timeformatter.qml'
--- tests/unit/tst_components/tst_timeformatter.qml 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_components/tst_timeformatter.qml 2015-01-12 17:27:26 +0000
@@ -0,0 +1,65 @@
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 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
17import QtQuick 2.0
18import QtTest 1.0
19import Ubuntu.Components 1.1
20import "dateExt.js" as DateExt
21
22TestCase {
23 name: "TimeFormatter"
24
25 function init() {
26 timeFormatter.relative = false;
27 }
28
29 property date testTime: (new Date(2014, 10, 27, 14, 48, 0, 0))
30
31 function test_relative_data() {
32 return [
33 { tag: "now", datetime: testTime, expected: "Now" },
34 { tag: "last minute", datetime: testTime.addMinutes(-1), expected: "1 minute ago" },
35 { tag: "next minute", datetime: testTime.addMinutes(1), expected: "1 minute" },
36 { tag: "last hour", datetime: testTime.addMinutes(-50), expected: "50 minutes ago" },
37 { tag: "next hour", datetime: testTime.addMinutes(50), expected: "50 minutes" },
38 { tag: "today-before", datetime: testTime.addHours(-4), expected: "10:48" },
39 { tag: "today-after", datetime: testTime.addHours(4), expected: "18:48" },
40 { tag: "yesterday", datetime: testTime.addDays(-1), expected: "Yesterday\u200314:48" },
41 { tag: "tomorrow", datetime: testTime.addDays(1), expected: "Tomorrow\u200314:48" },
42 { tag: "last-week", datetime: testTime.addDays(-6), expected: "Fri\u200314:48" },
43 { tag: "next-week", datetime: testTime.addDays(6), expected: "Wed\u200314:48" },
44 { tag: "far-past", datetime: testTime.addDays(-7), expected: "Thu 20 Nov\u200314:48" },
45 { tag: "far-future", datetime: testTime.addDays(7), expected: "Thu 4 Dec\u200314:48" }
46 ];
47 }
48
49 function test_relative(data) {
50 timeFormatter.relative = true;
51 timeFormatter.millisecondsSinceEpoc = data.datetime.getTime();
52
53 if (data.expected !== undefined) {
54 compare(timeFormatter.timeString, data.expected);
55 }
56 }
57
58 TimeFormatter {
59 id: timeFormatter
60
61 timeSource: QtObject {
62 property date time: testTime
63 }
64 }
65}

Subscribers

People subscribed via source and target branches

to status/vote changes: