Merge lp:~nick-dedekind/unity8/indicator-polishing into lp:unity8

Proposed by Nick Dedekind
Status: Merged
Approved by: Andrea Cimitan
Approved revision: 1106
Merged at revision: 1296
Proposed branch: lp:~nick-dedekind/unity8/indicator-polishing
Merge into: lp:unity8
Diff against target: 2632 lines (+1031/-735)
28 files modified
debian/control (+2/-2)
plugins/Unity/Indicators/CMakeLists.txt (+0/-9)
plugins/Unity/Indicators/plugin.cpp (+0/-2)
plugins/Unity/Indicators/resources/artwork/messaging/default_app.svg (+0/-42)
plugins/Unity/Indicators/resources/indicators.qrc (+0/-6)
plugins/Utils/CMakeLists.txt (+1/-0)
plugins/Utils/plugin.cpp (+2/-0)
plugins/Utils/relativetimeformatter.cpp (+268/-0)
plugins/Utils/relativetimeformatter.h (+34/-0)
plugins/Utils/timeformatter.cpp (+6/-1)
plugins/Utils/timeformatter.h (+3/-1)
po/unity8.pot (+29/-25)
qml/Components/Header.qml (+27/-0)
qml/Panel/Indicators.qml (+2/-13)
qml/Panel/Indicators/DefaultIndicatorPage.qml (+8/-49)
qml/Panel/Indicators/IndicatorDelegate.qml (+2/-10)
qml/Panel/Indicators/MenuItemFactory.qml (+163/-52)
qml/Panel/Indicators/MessageMenuItemFactory.qml (+166/-181)
qml/Panel/Indicators/RemoveBackground.qml (+0/-55)
qml/Panel/Indicators/client/IndicatorsClient.qml (+4/-0)
qml/Panel/MenuContent.qml (+102/-126)
tests/mocks/Unity/Indicators/FakeMenuPage.qml (+0/-10)
tests/plugins/Utils/CMakeLists.txt (+2/-2)
tests/plugins/Utils/timeformattertest.cpp (+104/-7)
tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml (+32/-16)
tests/qmltests/Panel/Indicators/tst_MessageMenuItemFactory.qml (+43/-53)
tests/qmltests/Panel/tst_Indicators.qml (+10/-10)
tests/qmltests/Panel/tst_MenuContent.qml (+21/-63)
To merge this branch: bzr merge lp:~nick-dedekind/unity8/indicator-polishing
Reviewer Review Type Date Requested Status
Andrea Cimitan (community) Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Michał Sawicz Abstain
Albert Astals Cid (community) Abstain
Review via email: mp+228700@code.launchpad.net

Commit message

Visual changes for indicator RTM polishing

Description of the change

Visual changes for indicator RTM polishing sprint

https://docs.google.com/a/canonical.com/document/d/1KC40suUs13gajIlE1Ms6PJYoIPx_AjlF4ae6bvtNjNc/edit

 * Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~nick-dedekind/ubuntu-settings-components/indicator-polishing/+merge/229083

 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes

 * Did you make sure that your branch does not contain spurious tags?
Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
Yes

 * If you changed the UI, has there been a design review?
Yes

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
Albert Astals Cid (aacid) wrote :

Text conflict in qml/Panel/Indicators.qml
1 conflicts encountered.

review: Needs Fixing
1079. By Nick Dedekind

added copywrite

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in qml/Panel/Indicators/DefaultIndicatorPage.qml
1 conflicts encountered.

review: Needs Fixing
1080. By Nick Dedekind

Added default Header Components. Used in indicators.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in qml/Panel/Indicators/DefaultIndicatorPage.qml
1 conflicts encountered.

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

Add i18n.tr to the "Clear" button in RemoveBackground.qml please.

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

Please delete tag 7.85+14.10.20140428.2-0ubuntu1 in this branch and any local checkouts you might have.

Also:
 Text conflict in qml/Panel/Indicators/DefaultIndicatorPage.qml

review: Needs Fixing
1081. By Nick Dedekind

merged with trunk

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> Please delete tag 7.85+14.10.20140428.2-0ubuntu1 in this branch and any local
> checkouts you might have.
>
> Also:
> Text conflict in qml/Panel/Indicators/DefaultIndicatorPage.qml

Done.

1082. By Nick Dedekind

removed RemoveBackground

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> Add i18n.tr to the "Clear" button in RemoveBackground.qml please.

No longer used.
Removed.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in debian/control
1 conflicts encountered.

review: Needs Fixing
1083. By Nick Dedekind

rebased

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Merges fine

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

relativetimeformatter.cpp looks like copied from somewhere else :/

The pot needs updating

Also the comments for translators in relativetimeformatter.cpp don't make it to the .po file.

Since it seems relativetimeformatter.cpp is copied from indicator-datetime, maybe we want to use dgettext instead of gettext? This way we don't need to update the .pot and we get exactly the same translation as indicator-datetime has. (As long as the copied code is in sync)

Maybe you want to add a // TODO make sure we keep this in sync with indicator-datetime code?

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

> Since it seems relativetimeformatter.cpp is copied from indicator-datetime,
> maybe we want to use dgettext instead of gettext? This way we don't need to
> update the .pot and we get exactly the same translation as indicator-datetime
> has. (As long as the copied code is in sync)
>
> Maybe you want to add a // TODO make sure we keep this in sync with indicator-
> datetime code?

Yeah agreed we should just use indicator's domain here. And then there's:
https://blueprints.launchpad.net/ubuntu-ui-toolkit/+spec/time-formatter

But obviously dead for over half a year now.

1084. By Nick Dedekind

merged with trunk

1085. By Nick Dedekind

Fixed up relative time formatting & tests

1086. By Nick Dedekind

updated pot

1087. By Nick Dedekind

fixed/added comment

1088. By Nick Dedekind

fixed/added comment

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> relativetimeformatter.cpp looks like copied from somewhere else :/

Yeah, from indicator-datetime.
Shouldn't really be there anyway. We should get the raw time and format it how we want in the shell. These time components should probably be in the sdk.

>
> The pot needs updating

Done.

>
> Also the comments for translators in relativetimeformatter.cpp don't make it
> to the .po file.

No idea how to do this.

>
> Since it seems relativetimeformatter.cpp is copied from indicator-datetime,
> maybe we want to use dgettext instead of gettext? This way we don't need to
> update the .pot and we get exactly the same translation as indicator-datetime
> has. (As long as the copied code is in sync)

Done.

>
> Maybe you want to add a // TODO make sure we keep this in sync with indicator-
> datetime code?

Done.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Something is weird, if we're using dgettext("indicator-datetime", ); we should not have the messages in our .pot file since the whole intent of that is to reuse the translations in indicator-datetime and not make our translators do the work twice (with the potential for mismatches).

Seems that the way to trick gettexxt into not extracting those strings is adding an intermediate function? http://stackoverflow.com/questions/3341829/can-xgettext-be-used-to-extract-specific-domain-strings-only/5354360#5354360

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

I've been told to abstain

review: Abstain
1089. By Nick Dedekind

use dgettext

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) :
review: Abstain
Revision history for this message
Andrea Cimitan (cimi) wrote :

I see some delay in the notification center...
you receive a message, open the notification center immediately -> empty -> 1 second wait -> message appears.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> I see some delay in the notification center...
> you receive a message, open the notification center immediately -> empty -> 1
> second wait -> message appears.

That's because the model takes a bit of time to connect and populate. It's always been like that as far as I know.

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> > I see some delay in the notification center...
> > you receive a message, open the notification center immediately -> empty ->
> 1
> > second wait -> message appears.
>
> That's because the model takes a bit of time to connect and populate. It's
> always been like that as far as I know.

Actually, it's because the model is now asynchronous.
We stop registering for changes to the indicators after a while of them being closed, and when we re-open, all the menus get added. And since they're now async, the model takes it's time...

1090. By Nick Dedekind

Simplified MessageMenuItemFactory

1091. By Nick Dedekind

updated for changes to ListItem.Empty

1092. By Nick Dedekind

removed content activator

1093. By Nick Dedekind

test fixes for removal of content activator

1094. By Nick Dedekind

confirm removal for message items

1095. By Nick Dedekind

tweak delegate caching

1096. By Nick Dedekind

added fix for current indicator item

1097. By Nick Dedekind

removed USC.IconVisual

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

I've changed it so that the indicators are always in sync. But there are only x number of delegates loaded at a time. This should restrict the indicators memory consumption if the notifications/transfers get "out of hand".

1098. By Nick Dedekind

fixed test for dd day in LC_ALL=C

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Omer Akram (om26er) wrote :

Can you merge trunk, perhaps ?

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> Can you merge trunk, perhaps ?

It's failing due to dependence o a pre-requisite branch.

Revision history for this message
kevin gunn (kgunn72) wrote :

what's the pre-req ?

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

@Kevin: It's listed in the description

Revision history for this message
Andrea Cimitan (cimi) wrote :

More to come (changing computer)

Revision history for this message
Andrea Cimitan (cimi) wrote :

Shall we update pot files again?

More maybe to come tomorrow, comments in diff

Also, shall we put the highlightWhenPressed: false as default at this point? (is everywhere)

I have to dig into the clip: true we have on some listViews, not sure they are always required

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

Text conflict in po/unity8.pot
Text conflict in tests/plugins/Utils/CMakeLists.txt
2 conflicts encountered.

1099. By Nick Dedekind

merged with trunk

1100. By Nick Dedekind

more review comments

1101. By Nick Dedekind

merged with trunk

1102. By Nick Dedekind

update pot

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

Fixed all review coments

> Shall we update pot files again?

Done

>
> More maybe to come tomorrow, comments in diff
>
> Also, shall we put the highlightWhenPressed: false as default at this point?
> (is everywhere)

It's from SDK, dont want to default in USC because it's used by settings now so may break.

>
> I have to dig into the clip: true we have on some listViews, not sure they are
> always required

We have to clip the indicators. Tablet mode requires it since it's in the sidebar.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1103. By Nick Dedekind

merged with LC_ALL fix

1104. By Nick Dedekind

LC_ALL=C.UTF-8 again

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1105. By Nick Dedekind

fixed up defaults for media player menu

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1106. By Nick Dedekind

MediaPlayerMenu.running -> showTrack

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Andrea Cimitan (cimi) wrote :

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
 * Did CI run pass? If not, please explain why.
No, but silo did

review: Approve
1107. By Nick Dedekind

merged with trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2014-09-18 19:33:04 +0000
3+++ debian/control 2014-09-25 12:44:25 +0000
4@@ -44,7 +44,7 @@
5 qtdeclarative5-dev-tools,
6 qtdeclarative5-private-dev (>= 5.2.1),
7 qtdeclarative5-qtmultimedia-plugin,
8- qtdeclarative5-ubuntu-settings-components (>= 0.3),
9+ qtdeclarative5-ubuntu-settings-components (>= 0.4),
10 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 0.1.49) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 0.1.49),
11 ttf-ubuntu-font-family,
12 Standards-Version: 3.9.4
13@@ -107,7 +107,7 @@
14 Package: unity8-common
15 Architecture: all
16 Depends: qml-module-qtquick-layouts,
17- qtdeclarative5-ubuntu-settings-components (>= 0.3),
18+ qtdeclarative5-ubuntu-settings-components (>= 0.4),
19 qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
20 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 0.1.49) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 0.1.49),
21 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
22
23=== modified file 'plugins/Unity/Indicators/CMakeLists.txt'
24--- plugins/Unity/Indicators/CMakeLists.txt 2014-06-26 10:00:41 +0000
25+++ plugins/Unity/Indicators/CMakeLists.txt 2014-09-25 12:44:25 +0000
26@@ -30,16 +30,7 @@
27 )
28 add_definitions(-DUNITYINDICATORS_LIBRARY)
29
30-set(IndicatorsQML_RESOURCES
31- resources/indicators.qrc
32-)
33-
34-qt5_add_resources(IndicatorsQML_RESOURCES_RCC
35- ${IndicatorsQML_RESOURCES}
36-)
37-
38 add_library(IndicatorsQml SHARED
39- ${IndicatorsQML_RESOURCES_RCC}
40 ${IndicatorsQML_SOURCES}
41 )
42
43
44=== modified file 'plugins/Unity/Indicators/plugin.cpp'
45--- plugins/Unity/Indicators/plugin.cpp 2013-10-23 14:22:27 +0000
46+++ plugins/Unity/Indicators/plugin.cpp 2014-09-25 12:44:25 +0000
47@@ -42,8 +42,6 @@
48
49 void Indicators2Plugin::registerTypes(const char *uri)
50 {
51- Q_INIT_RESOURCE(indicators);
52-
53 qmlRegisterType<IndicatorsManager>(uri, 0, 1, "IndicatorsManager");
54 qmlRegisterType<IndicatorsModel>(uri, 0, 1, "IndicatorsModel");
55 qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
56
57=== removed directory 'plugins/Unity/Indicators/resources'
58=== removed directory 'plugins/Unity/Indicators/resources/artwork'
59=== removed directory 'plugins/Unity/Indicators/resources/artwork/messaging'
60=== removed file 'plugins/Unity/Indicators/resources/artwork/messaging/default_app.svg'
61--- plugins/Unity/Indicators/resources/artwork/messaging/default_app.svg 2013-06-07 12:51:15 +0000
62+++ plugins/Unity/Indicators/resources/artwork/messaging/default_app.svg 1970-01-01 00:00:00 +0000
63@@ -1,42 +0,0 @@
64-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
65-<!-- Created with Inkscape (http://www.inkscape.org/) -->
66-<svg id="svg15137" xmlns="http://www.w3.org/2000/svg" height="48" width="48" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
67- <defs id="defs15139">
68- <radialGradient id="radialGradient2612" gradientUnits="userSpaceOnUse" cy="4.625" cx="62.625" gradientTransform="matrix(1 0 0 .34118 0 3.0471)" r="10.625">
69- <stop id="stop8840" offset="0"/>
70- <stop id="stop8842" style="stop-opacity:0" offset="1"/>
71- </radialGradient>
72- <linearGradient id="linearGradient15133" y2=".24326" gradientUnits="userSpaceOnUse" x2="62.2" gradientTransform="matrix(2.1499 0 0 2.1499 -110.12 31.935)" y1="-12.489" x1="62.2">
73- <stop id="stop4875" style="stop-color:#fff" offset="0"/>
74- <stop id="stop4877" style="stop-color:#fff;stop-opacity:0" offset="1"/>
75- </linearGradient>
76- <radialGradient id="radialGradient15127" gradientUnits="userSpaceOnUse" cy="-8.7256" cx="62.2" gradientTransform="matrix(2.4129 0 0 2.413 -126.48 34.231)" r="9.7553">
77- <stop id="stop8649" style="stop-color:#8fb1dc" offset="0"/>
78- <stop id="stop8651" style="stop-color:#3465a4" offset="1"/>
79- </radialGradient>
80- <radialGradient id="radialGradient2418" gradientUnits="userSpaceOnUse" cy="24.149" cx="17.814" gradientTransform="matrix(-2.644 0 2.9365e-8 2.5344 78.725 -37.986)" r="9.125">
81- <stop id="stop4847" style="stop-color:#fff" offset="0"/>
82- <stop id="stop4849" style="stop-color:#b6b6b6" offset="1"/>
83- </radialGradient>
84- <radialGradient id="radialGradient5145" gradientUnits="userSpaceOnUse" cy="13.067" cx="23.86" gradientTransform="matrix(-1.5425 0 0 -.84553 60.718 23.829)" r="18.098">
85- <stop id="stop14112" style="stop-color:#557695" offset="0"/>
86- <stop id="stop14114" style="stop-color:#15395c" offset="1"/>
87- </radialGradient>
88- <radialGradient id="radialGradient5147" gradientUnits="userSpaceOnUse" cy="-3.442" cx="62.225" gradientTransform="matrix(1.1035 0 0 1.0265 -4.1555 -1.8158)" r="10.081">
89- <stop id="stop14118" style="stop-color:#9e9e9e" offset="0"/>
90- <stop id="stop14120" style="stop-color:#9e9e9e;stop-opacity:0" offset="1"/>
91- </radialGradient>
92- </defs>
93- <g id="layer1">
94- <path id="path8836" style="opacity:.4;fill-rule:evenodd;fill:url(#radialGradient2612)" d="m73.25 4.625a10.625 3.625 0 1 1 -21.25 0 10.625 3.625 0 1 1 21.25 0z" transform="matrix(2.1647 0 0 2.5637 -111.56 26.85)"/>
95- <g id="g15122" transform="translate(.79042 -.78563)">
96- <path id="path6495" style="stroke:#204a87;fill:url(#radialGradient15127)" d="m43.505 24.387c0 10.99-8.9091 19.899-19.897 19.899-10.989 0-19.898-8.9091-19.898-19.899 0-10.989 8.9086-19.897 19.898-19.897 10.988 0 19.897 8.9081 19.897 19.897z"/>
97- <path id="path6534" style="stroke:url(#radialGradient5147);stroke-width:1.1035;fill:url(#radialGradient5145)" d="m23.726 5.3141c-1.5283 0.12067-3.0328 0.36544-4.4919 0.84567-1.23 0.48843 0.88689-0.42988-0.37486-0.60468-0.75942-0.12994-1.0776 0.65251-1.7561 0.67046-0.7741 0.023841-1.3048 0.71572-2.0319 0.79898-0.26187 1.4432-0.59924-0.56894-0.83949 0.13173 0.19047 0.7212-0.07796 1.1928-0.63582 1.6119-0.60156 0.68249-0.03584 1.2934 0.54212 0.69395 0.2775-0.83446 1.1825-1.7618 2.0655-1.2049 0.8837 0.48448 1.7582 1.6525 2.4938 0.40935-0.75488-0.090735-1.0462-0.73637-1.4079-1.2096-0.40023 0.031761-2.0794-0.32019-1.0059-0.24024 0.5284-0.17249 1.549-0.68558 1.9239-0.66537-0.94013 0.49026 0.35015 0.81268 0.73202 1.2035 0.68671 0.20357 0.99776 1.0757 0.37414 1.527-0.80181 0.4162 0.05573 1.1017 0.221 1.6748 0.12828 0.99827 0.99623 0.43282 1.2716-0.18046 0.39803-1.1153 1.6733-1.0767 2.5958-1.5522 1.008-0.51754 1.0248-0.53575 1.5034 0.20195 0.36764 0.21151 1.5947-0.55825 0.78901-0.929-0.68957 0.03713-1.142 0.46029-0.56364-0.60801 0.13915-0.57404 0.6791-1.3235 0.58092-1.7937-0.662-0.2603-1.324-0.5207-1.986-0.7811zm-9.3732 3.6945c0.35612 0.3643 1.5564 1.0234 1.4368 0.11255-0.14419-0.61744-1.0418-0.62308-1.4368-0.11255zm18.165-0.44471c-0.82412 0.16922-1.6412 0.35467-2.292 0.92363 0.19457 0.7853-0.8341 0.89786-1.2851 1.3281-0.12036 0.25242-0.02467 1.8403 0.51105 1.1573 0.58162-0.77246 0.83368 0.40868 1.4478 0.52687 0.4451-0.14324 0.5002-1.1438 0.33275-1.6043 0.28525-0.46984 0.75058-1.1195 1.3539-1.0659-0.37419 0.57099-0.80163 2.0315 0.3911 1.4345 0.34518-0.006-0.93958 0.75452-1.0166 1.273-0.48258 0.51284-0.9934 0.90587-1.6905 0.50847-0.33355-0.28162-0.50305-1.0992-0.71414-0.17566 0.43341 0.73252-1.089 0.04718-1.0514 1.0356-0.31972 0.61514-0.89623 0.8671-1.563 0.91149 0.24198 0.19141 1.1924 1.3314 0.24953 1.1701-0.60352 0.06628-1.4857 0.40701-1.2414 1.1653-0.27486 0.9444 0.4249 0.70654 0.85522 1.2977 0.70116-0.19916 1.1488-0.62908 1.2634-1.3621 0.65618-0.19273 0.73557-0.93195 1.456-0.91702 0.7182-0.40381 0.88559 0.73738 1.5587 0.82181 0.07058 0.4087-0.33464 1.281 0.45659 0.4693 0.76441-0.55387-0.79512-1.2716-0.30963-1.4066 0.69099 0.22071 0.94006 0.87671 1.051 1.519 0.56306 0.9634 0.70185 0.44404 0.74672-0.40362 0.87723-0.39439 1.1473 1.641 2.3881 1.1397 0.92678 0.19174 0.59949 0.8304-0.01904 1.2203-0.50066 0.47112-1.3382 0.17338-1.9265-0.01558-0.56472-0.27756-1.3196-0.24813-1.6214 0.38347-0.46529-0.21764-0.94642-0.91135-1.4178-1.3118-1.1647-0.5139-2.4314-0.07571-3.5919 0.23946-0.99563 1.1632-2.1949 2.219-2.6236 3.7359-0.62778 0.63853 0.54336 1.0082-0.24392 1.556-0.6428 0.51279 0.10805 1.1629 0.2458 1.7527 0.60445 0.74395 1.6306 3.0723 2.5708 2.1452 0.52705-0.80245 0.81963 0.61582 1.4399-0.30194 0.4952-0.39949 0.9695 0.45802 1.6897 0.14331 0.69372 0.4284 0.56095 1.0433 0.27484 1.6928 0.15583 0.54087 0.93098 0.9344 0.62978 1.6677-0.27366 0.68309 0.58312 1.201 0.41038 1.7987-0.5748 1.1512-0.43928 2.5747 0.09386 3.7157 0.42668 1.0325 0.67699 2.1484 0.64366 3.2692 0.74277 0.2222 1.1367-0.72912 1.8776-0.51313 0.72333 0.09324 0.99191-0.82974 1.5008-1.2158 0.56704-0.46747-0.07223-1.1873 0.82794-1.5185 0.87331-0.42523-1.106-1.0213 0.0152-1.4024 0.46515-0.51761 1.4132-0.69776 1.6008-1.3735-0.33834-1.0398-0.21797-2.1801-0.16738-3.2436 0.32552-0.84167 0.72975-1.6312 1.4262-2.2272 0.28082-0.92669 0.94924-1.7777 0.88942-2.7709-1.6476 0.50399-1.1482-0.21491-0.22962-0.87318 0.63508-0.42199 1.4051-0.84564 1.7006-1.5617 0.14435-0.81048-0.45227-2.1297-1.0079-0.90496-0.24511-0.4707-1.1542-0.71744-1.113-1.3307-0.17659-1.2625 0.34462-0.14427 0.86051 0.10789 1.1146-0.60521 1.6818 1.7766 2.3893 0.35503-0.618-4.471-3.052-8.528-6.34-11.567-0.571-1.0949-0.921 0.75-1.501 0.68-0.464-0.485-1.33-1.1394-0.122-0.914 1.034-0.3028 0.333-0.7027-0.425-0.6842-0.574-0.0697-1.101-0.2706-1.635-0.4789zm-20.56 0.4447c-0.275 1.3534-2.0109 1.1954-2.6162 2.5304-2.9783 3.153-4.8166 7.302-5.32 11.598 0.26584 1.0071 1.1105 1.4908 1.9601 1.9373 0.72184 0.41932 1.7801 0.2342 2.1848 1.1124 0.45187 0.36983 0.93948 1.0997 1.5856 0.87722 0.93664-0.09099 0.36019 0.85823 0.19973 1.3392-0.059277 0.607-0.80778 0.99372-0.52016 1.5778-0.24136 0.66166-0.43304 1.3177 0.10262 1.8906 0.45551 0.83988 0.82632 1.7478 1.6708 2.2751 0.59217 0.49728 1.2625 1.1553 1.0304 1.9974-0.12338 0.68167 0.04306 1.3099 0.3725 1.908-0.11816 0.67146-0.36073 1.3584-0.4105 2.0183 0.87949 0.62206 2.6705 2.0606 2.8031 0.49489 0.50176-0.45161 0.5321-1.1784 1.3743-1.1804 0.3909-0.47777 0.52549-1.2283 0.81706-1.8117-0.42572-0.5384 0.16631-1.3697 0.8046-1.3477 0.81594 0.06128 0.78593-0.89448 1.1111-1.4232-0.0073-0.77224-0.38892-1.6471 0.30542-2.227 0.52242-0.47344 0.46827-1.1675 0.5498-1.8097-1.171-0.7244-2.712-1.0911-3.6386-2.0687-0.18364-0.76504-0.7598-1.0229-1.4925-1.0784-0.30936-0.43256-0.25697-1.4628-0.79753-1.5131-0.69628 0.13369-1.3857 0.24089-1.8917-0.3644-0.573-0.776-1.069 0.2-1.593 0.546-0.492 0.856-1.8683-0.043-1.7038-1.007 0.4839-1.334-1.6425 0.148-0.7699-1.425 0.4151-1.715-0.7067-0.396-1.2952-0.011-0.71822 0.0081-0.98953-0.70747-0.86146-1.3625-0.091117-0.78733 0.48283-1.1877 1.0669-1.5822 0.78161 0.12038 0.97989-0.56085 1.5654-0.4722 0.73603-0.03767 1.0049 0.66782 1.4232 1.1357 0.17514-0.66797-0.18345-1.6152 0.55606-1.9879 0.56414-0.42781 1.137-0.84927 1.2721-1.5904 0.13304-0.77598 1.2893-0.46761 1.4837-1.2526 0.26877-0.8206 1.5114-0.15823 1.7899-0.96804 0.8733-0.82086-0.27242-0.57178-0.89854-0.59806-1.2353 0.12695 0.1228-0.32763 0.58598-0.58155 0.68608 0.09073 1.3195-0.13384 1.9499-0.37629 0.08445 0.85843 0.24597 1.3112 0.68417 0.30788-0.85421-0.20211-0.11618-1.0402-0.95973-1.2614-0.66764 0.04697 0.0066-1.4189-0.81571-1.2577-1.0697 0.70782-0.11401-0.50251-0.9854-0.66347-0.68736-0.74222-0.85436 0.47657-1.2276 0.9183 0.24207 0.84702-0.79095 0.66525-0.97976 1.3606-0.41814 1.2534-0.24143-0.08931-0.74055-0.41035-0.61653-0.24732-1.3592-0.3784-1.3637-1.1899 0.82658-0.60512 2.0667-0.96189 2.5994-1.9148 0.3095-0.74008-0.26215-1.1445-0.96618-1.0889l-0.000005-2e-7zm14.675 1.642c-0.12491 0.65746 0.5475 1.009 0.30788 1.7104-0.21487 0.76842-0.27728 1.3789 0.68289 0.93046 0.99668-0.51183 0.36052-0.90148-0.03867-1.5728-0.27187-0.44613-0.24574-1.275-0.9521-1.0681zm-0.75259 1.0947c-0.79414-0.24012-0.61745 1.4493-0.12164 1.0118 0.7276-0.17916 0.23703-0.5252 0.12164-1.0118zm10.023 8.9969c0.95184 0.84444 1.277 2.0946 1.8858 3.1596 0.90428 0.39972 0.0415 1.0795 0.44521 1.5712 0.84897 0.92228-1.1752 0.24516-0.90606-0.67899-0.1971-1.2139-1.0559-2.044-1.4678-3.1045-0.04294-0.3526-0.38552-0.71788 0.04284-0.94732z"/>
98- <path id="path8655" style="opacity:.4;stroke:url(#linearGradient15133);fill:none" d="m42.409 24.387c0 10.384-8.4184 18.803-18.801 18.803-10.384 0-18.802-8.4184-18.802-18.803 0-10.384 8.418-18.801 18.802-18.801 10.383 0 18.801 8.4175 18.801 18.801z"/>
99- </g>
100- <g id="g2414" transform="matrix(.99991 -.013701 .013701 .99991 -.28870 .53585)">
101- <path id="path3970" style="stroke-linejoin:round;fill-rule:evenodd;stroke:#666;fill:url(#radialGradient2418)" d="m30.5 20.937 17 16.5-7.75 0.25s3.25 6.75 3.25 6.75c1 3-3.5 4.125-4.25 1.875l-3-6.75-5.5 5.875 0.25-24.5z"/>
102- <path id="path4853" style="opacity:.4;stroke:#fff;fill:none" d="m31.657 23.379 13.476 13.186-6.9219 0.27746l3.8721 7.7566c0.40273 1.6501-2.0283 2.4126-2.5071 1.1529l-3.6831-7.845-4.4247 4.7083 0.18907-19.236z"/>
103- </g>
104- </g>
105-</svg>
106
107=== removed file 'plugins/Unity/Indicators/resources/artwork/messaging/default_contact.png'
108Binary files plugins/Unity/Indicators/resources/artwork/messaging/default_contact.png 2013-06-07 12:51:15 +0000 and plugins/Unity/Indicators/resources/artwork/messaging/default_contact.png 1970-01-01 00:00:00 +0000 differ
109=== removed file 'plugins/Unity/Indicators/resources/indicators.qrc'
110--- plugins/Unity/Indicators/resources/indicators.qrc 2013-12-13 15:11:30 +0000
111+++ plugins/Unity/Indicators/resources/indicators.qrc 1970-01-01 00:00:00 +0000
112@@ -1,6 +0,0 @@
113-<RCC>
114- <qresource prefix="/indicators">
115- <file>artwork/messaging/default_contact.png</file>
116- <file>artwork/messaging/default_app.svg</file>
117- </qresource>
118-</RCC>
119
120=== modified file 'plugins/Utils/CMakeLists.txt'
121--- plugins/Utils/CMakeLists.txt 2014-07-17 17:10:05 +0000
122+++ plugins/Utils/CMakeLists.txt 2014-09-25 12:44:25 +0000
123@@ -13,6 +13,7 @@
124 set(QMLPLUGIN_SRC
125 qlimitproxymodelqml.cpp
126 qsortfilterproxymodelqml.cpp
127+ relativetimeformatter.cpp
128 timeformatter.cpp
129 unitymenumodelpaths.cpp
130 windowkeysfilter.cpp
131
132=== modified file 'plugins/Utils/plugin.cpp'
133--- plugins/Utils/plugin.cpp 2014-07-17 17:10:05 +0000
134+++ plugins/Utils/plugin.cpp 2014-09-25 12:44:25 +0000
135@@ -28,6 +28,7 @@
136 // local
137 #include "qlimitproxymodelqml.h"
138 #include "qsortfilterproxymodelqml.h"
139+#include "relativetimeformatter.h"
140 #include "timeformatter.h"
141 #include "unitymenumodelpaths.h"
142 #include "windowkeysfilter.h"
143@@ -44,6 +45,7 @@
144 qmlRegisterType<WindowKeysFilter>(uri, 0, 1, "WindowKeysFilter");
145 qmlRegisterType<GDateTimeFormatter>(uri, 0, 1, "GDateTimeFormatter");
146 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
147+ qmlRegisterType<RelativeTimeFormatter>(uri, 0, 1, "RelativeTimeFormatter");
148 }
149
150 void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
151
152=== added file 'plugins/Utils/relativetimeformatter.cpp'
153--- plugins/Utils/relativetimeformatter.cpp 1970-01-01 00:00:00 +0000
154+++ plugins/Utils/relativetimeformatter.cpp 2014-09-25 12:44:25 +0000
155@@ -0,0 +1,268 @@
156+/*
157+ * Copyright 2014 Canonical Ltd.
158+ *
159+ * This program is free software; you can redistribute it and/or modify
160+ * it under the terms of the GNU General Public License as published by
161+ * the Free Software Foundation; version 3.
162+ *
163+ * This program is distributed in the hope that it will be useful,
164+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
165+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
166+ * GNU General Public License for more details.
167+ *
168+ * You should have received a copy of the GNU General Public License
169+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
170+ *
171+ */
172+
173+// Local
174+#include "relativetimeformatter.h"
175+
176+// Qt
177+#include <QDateTime>
178+
179+// Other
180+#include <glib.h>
181+#include <glib/gi18n.h>
182+#include <locale.h>
183+#include <langinfo.h>
184+#include <string.h>
185+
186+RelativeTimeFormatter::RelativeTimeFormatter(QObject *parent)
187+ : GDateTimeFormatter(parent)
188+{
189+}
190+
191+ /* Check the system locale setting to see if the format is 24-hour
192+ time or 12-hour time */
193+gboolean
194+is_locale_12h(void)
195+{
196+ int i;
197+ static const char *formats_24h[] = {"%H", "%R", "%T", "%OH", "%k", nullptr};
198+ const char* t_fmt = nl_langinfo(T_FMT);
199+
200+ for (i=0; formats_24h[i]!=nullptr; i++)
201+ if (strstr(t_fmt, formats_24h[i]) != nullptr)
202+ return FALSE;
203+
204+ return TRUE;
205+}
206+
207+typedef enum
208+{
209+ DATE_PROXIMITY_YESTERDAY,
210+ DATE_PROXIMITY_TODAY,
211+ DATE_PROXIMITY_TOMORROW,
212+ DATE_PROXIMITY_LAST_WEEK,
213+ DATE_PROXIMITY_NEXT_WEEK,
214+ DATE_PROXIMITY_FAR
215+} date_proximity_t;
216+
217+static date_proximity_t
218+getDateProximity(GDateTime* now, GDateTime* time)
219+{
220+ date_proximity_t prox = DATE_PROXIMITY_FAR;
221+ gint now_year, now_month, now_day;
222+ gint time_year, time_month, time_day;
223+
224+ // does it happen today?
225+ g_date_time_get_ymd(now, &now_year, &now_month, &now_day);
226+ g_date_time_get_ymd(time, &time_year, &time_month, &time_day);
227+ if ((now_year == time_year) && (now_month == time_month) && (now_day == time_day)) {
228+ return DATE_PROXIMITY_TODAY;
229+ }
230+
231+ // did it happen yesterday?
232+ GDateTime* tomorrow = g_date_time_add_days(now, -1);
233+ gint tom_year, tom_month, tom_day;
234+ g_date_time_get_ymd(tomorrow, &tom_year, &tom_month, &tom_day);
235+ g_date_time_unref(tomorrow);
236+ if ((tom_year == time_year) && (tom_month == time_month) && (tom_day == time_day)) {
237+ return DATE_PROXIMITY_YESTERDAY;
238+ }
239+
240+ // does it happen tomorrow?
241+ if (prox == DATE_PROXIMITY_FAR)
242+ {
243+ GDateTime* tomorrow = g_date_time_add_days(now, 1);
244+
245+ gint tom_year, tom_month, tom_day;
246+ g_date_time_get_ymd(tomorrow, &tom_year, &tom_month, &tom_day);
247+ g_date_time_unref(tomorrow);
248+ if ((tom_year == time_year) && (tom_month == time_month) && (tom_day == time_day)) {
249+ return DATE_PROXIMITY_TOMORROW;
250+ }
251+ }
252+
253+ // does it happen this week?
254+ if (prox == DATE_PROXIMITY_FAR) {
255+ if (g_date_time_compare(time, now) < 0) {
256+ GDateTime* last_week = g_date_time_add_days(now, -6);
257+ GDateTime* last_week_bound = g_date_time_new_local(g_date_time_get_year(last_week),
258+ g_date_time_get_month(last_week),
259+ g_date_time_get_day_of_month(last_week),
260+ 0, 0, 0);
261+ if (g_date_time_compare(time, last_week_bound) >= 0)
262+ prox = DATE_PROXIMITY_LAST_WEEK;
263+
264+ g_date_time_unref(last_week);
265+ g_date_time_unref(last_week_bound);
266+ } else {
267+ GDateTime* next_week = g_date_time_add_days(now, 6);
268+ GDateTime* next_week_bound = g_date_time_new_local(g_date_time_get_year(next_week),
269+ g_date_time_get_month(next_week),
270+ g_date_time_get_day_of_month(next_week),
271+ 23, 59, 59.9);
272+ if (g_date_time_compare(time, next_week_bound) <= 0)
273+ prox = DATE_PROXIMITY_NEXT_WEEK;
274+
275+ g_date_time_unref(next_week);
276+ g_date_time_unref(next_week_bound);
277+ }
278+
279+ }
280+
281+ return prox;
282+}
283+
284+const char*
285+dgettext_datetime(const char *text)
286+{
287+ return dgettext("indicator-datetime", text);
288+}
289+
290+/**
291+ * _ a time yesterday should be shown as (e.g. “Yesterday 3:55 PM”)
292+ * _ a time today should be shown as just the time (e.g. “3:55 PM”)
293+ * _ a time tomorrow should be shown as(e.g. “Tomorrow 3:55 PM”)
294+ * _ a time any other day this week should be shown as the short version of the
295+ * day and time (e.g. “Wed 3:55 PM”)
296+ * weekday (e.g. “Friday”)
297+ * _ a time after this week should be shown as the short version of the day,
298+ * date, and time (e.g. “Wed 21 Apr 3:55 PM”)
299+ * _ in addition, when presenting the times of upcoming events, the time should
300+ * be followed by the timezone if it is different from the one the computer
301+ * is currently set to. For example, “Wed 3:55 PM UTC−5”.
302+ *
303+ * TODO - keep inline with indicator-datetime
304+ */
305+char* generate_full_format_string_at_time (GDateTime* now,
306+ GDateTime* then)
307+{
308+ GString* ret = g_string_new (nullptr);
309+
310+ if (then != nullptr) {
311+ const date_proximity_t prox = getDateProximity(now, then);
312+
313+ if (is_locale_12h()) {
314+ switch (prox) {
315+ case DATE_PROXIMITY_YESTERDAY:
316+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
317+ This format string is used for showing, on a 12-hour clock, times that happen yesterday.
318+ (\u2003 is a unicode em space which is slightly wider than a normal space.)
319+ en_US example: "Yesterday\u2003%l:%M %p" --> "Yesterday 1:00 PM" */
320+ g_string_assign (ret, dgettext_datetime("Yesterday\u2003%l:%M %p"));
321+ break;
322+
323+ case DATE_PROXIMITY_TODAY:
324+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
325+ This format string is used for showing, on a 12-hour clock, times that happened today.
326+ en_US example: "%l:%M %p" --> "1:00 PM" */
327+ g_string_assign (ret, dgettext_datetime("%l:%M %p"));
328+ break;
329+
330+ case DATE_PROXIMITY_TOMORROW:
331+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
332+ This format string is used for showing, on a 12-hour clock, events/appointments that happen tomorrow.
333+ (\u2003 is a unicode em space which is slightly wider than a normal space.)
334+ en_US example: "Tomorrow\u2003%l:%M %p" --> "Tomorrow 1:00 PM" */
335+ g_string_assign (ret, dgettext_datetime("Tomorrow\u2003%l:%M %p"));
336+ break;
337+
338+ case DATE_PROXIMITY_LAST_WEEK:
339+ case DATE_PROXIMITY_NEXT_WEEK:
340+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
341+ This format string is used for showing, on a 12-hour clock, times that happened in the last week.
342+ (\u2003 is a unicode em space which is slightly wider than a normal space.)
343+ en_US example: "%a\u2003%l:%M %p" --> "Fri 1:00 PM" */
344+ g_string_assign (ret, dgettext_datetime("%a\u2003%l:%M %p"));
345+ break;
346+
347+ case DATE_PROXIMITY_FAR:
348+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
349+ This format string is used for showing, on a 12-hour clock, times that happened before a week from now.
350+ (\u2003 is a unicode em space which is slightly wider than a normal space.)
351+ en_US example: "%a %d %b\u2003%l:%M %p" --> "Fri Oct 31 1:00 PM"
352+ en_GB example: "%a %b %d\u2003%l:%M %p" --> "Fri 31 Oct 1:00 PM" */
353+ g_string_assign (ret, dgettext_datetime("%a %d %b\u2003%l:%M %p"));
354+ break;
355+ }
356+ } else {
357+ switch (prox) {
358+
359+ case DATE_PROXIMITY_YESTERDAY:
360+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
361+ This format string is used for showing, on a 24-hour clock, times that happen yesterday.
362+ (\u2003 is a unicode em space which is slightly wider than a normal space.)
363+ en_US example: "Yesterday\u2003%l:%M %p" --> "Yesterday 13:00" */
364+ g_string_assign (ret, dgettext_datetime("Yesterday\u2003%H:%M"));
365+ break;
366+
367+ case DATE_PROXIMITY_TODAY:
368+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
369+ This format string is used for showing, on a 24-hour clock, times that happened today.
370+ en_US example: "%H:%M" --> "13:00" */
371+ g_string_assign (ret, dgettext_datetime("%H:%M"));
372+ break;
373+
374+ case DATE_PROXIMITY_TOMORROW:
375+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
376+ This format string is used for showing, on a 24-hour clock, events/appointments that happen tomorrow.
377+ (\u2003 is a unicode em space which is slightly wider than a normal space.)
378+ en_US example: "Tomorrow\u2003%l:%M %p" --> "Tomorrow 13:00" */
379+ g_string_assign (ret, dgettext_datetime("Tomorrow\u2003%H:%M"));
380+ break;
381+
382+ case DATE_PROXIMITY_LAST_WEEK:
383+ case DATE_PROXIMITY_NEXT_WEEK:
384+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
385+ This format string is used for showing, on a 24-hour clock, times that happened in the last week.
386+ (\u2003 is a unicode em space which is slightly wider than a normal space.)
387+ en_US example: "%a\u2003%H:%M" --> "Fri 13:00" */
388+ g_string_assign (ret, dgettext_datetime("%a\u2003%H:%M"));
389+ break;
390+
391+ case DATE_PROXIMITY_FAR:
392+ /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
393+ This format string is used for showing, on a 24-hour clock, times that happened before a week from now.
394+ (\u2003 is a unicode em space which is slightly wider than a normal space.)
395+ en_US example: "%a %d %b\u2003%H:%M" --> "Fri Oct 31 13:00"
396+ en_GB example: "%a %b %d\u2003%H:%M" --> "Fri 31 Oct 13:00" */
397+ g_string_assign (ret, dgettext_datetime("%a %d %b\u2003%H:%M"));
398+ break;
399+ }
400+ }
401+ }
402+
403+ return g_string_free (ret, FALSE);
404+}
405+
406+QString RelativeTimeFormatter::format() const
407+{
408+ GDateTime* now = g_date_time_new_from_unix_utc(QDateTime::currentMSecsSinceEpoch() / 1000);
409+ if (!now) { return QString(); }
410+
411+ GDateTime* then = g_date_time_new_from_unix_local(time());
412+ if (!then) { return QString(); }
413+
414+ char* time_format = generate_full_format_string_at_time(now, then);
415+
416+ QString str(QString::fromUtf8(time_format));
417+ g_free(time_format);
418+
419+ g_date_time_unref(now);
420+ g_date_time_unref(then);
421+
422+ return str;
423+}
424
425=== added file 'plugins/Utils/relativetimeformatter.h'
426--- plugins/Utils/relativetimeformatter.h 1970-01-01 00:00:00 +0000
427+++ plugins/Utils/relativetimeformatter.h 2014-09-25 12:44:25 +0000
428@@ -0,0 +1,34 @@
429+/*
430+ * Copyright 2014 Canonical Ltd.
431+ *
432+ * This program is free software; you can redistribute it and/or modify
433+ * it under the terms of the GNU General Public License as published by
434+ * the Free Software Foundation; version 3.
435+ *
436+ * This program is distributed in the hope that it will be useful,
437+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
438+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
439+ * GNU General Public License for more details.
440+ *
441+ * You should have received a copy of the GNU General Public License
442+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
443+ *
444+ */
445+
446+#ifndef RELATIVETIMEFORMATTER_H
447+#define RELATIVETIMEFORMATTER_H
448+
449+#include "timeformatter.h"
450+
451+// TODO - move this to the sdk
452+// https://blueprints.launchpad.net/ubuntu-ui-toolkit/+spec/time-formatter
453+class RelativeTimeFormatter : public GDateTimeFormatter
454+{
455+ Q_OBJECT
456+public:
457+ RelativeTimeFormatter(QObject *parent = 0);
458+
459+ QString format() const override;
460+};
461+
462+#endif // RELATIVETIMEFORMATTER_H
463
464=== modified file 'plugins/Utils/timeformatter.cpp'
465--- plugins/Utils/timeformatter.cpp 2014-08-26 08:14:44 +0000
466+++ plugins/Utils/timeformatter.cpp 2014-09-25 12:44:25 +0000
467@@ -121,6 +121,11 @@
468 g_bus_get (G_BUS_TYPE_SYSTEM, priv->cancellable, got_bus, priv);
469 }
470
471+TimeFormatter::TimeFormatter(const QString &initialFormat, QObject *parent): TimeFormatter(parent)
472+{
473+ priv->format = initialFormat;
474+}
475+
476 TimeFormatter::~TimeFormatter()
477 {
478 if (priv->system_bus) {
479@@ -177,7 +182,7 @@
480 }
481
482 GDateTimeFormatter::GDateTimeFormatter(QObject* parent)
483-: TimeFormatter(parent)
484+: TimeFormatter("%d-%m-%Y %I:%M%p", parent)
485 {
486 }
487
488
489=== modified file 'plugins/Utils/timeformatter.h'
490--- plugins/Utils/timeformatter.h 2013-12-13 13:25:35 +0000
491+++ plugins/Utils/timeformatter.h 2014-09-25 12:44:25 +0000
492@@ -33,7 +33,7 @@
493 TimeFormatter(QObject *parent = 0);
494 virtual ~TimeFormatter();
495
496- QString format() const;
497+ virtual QString format() const;
498 QString timeString() const;
499 qint64 time() const;
500
501@@ -48,6 +48,8 @@
502 void timeChanged(qint64 time);
503
504 protected:
505+ TimeFormatter(const QString &initialFormat, QObject *parent = 0);
506+
507 virtual QString formatTime() const;
508
509 private:
510
511=== modified file 'po/unity8.pot'
512--- po/unity8.pot 2014-09-18 12:13:23 +0000
513+++ po/unity8.pot 2014-09-25 12:44:25 +0000
514@@ -8,7 +8,7 @@
515 msgstr ""
516 "Project-Id-Version: unity8\n"
517 "Report-Msgid-Bugs-To: \n"
518-"POT-Creation-Date: 2014-09-18 20:12+0800\n"
519+"POT-Creation-Date: 2014-09-24 10:43+0100\n"
520 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
521 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
522 "Language-Team: LANGUAGE <LL@li.org>\n"
523@@ -21,12 +21,12 @@
524 msgid "Password: "
525 msgstr ""
526
527-#: plugins/Unity/Launcher/launcheritem.cpp:44
528-#: plugins/Unity/Launcher/launcheritem.cpp:74
529+#: plugins/Unity/Launcher/launcheritem.cpp:45
530+#: plugins/Unity/Launcher/launcheritem.cpp:91
531 msgid "Pin shortcut"
532 msgstr ""
533
534-#: plugins/Unity/Launcher/launcheritem.cpp:74
535+#: plugins/Unity/Launcher/launcheritem.cpp:91
536 msgid "Unpin shortcut"
537 msgstr ""
538
539@@ -157,15 +157,15 @@
540 msgid "Hello"
541 msgstr ""
542
543-#: qml/Dash/GenericScopeView.qml:364 qml/Dash/GenericScopeView.qml:483
544+#: qml/Dash/GenericScopeView.qml:411 qml/Dash/GenericScopeView.qml:533
545 msgid "See less"
546 msgstr ""
547
548-#: qml/Dash/GenericScopeView.qml:364
549+#: qml/Dash/GenericScopeView.qml:411
550 msgid "See all"
551 msgstr ""
552
553-#: qml/Dash/GenericScopeView.qml:427 qml/Dash/PageHeader.qml:258
554+#: qml/Dash/GenericScopeView.qml:473 qml/Dash/PageHeader.qml:258
555 #: qml/Panel/SearchIndicator.qml:27
556 msgid "Search"
557 msgstr ""
558@@ -203,7 +203,7 @@
559 msgstr ""
560
561 #: qml/Dash/ScopesOverview.qml:206
562-msgid "Manage Dash"
563+msgid "Manage Scopes"
564 msgstr ""
565
566 #: qml/Dash/ScopesOverview.qml:428
567@@ -266,27 +266,31 @@
568 msgid "Conference"
569 msgstr ""
570
571-#: qml/Panel/Indicators/MenuItemFactory.qml:651
572+#: qml/Panel/Indicators/MenuItemFactory.qml:600
573+msgid "Nothing is playing"
574+msgstr ""
575+
576+#: qml/Panel/Indicators/MenuItemFactory.qml:748
577 msgid "In queue…"
578 msgstr ""
579
580-#: qml/Panel/Indicators/MenuItemFactory.qml:655
581+#: qml/Panel/Indicators/MenuItemFactory.qml:752
582 msgid "Downloading"
583 msgstr ""
584
585-#: qml/Panel/Indicators/MenuItemFactory.qml:657
586+#: qml/Panel/Indicators/MenuItemFactory.qml:754
587 msgid "Paused, tap to resume"
588 msgstr ""
589
590-#: qml/Panel/Indicators/MenuItemFactory.qml:659
591+#: qml/Panel/Indicators/MenuItemFactory.qml:756
592 msgid "Canceled"
593 msgstr ""
594
595-#: qml/Panel/Indicators/MenuItemFactory.qml:661
596+#: qml/Panel/Indicators/MenuItemFactory.qml:758
597 msgid "Finished"
598 msgstr ""
599
600-#: qml/Panel/Indicators/MenuItemFactory.qml:663
601+#: qml/Panel/Indicators/MenuItemFactory.qml:760
602 msgid "Failed, tap to retry"
603 msgstr ""
604
605@@ -298,51 +302,51 @@
606 msgid "Roaming"
607 msgstr ""
608
609-#: qml/Shell.qml:292
610+#: qml/Shell.qml:320
611 msgid "Enter your passphrase"
612 msgstr ""
613
614-#: qml/Shell.qml:293
615+#: qml/Shell.qml:321
616 msgid "Sorry, incorrect passphrase"
617 msgstr ""
618
619-#: qml/Shell.qml:295
620+#: qml/Shell.qml:323
621 msgid "Enter your passcode"
622 msgstr ""
623
624-#: qml/Shell.qml:296
625+#: qml/Shell.qml:324
626 msgid "Sorry, incorrect passcode"
627 msgstr ""
628
629-#: qml/Shell.qml:299
630+#: qml/Shell.qml:327
631 #, qt-format
632 msgid "Enter your %1"
633 msgstr ""
634
635-#: qml/Shell.qml:300
636+#: qml/Shell.qml:328
637 #, qt-format
638 msgid "Sorry, incorrect %1"
639 msgstr ""
640
641-#: qml/Shell.qml:335
642+#: qml/Shell.qml:363
643 msgid "Sorry, incorrect passphrase."
644 msgstr ""
645
646-#: qml/Shell.qml:336
647+#: qml/Shell.qml:364
648 msgid "Sorry, incorrect passcode."
649 msgstr ""
650
651-#: qml/Shell.qml:337
652+#: qml/Shell.qml:365
653 msgid "This will be your last attempt."
654 msgstr ""
655
656-#: qml/Shell.qml:339
657+#: qml/Shell.qml:367
658 msgid ""
659 "If passphrase is entered incorrectly, your phone will conduct a factory "
660 "reset and all personal data will be deleted."
661 msgstr ""
662
663-#: qml/Shell.qml:340
664+#: qml/Shell.qml:368
665 msgid ""
666 "If passcode is entered incorrectly, your phone will conduct a factory reset "
667 "and all personal data will be deleted."
668
669=== added file 'qml/Components/Header.qml'
670--- qml/Components/Header.qml 1970-01-01 00:00:00 +0000
671+++ qml/Components/Header.qml 2014-09-25 12:44:25 +0000
672@@ -0,0 +1,27 @@
673+/*
674+ * Copyright (C) 2014 Canonical, Ltd.
675+ *
676+ * This program is free software; you can redistribute it and/or modify
677+ * it under the terms of the GNU General Public License as published by
678+ * the Free Software Foundation; version 3.
679+ *
680+ * This program is distributed in the hope that it will be useful,
681+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
682+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
683+ * GNU General Public License for more details.
684+ *
685+ * You should have received a copy of the GNU General Public License
686+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
687+ */
688+
689+import Ubuntu.Components 1.1
690+import Ubuntu.Components.Themes.Ambiance 1.1
691+
692+PageHeadStyle {
693+ id: root
694+
695+ property var styledItem: root
696+ property string title
697+ property var config: PageHeadConfiguration {}
698+ property var contents: null
699+}
700
701=== modified file 'qml/Panel/Indicators.qml'
702--- qml/Panel/Indicators.qml 2014-07-23 23:41:38 +0000
703+++ qml/Panel/Indicators.qml 2014-09-25 12:44:25 +0000
704@@ -84,10 +84,6 @@
705 indicators.state = "locked";
706 }
707 }
708-
709- if (enableRelease && revealProgress === 0) {
710- menuContent.releaseContent();
711- }
712 }
713
714 function calculateCurrentItem(xValue, useBuffer) {
715@@ -189,8 +185,7 @@
716 }
717 indicatorsModel: visibleIndicators.model
718 visible: indicators.partiallyOpened || indicators.fullyOpened
719- clip: !indicators.fullyOpened
720- activeHeader: indicators.state == "hint" || indicators.state == "reveal"
721+ clip: indicators.partiallyOpened
722 enabled: contentEnabled
723
724 //small shadow gradient at bottom of menu
725@@ -212,7 +207,7 @@
726 Rectangle {
727 id: handle
728
729- color: menuContent.backgroundColor
730+ color: menuContent.color
731
732 anchors {
733 left: parent.left
734@@ -358,12 +353,6 @@
735 maxTotalDragDistance: openedHeight - panelHeight
736 distanceThreshold: panelHeight
737
738- onStatusChanged: {
739- if (status === DirectionalDragArea.Recognized) {
740- menuContent.activateContent();
741- }
742- }
743-
744 onTapped: showTapped(Qt.point(touchSceneX, touchSceneY));
745 }
746
747
748=== modified file 'qml/Panel/Indicators/DefaultIndicatorPage.qml'
749--- qml/Panel/Indicators/DefaultIndicatorPage.qml 2014-07-30 20:50:34 +0000
750+++ qml/Panel/Indicators/DefaultIndicatorPage.qml 2014-09-25 12:44:25 +0000
751@@ -26,14 +26,12 @@
752 id: main
753
754 //const
755- property bool contentActive: false
756 property string title: rootActionState.title
757- property alias emptyText: emptyLabel.text
758 property alias highlightFollowsCurrentItem : mainMenu.highlightFollowsCurrentItem
759
760 Indicators.UnityMenuModelStack {
761 id: menuStack
762- head: contentActive ? main.menuModel : null
763+ head: main.menuModel
764
765 property var rootMenu: null
766
767@@ -88,11 +86,13 @@
768 }
769 }
770
771- // Ensure all delegates are cached in order to improve smoothness of scrolling
772- cacheBuffer: 10000
773+ // Don't load all the delegates (only max of 3 pages worth -1/0/+1)
774+ cacheBuffer: Math.max(height * 3, units.gu(70))
775
776 // Only allow flicking if the content doesn't fit on the page
777 interactive: contentHeight > height
778+ // FIXME - https://bugreports.qt-project.org/browse/QTBUG-41207
779+ boundsBehavior: Flickable.StopAtBounds
780
781 property int selectedIndex: -1
782 property bool blockCurrentIndexChange: false
783@@ -125,17 +125,12 @@
784 delegate: Loader {
785 id: loader
786 objectName: "menuItem" + index
787- asynchronous: false
788+ asynchronous: true
789+ width: ListView.view.width
790 visible: status == Loader.Ready
791
792 property int modelIndex: index
793-
794- anchors {
795- left: parent.left
796- right: parent.right
797- }
798-
799- sourceComponent: factory.load(model)
800+ sourceComponent: factory.load(model, identifier)
801
802 onLoaded: {
803 if (item.hasOwnProperty("selected")) {
804@@ -180,44 +175,8 @@
805 menuModel: mainMenu.model ? mainMenu.model : null
806 }
807
808- Components.Label {
809- id: emptyLabel
810- objectName: "emptyLabel"
811- visible: mainMenu.count == 0
812- anchors {
813- top: parent.top
814- left: parent.left
815- right: parent.right
816- topMargin: units.gu(2)
817- }
818- wrapMode: Text.WordWrap
819- horizontalAlignment: Text.AlignHCenter
820-
821- //style
822- color: "#e8e1d0"
823- fontSize: "medium"
824-
825- text: "Empty!"
826- }
827-
828- function start()
829- {
830- reset()
831- if (!contentActive) {
832- contentActive = true;
833- }
834- }
835-
836- function stop()
837- {
838- if (contentActive) {
839- contentActive = false;
840- }
841- }
842-
843 function reset()
844 {
845- mainMenu.selectedIndex = -1;
846 mainMenu.positionViewAtBeginning();
847 }
848 }
849
850=== modified file 'qml/Panel/Indicators/IndicatorDelegate.qml'
851--- qml/Panel/Indicators/IndicatorDelegate.qml 2014-06-26 10:00:41 +0000
852+++ qml/Panel/Indicators/IndicatorDelegate.qml 2014-09-25 12:44:25 +0000
853@@ -20,14 +20,6 @@
854 import QtQuick 2.0
855
856 IndicatorBase {
857- enabled: false
858-
859- onRootActionStateChanged: {
860- if (rootActionState == undefined) {
861- enabled = false;
862- return;
863- }
864-
865- enabled = rootActionState.visible;
866- }
867+ enabled: rootActionState.visible
868+ property string title: rootActionState.title
869 }
870
871=== modified file 'qml/Panel/Indicators/MenuItemFactory.qml'
872--- qml/Panel/Indicators/MenuItemFactory.qml 2014-07-30 21:40:40 +0000
873+++ qml/Panel/Indicators/MenuItemFactory.qml 2014-09-25 12:44:25 +0000
874@@ -19,11 +19,10 @@
875
876 import QtQuick 2.0
877 import Ubuntu.Settings.Menus 0.1 as Menus
878-import Ubuntu.Settings.Components 0.1 as SettingsComponents
879 import QMenuModel 0.1
880 import Utils 0.1 as Utils
881 import Ubuntu.Components.ListItems 0.1 as ListItems
882-import Ubuntu.Components 0.1
883+import Ubuntu.Components 1.1
884
885 Item {
886 id: menuFactory
887@@ -32,32 +31,38 @@
888 property var menuModel: null
889
890 property var _map: {
891- "unity.widgets.systemsettings.tablet.volumecontrol" : sliderMenu,
892- "unity.widgets.systemsettings.tablet.switch" : switchMenu,
893-
894- "com.canonical.indicator.button" : buttonMenu,
895- "com.canonical.indicator.div" : separatorMenu,
896- "com.canonical.indicator.section" : sectionMenu,
897- "com.canonical.indicator.progress" : progressMenu,
898- "com.canonical.indicator.slider" : sliderMenu,
899- "com.canonical.indicator.switch" : switchMenu,
900- "com.canonical.indicator.alarm" : alarmMenu,
901- "com.canonical.indicator.appointment" : appointmentMenu,
902- "com.canonical.indicator.transfer" : transferMenu,
903- "com.canonical.indicator.button-section" : buttonSectionMenu,
904-
905- "com.canonical.indicator.messages.messageitem" : messageItem,
906- "com.canonical.indicator.messages.sourceitem" : groupedMessage,
907-
908- "com.canonical.unity.slider" : sliderMenu,
909- "com.canonical.unity.switch" : switchMenu,
910-
911- "com.canonical.unity.media-player" : mediaPayerMenu,
912- "com.canonical.unity.playback-item" : playbackItemMenu,
913-
914- "unity.widgets.systemsettings.tablet.wifisection" : wifiSection,
915- "unity.widgets.systemsettings.tablet.accesspoint" : accessPoint,
916- "com.canonical.indicator.network.modeminfoitem" : modeminfoitem,
917+ "default": {
918+ "unity.widgets.systemsettings.tablet.volumecontrol" : sliderMenu,
919+ "unity.widgets.systemsettings.tablet.switch" : switchMenu,
920+
921+ "com.canonical.indicator.button" : buttonMenu,
922+ "com.canonical.indicator.div" : separatorMenu,
923+ "com.canonical.indicator.section" : sectionMenu,
924+ "com.canonical.indicator.progress" : progressMenu,
925+ "com.canonical.indicator.slider" : sliderMenu,
926+ "com.canonical.indicator.switch" : switchMenu,
927+ "com.canonical.indicator.alarm" : alarmMenu,
928+ "com.canonical.indicator.appointment" : appointmentMenu,
929+ "com.canonical.indicator.transfer" : transferMenu,
930+ "com.canonical.indicator.button-section" : buttonSectionMenu,
931+ "com.canonical.indicator.link" : linkMenu,
932+
933+ "com.canonical.indicator.messages.messageitem" : messageItem,
934+ "com.canonical.indicator.messages.sourceitem" : groupedMessage,
935+
936+ "com.canonical.unity.slider" : sliderMenu,
937+ "com.canonical.unity.switch" : switchMenu,
938+
939+ "com.canonical.unity.media-player" : mediaPayerMenu,
940+ "com.canonical.unity.playback-item" : playbackItemMenu,
941+
942+ "unity.widgets.systemsettings.tablet.wifisection" : wifiSection,
943+ "unity.widgets.systemsettings.tablet.accesspoint" : accessPoint,
944+ "com.canonical.indicator.network.modeminfoitem" : modeminfoitem,
945+ },
946+ "indicator-messages" : {
947+ "com.canonical.indicator.button" : messagesButtonMenu
948+ }
949 }
950
951 function getExtendedProperty(object, propertyName, defaultValue) {
952@@ -100,6 +105,7 @@
953 return maximum;
954 }
955 enabled: menuData && menuData.sensitive || false
956+ highlightWhenPressed: false
957
958 onMenuModelChanged: {
959 loadAttributes();
960@@ -138,12 +144,43 @@
961
962 buttonText: menuData && menuData.label || ""
963 enabled: menuData && menuData.sensitive || false
964+ highlightWhenPressed: false
965
966 onTriggered: {
967 menuModel.activate(menuIndex);
968 }
969 }
970 }
971+
972+ Component {
973+ id: messagesButtonMenu;
974+
975+ Item {
976+ objectName: "messagesButtonMenu"
977+ property QtObject menuData: null
978+ property var menuModel: menuFactory.menuModel
979+ property int menuIndex: -1
980+
981+ implicitHeight: units.gu(5)
982+ enabled: menuData && menuData.sensitive || false
983+
984+ Label {
985+ id: buttonMenuLabel
986+ text: menuData && menuData.label || ""
987+ anchors.centerIn: parent
988+ font.bold: true
989+ }
990+
991+ MouseArea {
992+ anchors {
993+ fill: buttonMenuLabel
994+ margins: units.gu(-1)
995+ }
996+ onClicked: menuModel.activate(menuIndex);
997+ }
998+ }
999+ }
1000+
1001 Component {
1002 id: sectionMenu;
1003
1004@@ -169,6 +206,7 @@
1005 iconSource: menuData && menuData.icon || ""
1006 value : menuData && menuData.actionState || 0.0
1007 enabled: menuData && menuData.sensitive || false
1008+ highlightWhenPressed: false
1009 }
1010 }
1011
1012@@ -183,9 +221,57 @@
1013 text: menuData && menuData.label || ""
1014 iconSource: menuData && menuData.icon || ""
1015 enabled: menuData && menuData.sensitive || false
1016-
1017- onTriggered: {
1018- menuModel.activate(menuIndex);
1019+ highlightWhenPressed: false
1020+
1021+ onTriggered: {
1022+ menuModel.activate(menuIndex);
1023+ }
1024+
1025+ // FIXME : At the moment, the indicators aren't using
1026+ // com.canonical.indicators.link for settings menu. Need to fudge it.
1027+ property bool settingsMenu: menuData && menuData.action.indexOf("settings") > -1 || false
1028+ backColor: settingsMenu ? Qt.rgba(1,1,1,0.07) : "transparent"
1029+ component: settingsMenu ? buttonForSettings : undefined
1030+ Component {
1031+ id: buttonForSettings
1032+ Icon {
1033+ name: "settings"
1034+ height: units.gu(3)
1035+ width: height
1036+ color: Theme.palette.selected.backgroundText
1037+ }
1038+ }
1039+ }
1040+ }
1041+
1042+ Component {
1043+ id: linkMenu;
1044+
1045+ Menus.StandardMenu {
1046+ objectName: "linkMenu"
1047+ property QtObject menuData: null
1048+ property int menuIndex: -1
1049+
1050+ text: menuData && menuData.label || ""
1051+ iconSource: menuData && menuData.icon || ""
1052+ enabled: menuData && menuData.sensitive || false
1053+ highlightWhenPressed: false
1054+
1055+ onTriggered: {
1056+ menuModel.activate(menuIndex);
1057+ }
1058+
1059+ backColor: Qt.rgba(1,1,1,0.07)
1060+
1061+ component: menuData.icon ? icon : undefined
1062+ Component {
1063+ id: icon
1064+ Icon {
1065+ source: menuData.icon
1066+ height: units.gu(3)
1067+ width: height
1068+ color: Theme.palette.selected.backgroundText
1069+ }
1070 }
1071 }
1072 }
1073@@ -201,6 +287,7 @@
1074 text: menuData && menuData.label || ""
1075 enabled: menuData && menuData.sensitive || false
1076 checked: menuData && menuData.isToggled || false
1077+ highlightWhenPressed: false
1078
1079 onTriggered: {
1080 menuModel.activate(menuIndex);
1081@@ -208,7 +295,6 @@
1082 }
1083 }
1084
1085-
1086 Component {
1087 id: switchMenu;
1088
1089@@ -221,6 +307,7 @@
1090 iconSource: menuData && menuData.icon || ""
1091 enabled: menuData && menuData.sensitive || false
1092 checked: menuData && menuData.isToggled || false
1093+ highlightWhenPressed: false
1094
1095 onTriggered: {
1096 menuModel.activate(menuIndex);
1097@@ -247,6 +334,7 @@
1098 iconSource: menuData && menuData.icon || "image://theme/alarm-clock"
1099 time: timeFormatter.timeString
1100 enabled: menuData && menuData.sensitive || false
1101+ highlightWhenPressed: false
1102
1103 onMenuModelChanged: {
1104 loadAttributes();
1105@@ -286,6 +374,7 @@
1106 time: timeFormatter.timeString
1107 eventColor: getExtendedProperty(extendedData, "xCanonicalColor", Qt.rgba(0.0, 0.0, 0.0, 0.0))
1108 enabled: menuData && menuData.sensitive || false
1109+ highlightWhenPressed: false
1110
1111 onMenuModelChanged: {
1112 loadAttributes();
1113@@ -351,10 +440,11 @@
1114
1115 text: menuData && menuData.label || ""
1116 enabled: menuData && menuData.sensitive || false
1117- checked: menuData && menuData.isToggled || false
1118+ active: menuData && menuData.isToggled || false
1119 secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
1120 adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
1121 signalStrength: strengthAction.valid ? strengthAction.state : 0
1122+ highlightWhenPressed: false
1123
1124 onMenuModelChanged: {
1125 loadAttributes();
1126@@ -383,6 +473,7 @@
1127 property var menuModel: menuFactory.menuModel
1128 property int menuIndex: -1
1129 property var extendedData: menuData && menuData.ext || undefined
1130+ highlightWhenPressed: false
1131
1132 property var statusLabelAction: UnityMenuAction {
1133 model: menuModel
1134@@ -468,9 +559,10 @@
1135 property var extendedData: menuData && menuData.ext || undefined
1136
1137 text: menuData && menuData.label || ""
1138- iconSource: getExtendedProperty(extendedData, "icon", "qrc:/indicators/artwork/messaging/default_app.svg")
1139+ iconSource: getExtendedProperty(extendedData, "icon", "image://theme/message")
1140 count: menuData && menuData.actionState.length > 0 ? menuData.actionState[0] : "0"
1141 enabled: menuData && menuData.sensitive || false
1142+ highlightWhenPressed: false
1143 removable: true
1144
1145 onMenuModelChanged: {
1146@@ -502,17 +594,20 @@
1147 property var menuModel: menuFactory.menuModel
1148 property int menuIndex: -1
1149 property var actionState: menuData && menuData.actionState || undefined
1150-
1151- playerIcon: menuData && menuData.icon || ""
1152- playerName: menuData && menuData.label || ""
1153-
1154- albumArt: getExtendedProperty(actionState, "art-url", "")
1155- song: getExtendedProperty(actionState, "title", "unknown")
1156- artist: getExtendedProperty(actionState, "artist", "unknown")
1157- album: getExtendedProperty(actionState, "album", "unknown")
1158- running: getExtendedProperty(actionState, "running", false)
1159+ property bool running: getExtendedProperty(actionState, "running", false)
1160+
1161+ playerIcon: menuData && menuData.icon || "image://theme/stock_music"
1162+ playerName: menuData && menuData.label || i18n.tr("Nothing is playing")
1163+
1164+ albumArt: getExtendedProperty(actionState, "art-url", "image://theme/stock_music")
1165+ song: getExtendedProperty(actionState, "title", "")
1166+ artist: getExtendedProperty(actionState, "artist", "")
1167+ album: getExtendedProperty(actionState, "album", "")
1168+ showTrack: running && (state == "Playing" || state == "Paused")
1169 state: getExtendedProperty(actionState, "state", "")
1170 enabled: menuData && menuData.sensitive || false
1171+ highlightWhenPressed: false
1172+ showDivider: false
1173
1174 onTriggered: {
1175 model.activate(modelIndex);
1176@@ -551,6 +646,7 @@
1177 canGoNext: nextAction.valid
1178 canGoPrevious: previousAction.valid
1179 enabled: menuData && menuData.sensitive || false
1180+ highlightWhenPressed: false
1181
1182 onPlay: {
1183 playAction.activate();
1184@@ -590,9 +686,10 @@
1185 property var uid: getExtendedProperty(extendedData, "xCanonicalUid", undefined)
1186
1187 text: menuData && menuData.label || ""
1188- iconSource: menuData && menuData.icon || ""
1189+ iconSource: menuData && menuData.icon || "image://theme/transfer-none"
1190 maximum: 1.0
1191 enabled: menuData && menuData.sensitive || false
1192+ highlightWhenPressed: false
1193 removable: true
1194 confirmRemoval: true
1195
1196@@ -688,7 +785,7 @@
1197 Component {
1198 id: buttonSectionMenu;
1199
1200- ListItems.Standard {
1201+ Menus.StandardMenu {
1202 objectName: "buttonSectionMenu"
1203 property QtObject menuData: null
1204 property var menuModel: menuFactory.menuModel
1205@@ -697,8 +794,9 @@
1206
1207 iconSource: menuData && menuData.icon || ""
1208 enabled: menuData && menuData.sensitive || false
1209+ highlightWhenPressed: false
1210 text: menuData && menuData.label || ""
1211- showDivider: false
1212+ foregroundColor: Theme.palette.normal.backgroundText
1213
1214 onMenuModelChanged: {
1215 loadAttributes();
1216@@ -711,22 +809,35 @@
1217 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-extra-label': 'string'});
1218 }
1219
1220- control: Button {
1221- text: getExtendedProperty(extendedData, "xCanonicalExtraLabel", "")
1222+ component: Component {
1223+ Button {
1224+ objectName: "buttonSectionMenuControl"
1225+ text: getExtendedProperty(extendedData, "xCanonicalExtraLabel", "")
1226
1227- onClicked: {
1228- menuModel.activate(menuIndex);
1229+ onClicked: {
1230+ menuModel.activate(menuIndex);
1231+ }
1232 }
1233 }
1234 }
1235 }
1236
1237- function load(modelData) {
1238+ function load(modelData, context) {
1239 if (modelData.type !== undefined) {
1240- var component = _map[modelData.type];
1241+ var component = undefined;
1242+
1243+ var contextComponents = _map[context];
1244+ if (contextComponents !== undefined) {
1245+ component = contextComponents[modelData.type];
1246+ }
1247+
1248+ if (component === undefined) {
1249+ component = _map["default"][modelData.type];
1250+ }
1251 if (component !== undefined) {
1252 return component;
1253 }
1254+ console.debug("Don't know how to make " + modelData.type + " for " + context);
1255 }
1256 if (modelData.isCheck || modelData.isRadio) {
1257 return checkableMenu;
1258
1259=== modified file 'qml/Panel/Indicators/MessageMenuItemFactory.qml'
1260--- qml/Panel/Indicators/MessageMenuItemFactory.qml 2014-07-10 13:36:41 +0000
1261+++ qml/Panel/Indicators/MessageMenuItemFactory.qml 2014-09-25 12:44:25 +0000
1262@@ -24,8 +24,9 @@
1263 import QMenuModel 0.1 as QMenuModel
1264 import Utils 0.1 as Utils
1265
1266-Item {
1267+Loader {
1268 id: messageFactoryItem
1269+ objectName: "messageItem"
1270 property var menuModel: null
1271 property QtObject menuData: null
1272 property int menuIndex: -1
1273@@ -38,9 +39,8 @@
1274 property var actionsDescription: getExtendedProperty(extendedData, "xCanonicalMessageActions", undefined)
1275
1276 // TODO - bug #1260728
1277- property var timeFormatter: Utils.TimeFormatter {
1278- time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
1279- format: "hh:mm - MMM dd"
1280+ property var timeFormatter: Utils.RelativeTimeFormatter {
1281+ time: getExtendedProperty(extendedData, "xCanonicalTime", 0) / 1000000
1282 }
1283
1284 onMenuModelChanged: {
1285@@ -50,182 +50,7 @@
1286 loadAttributes();
1287 }
1288
1289- function loadAttributes() {
1290- if (!menuModel || menuIndex == -1) return;
1291- menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64',
1292- 'x-canonical-text': 'string',
1293- 'x-canonical-message-actions': 'variant',
1294- 'icon': 'icon',
1295- 'x-canonical-app-icon': 'icon'});
1296- }
1297-
1298- function getExtendedProperty(object, propertyName, defaultValue) {
1299- if (object && object.hasOwnProperty(propertyName)) {
1300- return object[propertyName];
1301- }
1302- return defaultValue;
1303- }
1304-
1305- implicitHeight: contents.status == Loader.Ready ? contents.item.implicitHeight : 0
1306-
1307- Loader {
1308- id: contents
1309- objectName: "loader"
1310- anchors.fill: parent
1311-
1312- sourceComponent: loadMessage(actionsDescription);
1313-
1314- Component {
1315- id: simpleTextMessage
1316-
1317- Menus.SimpleTextMessageMenu {
1318- id: message
1319- objectName: "simpleTextMessage"
1320- // text
1321- title: menuData && menuData.label || ""
1322- time: timeFormatter.timeString
1323- message: getExtendedProperty(extendedData, "xCanonicalText", "")
1324- // icons
1325- avatar: getExtendedProperty(extendedData, "icon", "qrc:/indicators/artwork/messaging/default_contact.png")
1326- appIcon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "qrc:/indicators/artwork/messaging/default_app.svg")
1327- // actions
1328- enabled: menuData && menuData.sensitive || false
1329- removable: !selected
1330- selected: messageFactoryItem.selected
1331-
1332- onAppActivated: {
1333- menuModel.activate(menuIndex, true);
1334- }
1335- onDismissed: {
1336- menuModel.activate(menuIndex, false);
1337- }
1338- onClicked: {
1339- if (selected) {
1340- menuDeselected();
1341- } else {
1342- menuSelected();
1343- }
1344- }
1345-
1346- backgroundIndicator: RemoveBackground {
1347- state: message.swipingState
1348- }
1349- }
1350- }
1351-
1352- Component {
1353- id: textMessage
1354-
1355- Menus.TextMessageMenu {
1356- id: message
1357- objectName: "textMessage"
1358- property var replyActionDescription: actionsDescription && actionsDescription.length > 0 ? actionsDescription[0] : undefined
1359-
1360- property var replyAction: QMenuModel.UnityMenuAction {
1361- model: menuModel
1362- index: menuIndex
1363- name: getExtendedProperty(replyActionDescription, "name", "")
1364- }
1365-
1366- // text
1367- title: menuData && menuData.label || ""
1368- time: timeFormatter.timeString
1369- message: getExtendedProperty(extendedData, "xCanonicalText", "")
1370- replyButtonText: getExtendedProperty(replyActionDescription, "label", "Send")
1371- // icons
1372- avatar: getExtendedProperty(extendedData, "icon", "qrc:/indicators/artwork/messaging/default_contact.png")
1373- appIcon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "qrc:/indicators/artwork/messaging/default_app.svg")
1374- // actions
1375- replyEnabled: replyAction.valid && replyAction.enabled
1376- enabled: menuData && menuData.sensitive || false
1377- removable: !selected
1378- selected: messageFactoryItem.selected
1379-
1380- onAppActivated: {
1381- menuModel.activate(menuIndex, true);
1382- }
1383- onDismissed: {
1384- menuModel.activate(menuIndex, false);
1385- }
1386- onReplied: {
1387- replyAction.activate(value);
1388- }
1389- onClicked: {
1390- if (selected) {
1391- menuDeselected();
1392- } else {
1393- menuSelected();
1394- }
1395- }
1396-
1397- backgroundIndicator: RemoveBackground {
1398- state: message.swipingState
1399- }
1400- }
1401- }
1402- Component {
1403- id: snapDecision
1404-
1405- Menus.SnapDecisionMenu {
1406- id: message
1407- objectName: "snapDecision"
1408- property var activateActionDescription: actionsDescription && actionsDescription.length > 0 ? actionsDescription[0] : undefined
1409- property var replyActionDescription: actionsDescription && actionsDescription.length > 1 ? actionsDescription[1] : undefined
1410-
1411- property var activateAction: QMenuModel.UnityMenuAction {
1412- model: menuModel
1413- index: menuIndex
1414- name: getExtendedProperty(activateActionDescription, "name", "")
1415- }
1416- property var replyAction: QMenuModel.UnityMenuAction {
1417- model: menuModel
1418- index: menuIndex
1419- name: getExtendedProperty(replyActionDescription, "name", "")
1420- }
1421-
1422- // text
1423- title: menuData && menuData.label || ""
1424- time: timeFormatter.timeString
1425- message: getExtendedProperty(extendedData, "xCanonicalText", "")
1426- actionButtonText: getExtendedProperty(activateActionDescription, "label", "Call back")
1427- replyButtonText: getExtendedProperty(replyActionDescription, "label", "Send")
1428- replyMessages: getExtendedProperty(replyActionDescription, "parameter-hint", "")
1429- // icons
1430- avatar: getExtendedProperty(extendedData, "icon", "qrc:/indicators/artwork/messaging/default_contact.png")
1431- appIcon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "qrc:/indicators/artwork/messaging/default_app.svg")
1432- // actions
1433- activateEnabled: activateAction.valid && activateAction.enabled
1434- replyEnabled: replyAction.valid && replyAction.enabled
1435- enabled: menuData && menuData.sensitive || false
1436- removable: !selected
1437- selected: messageFactoryItem.selected
1438-
1439- onAppActivated: {
1440- menuModel.activate(menuIndex, true);
1441- }
1442- onDismissed: {
1443- menuModel.activate(menuIndex, false);
1444- }
1445- onActivated: {
1446- activateAction.activate();
1447- }
1448- onReplied: {
1449- replyAction.activate(value);
1450- }
1451- onClicked: {
1452- if (selected) {
1453- menuDeselected();
1454- } else {
1455- menuSelected();
1456- }
1457- }
1458-
1459- backgroundIndicator: RemoveBackground {
1460- state: message.swipingState
1461- }
1462- }
1463- }
1464- }
1465+ sourceComponent: loadMessage(actionsDescription)
1466
1467 function loadMessage(actions)
1468 {
1469@@ -240,7 +65,7 @@
1470 }
1471
1472 if (parameterType === "") {
1473- return simpleTextMessage;
1474+ return simpleMessage;
1475 } else if (parameterType === "s") {
1476 return textMessage;
1477 } else if (parameterType === "_s") {
1478@@ -250,4 +75,164 @@
1479 }
1480 return undefined;
1481 }
1482+
1483+ function loadAttributes() {
1484+ if (!menuModel || menuIndex == -1) return;
1485+ menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64',
1486+ 'x-canonical-text': 'string',
1487+ 'x-canonical-message-actions': 'variant',
1488+ 'icon': 'icon',
1489+ 'x-canonical-app-icon': 'icon'});
1490+ }
1491+
1492+ function getExtendedProperty(object, propertyName, defaultValue) {
1493+ if (object && object.hasOwnProperty(propertyName)) {
1494+ return object[propertyName];
1495+ }
1496+ return defaultValue;
1497+ }
1498+
1499+ Component {
1500+ id: simpleMessage
1501+
1502+ Menus.SimpleMessageMenu {
1503+ id: message
1504+ objectName: "simpleTextMessage"
1505+ // text
1506+ title: menuData && menuData.label || ""
1507+ time: timeFormatter.timeString
1508+ body: getExtendedProperty(extendedData, "xCanonicalText", "")
1509+ // icons
1510+ avatar: getExtendedProperty(extendedData, "icon", "image://theme/contact")
1511+ icon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "image://theme/message")
1512+ // actions
1513+ enabled: menuData && menuData.sensitive || false
1514+ removable: !selected
1515+ confirmRemoval: true
1516+ selected: messageFactoryItem.selected
1517+
1518+ onIconActivated: {
1519+ menuModel.activate(menuIndex, true);
1520+ }
1521+ onDismissed: {
1522+ menuModel.activate(menuIndex, false);
1523+ }
1524+ onTriggered: {
1525+ if (selected) {
1526+ menuDeselected();
1527+ } else {
1528+ menuSelected();
1529+ }
1530+ }
1531+ }
1532+ }
1533+
1534+ Component {
1535+ id: textMessage
1536+
1537+ Menus.TextMessageMenu {
1538+ id: message
1539+ objectName: "textMessage"
1540+ property var replyActionDescription: actionsDescription && actionsDescription.length > 0 ? actionsDescription[0] : undefined
1541+
1542+ property var replyAction: QMenuModel.UnityMenuAction {
1543+ model: menuModel
1544+ index: menuIndex
1545+ name: getExtendedProperty(replyActionDescription, "name", "")
1546+ }
1547+
1548+ // text
1549+ title: menuData && menuData.label || ""
1550+ time: timeFormatter.timeString
1551+ body: getExtendedProperty(extendedData, "xCanonicalText", "")
1552+ replyButtonText: getExtendedProperty(replyActionDescription, "label", "Send")
1553+ // icons
1554+ avatar: getExtendedProperty(extendedData, "icon", "image://theme/contact")
1555+ icon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "image://theme/message")
1556+ // actions
1557+ replyEnabled: replyAction.valid && replyAction.enabled
1558+ enabled: menuData && menuData.sensitive || false
1559+ removable: !selected
1560+ confirmRemoval: true
1561+ selected: messageFactoryItem.selected
1562+ highlightWhenPressed: false
1563+
1564+ onIconActivated: {
1565+ menuModel.activate(menuIndex, true);
1566+ }
1567+ onDismissed: {
1568+ menuModel.activate(menuIndex, false);
1569+ }
1570+ onReplied: {
1571+ replyAction.activate(value);
1572+ }
1573+ onTriggered: {
1574+ if (selected) {
1575+ menuDeselected();
1576+ } else {
1577+ menuSelected();
1578+ }
1579+ }
1580+ }
1581+ }
1582+
1583+ Component {
1584+ id: snapDecision
1585+
1586+ Menus.SnapDecisionMenu {
1587+ id: message
1588+ objectName: "snapDecision"
1589+ property var activateActionDescription: actionsDescription && actionsDescription.length > 0 ? actionsDescription[0] : undefined
1590+ property var replyActionDescription: actionsDescription && actionsDescription.length > 1 ? actionsDescription[1] : undefined
1591+
1592+ property var activateAction: QMenuModel.UnityMenuAction {
1593+ model: menuModel
1594+ index: menuIndex
1595+ name: getExtendedProperty(activateActionDescription, "name", "")
1596+ }
1597+ property var replyAction: QMenuModel.UnityMenuAction {
1598+ model: menuModel
1599+ index: menuIndex
1600+ name: getExtendedProperty(replyActionDescription, "name", "")
1601+ }
1602+
1603+ // text
1604+ title: menuData && menuData.label || ""
1605+ time: timeFormatter.timeString
1606+ body: getExtendedProperty(extendedData, "xCanonicalText", "")
1607+ actionButtonText: getExtendedProperty(activateActionDescription, "label", "Call back")
1608+ replyButtonText: getExtendedProperty(replyActionDescription, "label", "Send")
1609+ // icons
1610+ avatar: getExtendedProperty(extendedData, "icon", "image://theme/contact")
1611+ icon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "image://theme/missed-call")
1612+ // actions
1613+ actionEnabled: activateAction.valid && activateAction.enabled
1614+ replyEnabled: replyAction.valid && replyAction.enabled
1615+ enabled: menuData && menuData.sensitive || false
1616+ removable: !selected
1617+ confirmRemoval: true
1618+ selected: messageFactoryItem.selected
1619+ highlightWhenPressed: false
1620+
1621+ onIconActivated: {
1622+ menuModel.activate(menuIndex, true);
1623+ }
1624+ onDismissed: {
1625+ menuModel.activate(menuIndex, false);
1626+ }
1627+ onActionActivated: {
1628+ activateAction.activate();
1629+ }
1630+ onReplied: {
1631+ replyAction.activate(value);
1632+ }
1633+ onTriggered: {
1634+ if (selected) {
1635+ menuDeselected();
1636+ } else {
1637+ menuSelected();
1638+ }
1639+ }
1640+ }
1641+ }
1642 }
1643
1644=== removed file 'qml/Panel/Indicators/RemoveBackground.qml'
1645--- qml/Panel/Indicators/RemoveBackground.qml 2014-06-20 15:13:17 +0000
1646+++ qml/Panel/Indicators/RemoveBackground.qml 1970-01-01 00:00:00 +0000
1647@@ -1,55 +0,0 @@
1648-/*
1649- * Copyright 2013 Canonical Ltd.
1650- *
1651- * This program is free software; you can redistribute it and/or modify
1652- * it under the terms of the GNU Lesser General Public License as published by
1653- * the Free Software Foundation; version 3.
1654- *
1655- * This program is distributed in the hope that it will be useful,
1656- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1657- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1658- * GNU Lesser General Public License for more details.
1659- *
1660- * You should have received a copy of the GNU Lesser General Public License
1661- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1662- */
1663-
1664-import QtQuick 2.0
1665-import Ubuntu.Components 0.1
1666-
1667-Rectangle {
1668- anchors.fill: parent
1669- color: "#333130"
1670- Label {
1671- id: backgroundText
1672-
1673- anchors.fill: parent
1674- verticalAlignment: Text.AlignVCenter
1675- text: "Clear"
1676- fontSize: "medium"
1677- color: "#e8e1d0"
1678- font.bold: true
1679- }
1680-
1681- states: [
1682- State {
1683- name: "SwipingRight"
1684- PropertyChanges {
1685- target: backgroundText
1686- anchors.rightMargin: units.gu(3)
1687- anchors.leftMargin: 0
1688- horizontalAlignment: Text.AlignRight
1689-
1690- }
1691- },
1692- State {
1693- name: "SwipingLeft"
1694- PropertyChanges {
1695- target: backgroundText
1696- anchors.rightMargin: 0
1697- anchors.leftMargin: units.gu(3)
1698- horizontalAlignment: Text.AlignLeft
1699- }
1700- }
1701- ]
1702-}
1703
1704=== modified file 'qml/Panel/Indicators/client/IndicatorsClient.qml'
1705--- qml/Panel/Indicators/client/IndicatorsClient.qml 2014-01-30 14:54:01 +0000
1706+++ qml/Panel/Indicators/client/IndicatorsClient.qml 2014-09-25 12:44:25 +0000
1707@@ -25,6 +25,10 @@
1708 color: "black"
1709 id: root
1710
1711+ Component.onCompleted: {
1712+ Theme.name = "Ubuntu.Components.Themes.SuruGradient"
1713+ }
1714+
1715 PageStack {
1716 id: pages
1717 anchors.fill: parent
1718
1719=== modified file 'qml/Panel/MenuContent.qml'
1720--- qml/Panel/MenuContent.qml 2014-03-05 12:52:57 +0000
1721+++ qml/Panel/MenuContent.qml 2014-09-25 12:44:25 +0000
1722@@ -15,143 +15,119 @@
1723 */
1724
1725 import QtQuick 2.0
1726-import Ubuntu.Components 0.1
1727+import QtQuick.Layouts 1.1
1728+import Ubuntu.Components 1.1
1729 import Unity.Indicators 0.1 as Indicators
1730 import Utils 0.1
1731 import "../Components"
1732+import "Indicators"
1733
1734-// FIXME : We dont want to use MainView.
1735-// Need a regular Item which can have tabs with local header.
1736-// https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1211704
1737-MainView {
1738+Rectangle {
1739 id: content
1740
1741 property QtObject indicatorsModel: null
1742- property bool __contentActive: false
1743- readonly property int currentMenuIndex: tabs.selectedTabIndex
1744- backgroundColor: "#221e1c" // FIXME not in palette yet
1745- property int contentReleaseInterval: 20000
1746- property bool activeHeader: false
1747- property real headerHeight: tabs.tabBar.height
1748+ readonly property alias currentMenuIndex: listViewHeader.currentIndex
1749+ color: "#221e1c" // FIXME not in palette yet
1750+ property real headerHeight: listViewHeader.height
1751
1752 width: units.gu(40)
1753 height: units.gu(42)
1754
1755 function setCurrentMenuIndex(index, animate) {
1756- if (tabs.selectedTabIndex !== index) {
1757- if (tabs.selectedTabIndex === -1 || !animate) {
1758- tabs.tabBar.animate = false;
1759- }
1760- tabs.selectedTabIndex = index;
1761- tabs.tabBar.animate = true;
1762- }
1763- }
1764-
1765- function activateContent() {
1766- contentReleaseTimer.stop();
1767- __contentActive = true;
1768- }
1769-
1770- function releaseContent() {
1771- if (__contentActive) {
1772- contentReleaseTimer.restart();
1773- }
1774- }
1775-
1776- onActiveHeaderChanged: {
1777- tabs.tabBar.selectionMode = activeHeader;
1778- tabs.tabBar.alwaysSelectionMode = activeHeader;
1779- }
1780-
1781- Tabs {
1782- id: tabs
1783- objectName: "tabs"
1784- anchors.fill: parent
1785-
1786- Repeater {
1787- id: repeater
1788- model: content.indicatorsModel ? content.indicatorsModel : null
1789- objectName: "tabsRepeater"
1790-
1791- // FIXME: This is needed because tabs dont handle repeaters well.
1792- // Due to the child ordering happening after child insertion.
1793- // QTBUG-32438
1794- onItemAdded: {
1795- parent.childrenChanged();
1796- }
1797-
1798- Tab {
1799- id: tab
1800- objectName: model.identifier
1801-
1802- page: Page {
1803- Loader {
1804- id: loader
1805- clip: true
1806- anchors.fill: parent
1807- source: pageSource
1808- asynchronous: true
1809-
1810- readonly property bool indexActive: index >= 0 && index < menuActivator.count && menuActivator.content[index].active
1811- readonly property bool contentActive: content.__contentActive && indexActive
1812-
1813- onContentActiveChanged: {
1814- if (contentActive && item) {
1815- item.start()
1816- } else if (!contentActive && item) {
1817- item.stop()
1818- }
1819- }
1820-
1821- onVisibleChanged: {
1822- // Reset the indicator states
1823- if (!visible && item && item["reset"]) {
1824- item.reset()
1825- }
1826- }
1827-
1828- onLoaded: {
1829- for(var pName in indicatorProperties) {
1830- if (item.hasOwnProperty(pName)) {
1831- item[pName] = indicatorProperties[pName]
1832- }
1833- }
1834- if (contentActive && tabs.visible) {
1835- item.start()
1836- }
1837- }
1838-
1839- Binding {
1840- target: tab
1841- property: "title"
1842- value: loader.item && loader.item.hasOwnProperty("title") && loader.item.title !== "" ? loader.item.title : model.identifier
1843- }
1844-
1845- Binding {
1846- target: loader.item
1847- property: "objectName"
1848- value: identifier + "-page"
1849- }
1850- }
1851- }
1852- }
1853- }
1854- }
1855-
1856- Timer {
1857- id: contentReleaseTimer
1858-
1859- interval: contentReleaseInterval
1860- onTriggered: {
1861- content.__contentActive = false;
1862- menuActivator.clear();
1863- }
1864- }
1865-
1866- Indicators.MenuContentActivator {
1867- id: menuActivator
1868- running: content.__contentActive
1869- baseIndex: content.currentMenuIndex
1870- count: indicatorsModel.count
1871+ // FIXME - https://bugreports.qt-project.org/browse/QTBUG-41229
1872+ listViewHeader.currentIndex = -1;
1873+ listViewHeader.currentIndex = index;
1874+ }
1875+
1876+ ListView {
1877+ id: listViewHeader
1878+ objectName: "indicatorsHeaderListView"
1879+ model: content.indicatorsModel
1880+ clip: true
1881+
1882+ anchors {
1883+ left: parent.left
1884+ right: parent.right
1885+ }
1886+ height: units.gu(8.5)
1887+
1888+ highlightFollowsCurrentItem: true
1889+ highlightMoveDuration: 0
1890+
1891+ orientation: ListView.Horizontal
1892+ snapMode: ListView.SnapOneItem
1893+ highlightRangeMode: ListView.StrictlyEnforceRange
1894+ boundsBehavior: Flickable.StopAtBounds
1895+ // Load all the indicator menus (a big number)
1896+ cacheBuffer: 1073741823
1897+
1898+ delegate: Header {
1899+ width: ListView.view.width
1900+ height: implicitHeight
1901+
1902+ title: indicatorDelegate.title !== "" ? indicatorDelegate.title : identifier
1903+
1904+ IndicatorDelegate {
1905+ id: indicatorDelegate
1906+ Component.onCompleted: {
1907+ for(var pName in indicatorProperties) {
1908+ if (indicatorDelegate.hasOwnProperty(pName)) {
1909+ indicatorDelegate[pName] = indicatorProperties[pName];
1910+ }
1911+ }
1912+ }
1913+ }
1914+ }
1915+ }
1916+
1917+ ListView {
1918+ id: listViewContent
1919+ objectName: "indicatorsContentListView"
1920+ anchors {
1921+ left: parent.left
1922+ right: parent.right
1923+ top: listViewHeader.bottom
1924+ bottom: parent.bottom
1925+ }
1926+ model: content.indicatorsModel
1927+ clip: true
1928+
1929+ currentIndex: listViewHeader.currentIndex
1930+ interactive: false
1931+ highlightMoveDuration: 0
1932+ orientation: ListView.Horizontal
1933+ // Load all the indicator menus (a big number)
1934+ cacheBuffer: 1073741823
1935+
1936+ delegate: Loader {
1937+ id: loader
1938+ width: ListView.view.width
1939+ height: ListView.view.height
1940+ objectName: identifier
1941+
1942+ source: pageSource
1943+ asynchronous: true
1944+
1945+ onVisibleChanged: {
1946+ // Reset the indicator states
1947+ if (!visible && item && item["reset"]) {
1948+ item.reset()
1949+ }
1950+ }
1951+
1952+ onLoaded: {
1953+ for(var pName in indicatorProperties) {
1954+ if (item.hasOwnProperty(pName)) {
1955+ item[pName] = indicatorProperties[pName]
1956+ }
1957+ }
1958+ }
1959+
1960+ Binding {
1961+ target: loader.item
1962+ property: "objectName"
1963+ value: identifier + "-page"
1964+ }
1965+ }
1966 }
1967 }
1968
1969=== modified file 'tests/mocks/Unity/Indicators/FakeMenuPage.qml'
1970--- tests/mocks/Unity/Indicators/FakeMenuPage.qml 2014-05-02 23:27:02 +0000
1971+++ tests/mocks/Unity/Indicators/FakeMenuPage.qml 2014-09-25 12:44:25 +0000
1972@@ -19,16 +19,6 @@
1973 Flickable {
1974 objectName: "fakeMenuPlugin"
1975 // Make it compatible with the PluginItem interface
1976- function start() {
1977- if (shell != undefined && shell.indicator_status != undefined) {
1978- shell.indicator_status[objectName].started = true;
1979- }
1980- }
1981- function stop() {
1982- if (shell != undefined && shell.indicator_status != undefined) {
1983- shell.indicator_status[objectName].started = false;
1984- }
1985- }
1986 function reset() {
1987 if (shell != undefined && shell.indicator_status != undefined) {
1988 shell.indicator_status[objectName].reset++;
1989
1990=== modified file 'tests/plugins/Utils/CMakeLists.txt'
1991--- tests/plugins/Utils/CMakeLists.txt 2014-09-17 14:18:59 +0000
1992+++ tests/plugins/Utils/CMakeLists.txt 2014-09-25 12:44:25 +0000
1993@@ -7,11 +7,11 @@
1994 macro(run_tests)
1995 set(_test_list "")
1996 foreach(_test ${ARGN})
1997- set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/${_test}Exec
1998+ set(testCommand env "LC_ALL=C.UTF-8" ${CMAKE_CURRENT_BINARY_DIR}/${_test}Exec
1999 -o ${CMAKE_BINARY_DIR}/${_test}.xml,xunitxml
2000 -o -,txt)
2001 add_test(NAME ${_test} COMMAND ${testCommand})
2002- add_custom_target(${_test} env "LC_ALL=C" ${testCommand})
2003+ add_custom_target(${_test} ${testCommand})
2004 add_executable(${_test}Exec ${_test}.cpp modeltest.cpp)
2005 qt5_use_modules(${_test}Exec Test Core Qml)
2006 target_link_libraries(${_test}Exec
2007
2008=== modified file 'tests/plugins/Utils/timeformattertest.cpp'
2009--- tests/plugins/Utils/timeformattertest.cpp 2014-01-10 08:47:02 +0000
2010+++ tests/plugins/Utils/timeformattertest.cpp 2014-09-25 12:44:25 +0000
2011@@ -17,6 +17,9 @@
2012 */
2013
2014 #include "timeformatter.h"
2015+#include "relativetimeformatter.h"
2016+
2017+#include <locale.h>
2018
2019 #include <QtTest>
2020 #include <QDebug>
2021@@ -24,8 +27,24 @@
2022 class TimeFormatterTest : public QObject
2023 {
2024 Q_OBJECT
2025+private:
2026+ void addTestData(QList<int> daysToAdd = QList<int>()) {
2027+ QTest::addColumn<QDateTime>("time");
2028+
2029+ Q_FOREACH(int dayToAdd, daysToAdd) {
2030+ QDateTime time = QDateTime::currentDateTime().addDays(dayToAdd);
2031+ QDateTime am(time); am.setTime(QTime(1, 1, 1));
2032+ QDateTime midday(time); midday.setTime(QTime(12, 0, 0));
2033+ QDateTime pm(time); pm.setTime(QTime(17, 59, 59));
2034+
2035+ QTest::newRow(QString("%1day-am").arg(dayToAdd).toLatin1()) << am;
2036+ QTest::newRow(QString("%1day-midday").arg(dayToAdd).toLatin1()) << midday;
2037+ QTest::newRow(QString("%1day-pm").arg(dayToAdd).toLatin1()) << pm;
2038+ }
2039+
2040+ }
2041+
2042 private Q_SLOTS:
2043-
2044 void initTestCase()
2045 {
2046 setenv("UNITY_TEST_ENV", "1", 1);
2047@@ -36,12 +55,12 @@
2048 unsetenv("UNITY_TEST_ENV");
2049 }
2050
2051- void testFormat()
2052+ void testTimeFormatter_Format_data() { addTestData(QList<int>() << 0); }
2053+ void testTimeFormatter_Format()
2054 {
2055+ QFETCH(QDateTime, time);
2056 const QString format = "hh:mm dd.MM.yy";
2057
2058- QDateTime time = QDateTime::currentDateTime();
2059-
2060 TimeFormatter formatter;
2061 formatter.setTime(time.toMSecsSinceEpoch() * 1000);
2062 formatter.setFormat(format);
2063@@ -49,18 +68,96 @@
2064 QCOMPARE(formatter.timeString(), time.toString(format));
2065 }
2066
2067- void testFormatStrF()
2068+ void tesGDatetTimeFormatter_Format_data() { addTestData(QList<int>() << 0); }
2069+ void tesGDatetTimeFormatter_Format()
2070 {
2071+ QFETCH(QDateTime, time);
2072 const QString format = "%d-%m-%Y %I:%M%p";
2073
2074- QDateTime time = QDateTime::currentDateTime();
2075-
2076 GDateTimeFormatter formatter;
2077 formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
2078 formatter.setFormat(format);
2079
2080 QCOMPARE(formatter.timeString(), time.toString("dd-MM-yyyy hh:mmAP"));
2081 }
2082+
2083+ void tesRelativeTimeFormatter_FarBack_data() { addTestData(QList<int>() << -200 << -20 << -7); }
2084+ void tesRelativeTimeFormatter_FarBack()
2085+ {
2086+ QFETCH(QDateTime, time);
2087+
2088+ RelativeTimeFormatter formatter;
2089+ formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
2090+
2091+ QCOMPARE(formatter.timeString(), time.toString("ddd dd MMM\u2003HH:mm"));
2092+ }
2093+
2094+ void tesRelativeTimeFormatter_WeekBack_data() { addTestData(QList<int>() << -6 << -2); }
2095+ void tesRelativeTimeFormatter_WeekBack()
2096+ {
2097+ QFETCH(QDateTime, time);
2098+
2099+ RelativeTimeFormatter formatter;
2100+ formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
2101+
2102+ QCOMPARE(formatter.timeString(), time.toString("ddd\u2003HH:mm"));
2103+ }
2104+
2105+ void tesRelativeTimeFormatter_Yesterday_data() { addTestData(QList<int>() << -1); }
2106+ void tesRelativeTimeFormatter_Yesterday()
2107+ {
2108+ QFETCH(QDateTime, time);
2109+
2110+ RelativeTimeFormatter formatter;
2111+ formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
2112+
2113+ QCOMPARE(formatter.timeString(), QString("Yesterday\u2003%1").arg(time.toString("HH:mm")));
2114+ }
2115+
2116+ void tesRelativeTimeFormatter_Today_data() { addTestData(QList<int>() << 0); }
2117+ void tesRelativeTimeFormatter_Today()
2118+ {
2119+ QFETCH(QDateTime, time);
2120+
2121+ RelativeTimeFormatter formatter;
2122+ formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
2123+
2124+ QCOMPARE(formatter.timeString(), time.toString("HH:mm"));
2125+ }
2126+
2127+ void tesRelativeTimeFormatter_Tomorrow_data() { addTestData(QList<int>() << 1); }
2128+ void tesRelativeTimeFormatter_Tomorrow()
2129+ {
2130+ QFETCH(QDateTime, time);
2131+
2132+ RelativeTimeFormatter formatter;
2133+ formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
2134+
2135+ QCOMPARE(formatter.timeString(), QString("Tomorrow\u2003%1").arg(time.toString("HH:mm")));
2136+ }
2137+
2138+
2139+ void tesRelativeTimeFormatter_WeekForward_data() { addTestData(QList<int>() << 2 << 6); }
2140+ void tesRelativeTimeFormatter_WeekForward()
2141+ {
2142+ QFETCH(QDateTime, time);
2143+
2144+ RelativeTimeFormatter formatter;
2145+ formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
2146+
2147+ QCOMPARE(formatter.timeString(), time.toString("ddd\u2003HH:mm"));
2148+ }
2149+
2150+ void tesRelativeTimeFormatter_FarForward_data() { addTestData(QList<int>() << 7 << 20 << 200); }
2151+ void tesRelativeTimeFormatter_FarForward()
2152+ {
2153+ QFETCH(QDateTime, time);
2154+
2155+ RelativeTimeFormatter formatter;
2156+ formatter.setTime(time.toMSecsSinceEpoch() / 1000); // strftime in seconds since epoc
2157+
2158+ QCOMPARE(formatter.timeString(), time.toString("ddd dd MMM\u2003HH:mm"));
2159+ }
2160 };
2161
2162 QTEST_GUILESS_MAIN(TimeFormatterTest)
2163
2164=== modified file 'tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml'
2165--- tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml 2014-07-31 13:31:32 +0000
2166+++ tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml 2014-09-25 12:44:25 +0000
2167@@ -368,9 +368,9 @@
2168 function test_create_alarmMenu_data() {
2169 return [
2170 {label: "testLabel1", enabled: true, icon: "file:///testIcon1", color: Qt.rgba(0, 0, 0, 0),
2171- time: new Date(2014, 04, 14).getTime()*1000, timeFormat: "%a %d %b %l:%M %p"},
2172+ time: new Date(2014, 04, 14), timeFormat: "%a %d %b %l:%M %p"},
2173 {label: "testLabel2", enabled: false, icon: "file:///testIcon2", color: Qt.rgba(1, 0, 0, 0),
2174- time: new Date(2015, 12, 31).getTime()*1000, timeFormat: "%A" },
2175+ time: new Date(2015, 11, 31), timeFormat: "%A" },
2176 ];
2177 }
2178
2179@@ -380,11 +380,11 @@
2180 menuData.sensitive = data.enabled;
2181 menuData.icon = data.icon;
2182 menuData.ext = {
2183- 'xCanonicalTime': data.time,
2184+ 'xCanonicalTime': data.time.getTime() / 1000,
2185 'xCanonicalTimeFormat': data.timeFormat
2186 };
2187 timeFormatter.format = data.timeFormat;
2188- timeFormatter.time = data.time;
2189+ timeFormatter.time = data.time.getTime() / 1000;
2190
2191 loader.data = menuData;
2192 loader.sourceComponent = factory.load(menuData);
2193@@ -400,9 +400,9 @@
2194 function test_create_appointmentMenu_data() {
2195 return [
2196 {label: "testLabel1", enabled: true, icon: "file:///testIcon1", color: Qt.rgba(0, 0, 0, 0),
2197- time: new Date(2014, 04, 14).getTime()*1000, timeFormat: "%a %d %b %l:%M %p"},
2198+ time: new Date(2014, 04, 14), timeFormat: "%a %d %b %l:%M %p"},
2199 {label: "testLabel2", enabled: false, icon: "file:///testIcon2", color: Qt.rgba(1, 0, 0, 0),
2200- time: new Date(2015, 12, 31).getTime()*1000, timeFormat: "%A" },
2201+ time: new Date(2015, 11, 31), timeFormat: "%A" },
2202 ];
2203 }
2204
2205@@ -413,11 +413,11 @@
2206 menuData.icon = data.icon;
2207 menuData.ext = {
2208 'xCanonicalColor': data.colour,
2209- 'xCanonicalTime': data.time,
2210+ 'xCanonicalTime': data.time.getTime() / 1000,
2211 'xCanonicalTimeFormat': data.timeFormat
2212 };
2213 timeFormatter.format = data.timeFormat;
2214- timeFormatter.time = data.time;
2215+ timeFormatter.time = data.time.getTime() / 1000;
2216
2217 loader.data = menuData;
2218 loader.sourceComponent = factory.load(menuData);
2219@@ -488,7 +488,10 @@
2220 compare(loader.item.text, data.label, "Label does not match data");
2221 compare(loader.item.iconSource, data.icon, "Icon does not match data");
2222 compare(loader.item.enabled, data.enabled, "Enabled does not match data");
2223- compare(loader.item.control.text, data.buttonText, "Button text does not match data");
2224+
2225+ var button = findChild(loader.item, "buttonSectionMenuControl");
2226+ verify(button !== null);
2227+ compare(button.text, data.buttonText, "Button text does not match data");
2228 }
2229
2230 function test_create_wifiSection_data() {
2231@@ -514,8 +517,8 @@
2232
2233 function test_create_accessPoint_data() {
2234 return [
2235- {label: "testLabel1", enabled: true, checked: false, secure: true, adHoc: false },
2236- {label: "testLabel2", enabled: false, checked: true, secure: false, adHoc: true },
2237+ {label: "testLabel1", enabled: true, active: false, secure: true, adHoc: false },
2238+ {label: "testLabel2", enabled: false, active: true, secure: false, adHoc: true },
2239 ];
2240 }
2241
2242@@ -523,7 +526,7 @@
2243 menuData.type = "unity.widgets.systemsettings.tablet.accesspoint";
2244 menuData.label = data.label;
2245 menuData.sensitive = data.enabled;
2246- menuData.isToggled = data.checked;
2247+ menuData.isToggled = data.active;
2248 menuData.ext = {
2249 'xCanonicalWifiApStrengthAction': "action::strength",
2250 'xCanonicalWifiApIsSecure': data.secure,
2251@@ -539,7 +542,7 @@
2252 compare(loader.item.strengthAction.name, "action::strength", "Strength action incorrect");
2253 compare(loader.item.secure, data.secure, "Secure does not match data");
2254 compare(loader.item.adHoc, data.adHoc, "AdHoc does not match data");
2255- compare(loader.item.checked, data.checked, "Checked does not match data");
2256+ compare(loader.item.active, data.active, "Checked does not match data");
2257 compare(loader.item.enabled, data.enabled, "Enabled does not match data");
2258 }
2259
2260@@ -635,7 +638,8 @@
2261 album: "album1",
2262 running: true,
2263 state: "Playing",
2264- enabled: true
2265+ enabled: true,
2266+ showTrack: true
2267 },{
2268 label: "player2",
2269 icon: "file:://icon2",
2270@@ -645,7 +649,19 @@
2271 album: "album2",
2272 running: false,
2273 state: "Paused",
2274- enabled: false
2275+ enabled: false,
2276+ showTrack: false
2277+ },{
2278+ label: "player3",
2279+ icon: "file:://icon3",
2280+ albumArt: "file:://art3",
2281+ song: "song3",
2282+ artist: "artist3",
2283+ album: "album3",
2284+ running: true,
2285+ state: "Stopped",
2286+ enabled: true,
2287+ showTrack: false
2288 }
2289 ];
2290 }
2291@@ -675,7 +691,7 @@
2292 compare(loader.item.song, data.song, "Song does not match data");
2293 compare(loader.item.artist, data.artist, "Artist does not match data");
2294 compare(loader.item.album, data.album, "Album does not match data");
2295- compare(loader.item.running, data.running, "Running does not match data");
2296+ compare(loader.item.showTrack, data.showTrack, "Show track does not match data");
2297 compare(loader.item.state, data.state, "State does not match data");
2298 compare(loader.item.enabled, data.enabled, "Enabled does not match data");
2299 }
2300
2301=== modified file 'tests/qmltests/Panel/Indicators/tst_MessageMenuItemFactory.qml'
2302--- tests/qmltests/Panel/Indicators/tst_MessageMenuItemFactory.qml 2014-06-20 15:13:17 +0000
2303+++ tests/qmltests/Panel/Indicators/tst_MessageMenuItemFactory.qml 2014-09-25 12:44:25 +0000
2304@@ -32,9 +32,8 @@
2305 menuIndex: 0
2306 }
2307
2308- Utils.TimeFormatter {
2309+ Utils.RelativeTimeFormatter {
2310 id: timeFormatter
2311- format: "hh:mm - MMM dd"
2312 }
2313
2314 UT.UnityTestCase {
2315@@ -73,8 +72,8 @@
2316
2317 function test_create_simpleTextmessage_data() {
2318 return [
2319- { title: "Title1", time: new Date(2013, 10, 10).getTime()*1000, message: "This is a text message 1", avatar: "file:///avatar1", appIcon: "file:///appIcon1", enabled: true},
2320- { title: "Title2", time: new Date(2014, 12, 10).getTime()*1000, message: "This is a text message 2", avatar: "file:///avatar2", appIcon: "file:///appIcon2", enabled: false},
2321+ { title: "Title1", time: new Date(2013, 10, 10), body: "This is a text message 1", avatar: "file:///avatar1", icon: "file:///appIcon1", enabled: true},
2322+ { title: "Title2", time: new Date(2014, 12, 10), body: "This is a text message 2", avatar: "file:///avatar2", icon: "file:///appIcon2", enabled: false},
2323 ];
2324 }
2325
2326@@ -83,30 +82,27 @@
2327 menuData.label = data.title;
2328 menuData.sensitive = data.enabled;
2329 menuData.ext = {
2330- 'xCanonicalTime': data.time,
2331- 'xCanonicalText': data.message,
2332+ 'xCanonicalTime': data.time.getTime()*1000,
2333+ 'xCanonicalText': data.body,
2334 'icon': data.avatar,
2335- 'xCanonicalAppIcon': data.appIcon,
2336+ 'xCanonicalAppIcon': data.icon,
2337 };
2338 factory.menuData = menuData;
2339- timeFormatter.time = data.time;
2340-
2341- var loader = findChild(factory, "loader");
2342- verify(loader !== undefined);
2343-
2344- tryCompare(loader.item, "objectName", "simpleTextMessage");
2345- compare(loader.item.title, data.title, "Title does not match data");
2346- compare(loader.item.time, timeFormatter.timeString, "Time does not match data");
2347- compare(loader.item.message, data.message, "Message does not match data");
2348- compare(loader.item.avatar, data.avatar, "Avatar does not match data");
2349- compare(loader.item.appIcon, data.appIcon, "App icon does not match data");
2350- compare(loader.item.enabled, data.enabled, "Enabled does not match data");
2351+ timeFormatter.time = data.time.getTime()/1000;
2352+
2353+ tryCompare(factory.item, "objectName", "simpleTextMessage");
2354+ compare(factory.item.title, data.title, "Title does not match data");
2355+ compare(factory.item.time, timeFormatter.timeString, "Time does not match data");
2356+ compare(factory.item.body, data.body, "Message does not match data");
2357+ compare(factory.item.avatar, data.avatar, "Avatar does not match data");
2358+ compare(factory.item.icon, data.icon, "App icon does not match data");
2359+ compare(factory.item.enabled, data.enabled, "Enabled does not match data");
2360 }
2361
2362 function test_create_textmessage_data() {
2363 return [
2364- { title: "Title1", time: new Date(2013, 10, 10).getTime()*1000, message: "This is a text message 1", avatar: "file:///avatar1", appIcon: "file:///appIcon1", enabled: true},
2365- { title: "Title2", time: new Date(2014, 12, 10).getTime()*1000, message: "This is a text message 2", avatar: "file:///avatar2", appIcon: "file:///appIcon2", enabled: false},
2366+ { title: "Title1", time: new Date(2013, 10, 10), body: "This is a text message 1", avatar: "file:///avatar1", icon: "file:///appIcon1", enabled: true},
2367+ { title: "Title2", time: new Date(2014, 12, 10), body: "This is a text message 2", avatar: "file:///avatar2", icon: "file:///appIcon2", enabled: false},
2368 ];
2369 }
2370
2371@@ -115,10 +111,10 @@
2372 menuData.label = data.title;
2373 menuData.sensitive = data.enabled;
2374 menuData.ext = {
2375- 'xCanonicalTime': data.time,
2376- 'xCanonicalText': data.message,
2377+ 'xCanonicalTime': data.time.getTime()*1000,
2378+ 'xCanonicalText': data.body,
2379 'icon': data.avatar,
2380- 'xCanonicalAppIcon': data.appIcon,
2381+ 'xCanonicalAppIcon': data.icon,
2382 'xCanonicalMessageActions': [{
2383 'parameter-type': "s",
2384 'name': "action::reply",
2385@@ -127,25 +123,22 @@
2386 ]
2387 };
2388 factory.menuData = menuData;
2389- timeFormatter.time = data.time;
2390-
2391- var loader = findChild(factory, "loader");
2392- verify(loader !== undefined);
2393-
2394- tryCompare(loader.item, "objectName", "textMessage");
2395- compare(loader.item.title, data.title, "Title does not match data");
2396- compare(loader.item.time, timeFormatter.timeString, "Time does not match data");
2397- compare(loader.item.message, data.message, "Message does not match data");
2398- compare(loader.item.avatar, data.avatar, "Avatar does not match data");
2399- compare(loader.item.appIcon, data.appIcon, "App icon does not match data");
2400- compare(loader.item.enabled, data.enabled, "Enabled does not match data");
2401+ timeFormatter.time = data.time.getTime()/1000;
2402+
2403+ tryCompare(factory.item, "objectName", "textMessage");
2404+ compare(factory.item.title, data.title, "Title does not match data");
2405+ compare(factory.item.time, timeFormatter.timeString, "Time does not match data");
2406+ compare(factory.item.body, data.body, "Message does not match data");
2407+ compare(factory.item.avatar, data.avatar, "Avatar does not match data");
2408+ compare(factory.item.icon, data.icon, "App icon does not match data");
2409+ compare(factory.item.enabled, data.enabled, "Enabled does not match data");
2410 }
2411
2412
2413 function test_create_snapDecision_data() {
2414 return [
2415- { title: "Title1", time: new Date(2013, 10, 10).getTime()*1000, message: "This is a text message 1", avatar: "file:///avatar1", appIcon: "file:///appIcon1", enabled: true},
2416- { title: "Title2", time: new Date(2014, 12, 10).getTime()*1000, message: "This is a text message 2", avatar: "file:///avatar2", appIcon: "file:///appIcon2", enabled: false},
2417+ { title: "Title1", time: new Date(2013, 10, 10), body: "This is a text message 1", avatar: "file:///avatar1", icon: "file:///appIcon1", enabled: true},
2418+ { title: "Title2", time: new Date(2014, 12, 10), body: "This is a text message 2", avatar: "file:///avatar2", icon: "file:///appIcon2", enabled: false},
2419 ];
2420 }
2421
2422@@ -154,10 +147,10 @@
2423 menuData.label = data.title;
2424 menuData.sensitive = data.enabled;
2425 menuData.ext = {
2426- 'xCanonicalTime': data.time,
2427- 'xCanonicalText': data.message,
2428+ 'xCanonicalTime': data.time.getTime()*1000,
2429+ 'xCanonicalText': data.body,
2430 'icon': data.avatar,
2431- 'xCanonicalAppIcon': data.appIcon,
2432+ 'xCanonicalAppIcon': data.icon,
2433 'xCanonicalMessageActions': [{
2434 'name': "action::callback",
2435 'label': "Callback1"
2436@@ -169,18 +162,15 @@
2437 ]
2438 };
2439 factory.menuData = menuData;
2440- timeFormatter.time = data.time;
2441-
2442- var loader = findChild(factory, "loader");
2443- verify(loader !== undefined);
2444-
2445- tryCompare(loader.item, "objectName", "snapDecision");
2446- compare(loader.item.title, data.title, "Title does not match data");
2447- compare(loader.item.time, timeFormatter.timeString, "Time does not match data");
2448- compare(loader.item.message, data.message, "Message does not match data");
2449- compare(loader.item.avatar, data.avatar, "Avatar does not match data");
2450- compare(loader.item.appIcon, data.appIcon, "App icon does not match data");
2451- compare(loader.item.enabled, data.enabled, "Enabled does not match data");
2452+ timeFormatter.time = data.time.getTime()/1000;
2453+
2454+ tryCompare(factory.item, "objectName", "snapDecision");
2455+ compare(factory.item.title, data.title, "Title does not match data");
2456+ compare(factory.item.time, timeFormatter.timeString, "Time does not match data");
2457+ compare(factory.item.body, data.body, "Message does not match data");
2458+ compare(factory.item.avatar, data.avatar, "Avatar does not match data");
2459+ compare(factory.item.icon, data.icon, "App icon does not match data");
2460+ compare(factory.item.enabled, data.enabled, "Enabled does not match data");
2461 }
2462
2463 }
2464
2465=== modified file 'tests/qmltests/Panel/tst_Indicators.qml'
2466--- tests/qmltests/Panel/tst_Indicators.qml 2014-05-07 13:59:58 +0000
2467+++ tests/qmltests/Panel/tst_Indicators.qml 2014-09-25 12:44:25 +0000
2468@@ -173,7 +173,7 @@
2469 function test_row_visible_menuContent_visible(data) {
2470 indicators.show();
2471
2472- var indicatorTabs = findChild(indicators, "tabs");
2473+ var contentListView = findChild(indicators, "indicatorsContentListView");
2474 var indicatorRowItems = findChild(indicators, "indicatorRowItems");
2475
2476 var count = data.visible.length
2477@@ -194,19 +194,19 @@
2478 tryCompareFunction(function() { return findChild(indicatorRowItems, widgetName) !== null }, data.visible[i]);
2479
2480 // check for tab
2481- tryCompareFunction(function() { return findChild(indicatorTabs, pageName) !== null }, data.visible[i]);
2482+ tryCompareFunction(function() { return findChild(contentListView, pageName) !== null }, data.visible[i]);
2483 }
2484 }
2485
2486- function test_indicator_visible_correct_tabs_data() { return [
2487- {tag: "current-first", currentIndex: 0, visible: [false, true, true, true, true], expectedIndex: 0, expectedTab: "indicator-fake2" },
2488- {tag: "current-last", currentIndex: 4, visible: [true, true, true, true, false], expectedIndex: 3, expectedTab: "indicator-fake4" },
2489- {tag: "after", currentIndex: 0, visible: [true, false, true, true, true], expectedIndex: 0, expectedTab: "indicator-fake1" },
2490- {tag: "before", currentIndex: 1, visible: [false, true, true, true, true], expectedIndex: 1, expectedTab: "indicator-fake2" }];
2491+ function test_indicator_visible_correct_menu_data() { return [
2492+ {tag: "current-first", currentIndex: 0, visible: [false, true, true, true, true], expectedIndex: 0, expextedMenu: "indicator-fake2" },
2493+ {tag: "current-last", currentIndex: 4, visible: [true, true, true, true, false], expectedIndex: 3, expextedMenu: "indicator-fake4" },
2494+ {tag: "after", currentIndex: 0, visible: [true, false, true, true, true], expectedIndex: 0, expextedMenu: "indicator-fake1" },
2495+ {tag: "before", currentIndex: 1, visible: [false, true, true, true, true], expectedIndex: 1, expextedMenu: "indicator-fake2" }];
2496 }
2497
2498- function test_indicator_visible_correct_tabs(data) {
2499- var indicatorTabs = findChild(indicators, "tabs");
2500+ function test_indicator_visible_correct_menu(data) {
2501+ var contentListView = findChild(indicators, "indicatorsContentListView");
2502 var indicatorRow = findChild(indicators, "indicatorRow");
2503
2504 indicators.show();
2505@@ -223,7 +223,7 @@
2506 tryCompare(indicatorRow, "currentItemIndex", data.expectedIndex);
2507
2508 // check for current selected tab
2509- tryCompareFunction(function() { return findChild(indicatorTabs, data.expectedTab) === indicatorTabs.selectedTab }, true);
2510+ tryCompareFunction(function() { return findChild(contentListView, data.expextedMenu) === contentListView.currentItem }, true);
2511
2512 }
2513 }
2514
2515=== modified file 'tests/qmltests/Panel/tst_MenuContent.qml'
2516--- tests/qmltests/Panel/tst_MenuContent.qml 2014-03-03 11:55:00 +0000
2517+++ tests/qmltests/Panel/tst_MenuContent.qml 2014-09-25 12:44:25 +0000
2518@@ -47,7 +47,6 @@
2519 MenuContent {
2520 id: menuContent
2521 indicatorsModel: indicatorsModel
2522- contentReleaseInterval: 50
2523 height: parent.height - 50
2524 }
2525
2526@@ -91,22 +90,22 @@
2527 return "indicator-fake" + (index + 1) + "-page";
2528 }
2529
2530- property string testTabObjectName : ""
2531-
2532- function selected_tab_equals_test_tab() {
2533- var currentTab = menu_content_test.findChild(menuContent, "tabs").selectedTab
2534- if (currentTab === null) {
2535- console.log("selected tab undefined");
2536- return false;
2537- }
2538-
2539- var testTab = menu_content_test.findChild(menuContent, testTabObjectName);
2540- if (testTab === null) {
2541- console.log("test_tab " + testTabObjectName + " undefined");
2542- return false;
2543- }
2544-
2545- return testTab == currentTab;
2546+ property string testItemObjectName : ""
2547+
2548+ function current_item_equals_test_item() {
2549+ var currentItem = menu_content_test.findChild(menuContent, "indicatorsContentListView").currentItem
2550+ if (currentItem === null) {
2551+ console.log("current item undefined");
2552+ return false;
2553+ }
2554+
2555+ var testItem = menu_content_test.findChild(menuContent, testItemObjectName);
2556+ if (testItem === null) {
2557+ console.log("testItem " + testItemObjectName + " undefined");
2558+ return false;
2559+ }
2560+
2561+ return testItem === currentItem;
2562 }
2563
2564 UT.UnityTestCase {
2565@@ -114,63 +113,22 @@
2566 name: "MenuContentTest"
2567 when: windowShown
2568
2569- function init() {
2570- if (menuContent.__contentActive)
2571- menuContent.releaseContent();
2572- tryCompare(menuContent, "__contentActive", false);
2573- }
2574-
2575 // Check that the correct menus are displayed for the requested item.
2576 function test_show_menu() {
2577 var menuCount = indicatorsModel.count;
2578 verify(menuCount > 0, "Menu count should be greater than zero");
2579
2580- var tabs = menu_content_test.findChild(menuContent, "tabs")
2581+ var listView = menu_content_test.findChild(menuContent, "indicatorsContentListView")
2582+ verify(listView !== null)
2583
2584 // Loop over twice to test jump between last and first.
2585 for (var i = 0; i < menuCount*2; i++) {
2586-
2587 var menuIndex = i%menuCount;
2588
2589 activate_content(menuIndex);
2590- testTabObjectName = indicatorsModel.data(menuIndex, Indicators.IndicatorsModelRole.Identifier);
2591- compare(tabs.selectedTabIndex, menuIndex, "Current tab index does not match selected tab index");
2592- tryCompareFunction(selected_tab_equals_test_tab, true);
2593- }
2594- }
2595-
2596- // Calling activateContent should call start on all menus
2597- function test_activate_content() {
2598- var menuCount = indicatorsModel.count;
2599- verify(menuCount > 0, "Menu count should be greater than zero");
2600-
2601- // Ensure all the menus are stopped first
2602- menuContent.__contentActive = false;
2603- for (var i = 0; i < menuCount; i++) {
2604- tryCompare(indicator_status[get_test_menu_objecName(i)], "started", false);
2605- }
2606-
2607- // activate content the content to call stop.
2608- menuContent.activateContent();
2609- for (var i = 0; i < menuCount; i++) {
2610- tryCompare(indicator_status[get_test_menu_objecName(i)], "started", true);
2611- }
2612- }
2613-
2614- // Calling activateContent should call stop on all menus.
2615- function test_release_content() {
2616- var menuCount = indicatorsModel.count;
2617- verify(menuCount > 0, "Menu count should be greater than zero");
2618-
2619- // Ensure all the menus are started first
2620- menuContent.__contentActive = true;
2621- for (var i = 0; i < menuCount; i++) {
2622- tryCompare(indicator_status[get_test_menu_objecName(i)], "started", true);
2623- }
2624- // release the content to call stop.
2625- menuContent.releaseContent();
2626- for (var i = 0; i < menuCount; i++) {
2627- tryCompare(indicator_status[get_test_menu_objecName(i)], "started", false);
2628+ testItemObjectName = indicatorsModel.data(menuIndex, Indicators.IndicatorsModelRole.Identifier);
2629+ compare(listView.currentIndex, menuIndex, "Current tab index does not match selected tab index");
2630+ tryCompareFunction(current_item_equals_test_item, true);
2631 }
2632 }
2633

Subscribers

People subscribed via source and target branches