on xenial help sign in
merge trunk
bbb7ed0Michael Zanetti
Bottombar/Bottombar.qml+3−3
@@ -16,10 +16,10 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import "../Components"
18import "../Components"
19−import "../Components/Math.js" as MathLocal
20import Unity 0.1
19import Unity 0.1
21import Unity.Application 0.1
20import Unity.Application 0.1
22import Ubuntu.Gestures 0.1
21import Ubuntu.Gestures 0.1
22+import Ubuntu.Components 0.1
23
23
24Item {
24Item {
25 id: bottombar
25 id: bottombar
@@ -82,7 +82,7 @@ Item {
82
82
83 readonly property bool centeredHud: parent.width < units.gu(68) // Nexus 7 has 67 gu width
83 readonly property bool centeredHud: parent.width < units.gu(68) // Nexus 7 has 67 gu width
84
84
85− x: centeredHud ? parent.width / 2 - width / 2 : MathLocal.clamp(dragArea.touchStartX - (width / 2), 0, bottombar.width - width)
85+ x: centeredHud ? parent.width / 2 - width / 2 : MathUtils.clamp(dragArea.touchStartX - (width / 2), 0, bottombar.width - width)
86 y: bottombar.height - bottomEdgeButtonCenterDistance - (height / 2) - bottomMargin
86 y: bottombar.height - bottomEdgeButtonCenterDistance - (height / 2) - bottomMargin
87 z: 1
87 z: 1
88 visible: opacity != 0
88 visible: opacity != 0
@@ -136,7 +136,7 @@ Item {
136 readonly property real distanceFromThreshold: (-distance) - distanceThreshold // distance is negative
136 readonly property real distanceFromThreshold: (-distance) - distanceThreshold // distance is negative
137 readonly property real revealDistance: units.gu(2)
137 readonly property real revealDistance: units.gu(2)
138 readonly property real commitDistance: units.gu(6)
138 readonly property real commitDistance: units.gu(6)
139− readonly property real commitProgress: MathLocal.clamp(distanceFromThreshold / commitDistance, 0, 1)
139+ readonly property real commitProgress: MathUtils.clamp(distanceFromThreshold / commitDistance, 0, 1)
140
140
141 onStatusChanged: {
141 onStatusChanged: {
142 if (status === DirectionalDragArea.WaitingForTouch) {
142 if (status === DirectionalDragArea.WaitingForTouch) {
Components/Carousel.qml+1−1
@@ -143,7 +143,7 @@ Item {
143 height: listView.tileHeight
143 height: listView.tileHeight
144 }
144 }
145
145
146− boundsBehavior: Flickable.StopAtBounds
146+ boundsBehavior: Flickable.DragOverBounds
147 cacheBuffer: carousel.cacheBuffer
147 cacheBuffer: carousel.cacheBuffer
148 flickDeceleration: Math.max(1500 * Math.pow(realWidth / referenceWidth, 1.5), 1500) // 1500 is platform default
148 flickDeceleration: Math.max(1500 * Math.pow(realWidth / referenceWidth, 1.5), 1500) // 1500 is platform default
149 maximumFlickVelocity: Math.max(2500 * Math.pow(realWidth / referenceWidth, 1.5), 2500) // 2500 is platform default
149 maximumFlickVelocity: Math.max(2500 * Math.pow(realWidth / referenceWidth, 1.5), 2500) // 2500 is platform default
Components/DragHandle.qml+22−24
@@ -17,7 +17,6 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Ubuntu.Gestures 0.1
19import Ubuntu.Gestures 0.1
20−import "Math.js" as MathLocal
21
20
22/*
21/*
23 Put a DragHandle inside a Showable to enable the user to drag it from that handle.
22 Put a DragHandle inside a Showable to enable the user to drag it from that handle.
@@ -48,9 +47,12 @@ EdgeDragArea {
48 id: dragArea
47 id: dragArea
49 objectName: "dragHandle"
48 objectName: "dragHandle"
50
49
51− // Disable gesture detection by default when hinting is used.
50+ // Disable most of the gesture recognition parameters by default when hinting is used as
52− // It doesn't make sense to have both.
51+ // it conflicts with the hinting idea.
52+ // The only part we keep in this situation is that it must be a single-finger gesture.
53− distanceThreshold: hintDisplacement > 0 ? 0 : units.gu(1.5)
53+ distanceThreshold: hintDisplacement > 0 ? 0 : defaultDistanceThreshold
54+ maxSilenceTime: hintDisplacement > 0 ? 60*60*1000 : defaultMaxSilenceTime
55+ maxDeviation: hintDisplacement > 0 ? 999999 : defaultMaxDeviation
54
56
55 property bool stretch: false
57 property bool stretch: false
56
58
@@ -113,8 +115,8 @@ EdgeDragArea {
113 }
115 }
114 }
116 }
115
117
116− function limitMovement(step) {
118+ function limitMovement(inputStep) {
117− var targetValue = MathLocal.clamp(dragParent[targetProp] + step, minValue, maxValue);
119+ var targetValue = MathUtils.clamp(dragParent[targetProp] + inputStep, minValue, maxValue);
118 var step = targetValue - dragParent[targetProp];
120 var step = targetValue - dragParent[targetProp];
119
121
120 if (hintDisplacement == 0) {
122 if (hintDisplacement == 0) {
@@ -181,29 +183,25 @@ EdgeDragArea {
181 }
183 }
182 }
184 }
183
185
184− onDraggingChanged: {
185− if (dragging) {
186− if (hintDisplacement > 0) {
187− hintingAnimation.targetValue = d.startValue;
188− hintingAnimation.start();
189− }
190− } else {
191− hintingAnimation.stop();
192− }
193− }
194−
195 onStatusChanged: {
186 onStatusChanged: {
196 if (status === DirectionalDragArea.WaitingForTouch) {
187 if (status === DirectionalDragArea.WaitingForTouch) {
188+ hintingAnimation.stop();
197 if (d.previousStatus === DirectionalDragArea.Recognized) {
189 if (d.previousStatus === DirectionalDragArea.Recognized) {
198 d.onFinishedRecognizedGesture();
190 d.onFinishedRecognizedGesture();
191+ } else /* d.previousStatus === DirectionalDragArea.Undecided */ {
192+ // Gesture was rejected.
193+ d.rollbackDrag();
194+ }
195+ } else /* Undecided || Recognized */ {
196+ if (d.previousStatus === DirectionalDragArea.WaitingForTouch ||
197+ d.previousStatus === undefined) {
198+ dragEvaluator.reset();
199+ d.startValue = parent[d.targetProp];
200+ }
201+ if (hintDisplacement > 0) {
202+ hintingAnimation.targetValue = d.startValue;
203+ hintingAnimation.start();
199 }
204 }
200− d.startValue = parent[d.targetProp];
201− }
202−
203− if (d.previousStatus === DirectionalDragArea.WaitingForTouch ||
204− d.previousStatus === undefined) {
205− dragEvaluator.reset();
206− d.startValue = parent[d.targetProp];
207 }
205 }
208
206
209 d.previousStatus = status;
207 d.previousStatus = status;
Components/DraggingArea.qml+1−2
@@ -16,7 +16,6 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19−import "Math.js" as MathLocal
20
19
21MouseArea {
20MouseArea {
22 id: draggingArea
21 id: draggingArea
@@ -26,7 +25,7 @@ MouseArea {
26 property real dragVelocity: 0
25 property real dragVelocity: 0
27 property real dragValue: (orientation == Qt.Vertical ? (mouseY - __pressedPosition.y)
26 property real dragValue: (orientation == Qt.Vertical ? (mouseY - __pressedPosition.y)
28 : (mouseX - __pressedPosition.x))
27 : (mouseX - __pressedPosition.x))
29− property real lateralPosition: orientation == Qt.Horizontal ? MathLocal.clamp(mouseY, 0, height) : MathLocal.clamp(mouseX, 0, width)
28+ property real lateralPosition: orientation == Qt.Horizontal ? MathUtils.clamp(mouseY, 0, height) : MathUtils.clamp(mouseX, 0, width)
30 property point __pressedPosition: Qt.point(0, 0)
29 property point __pressedPosition: Qt.point(0, 0)
31 property var __dragEvents: []
30 property var __dragEvents: []
32 property bool clickValidated: true
31 property bool clickValidated: true
Components/EdgeDemoOverlay.qml+2
@@ -105,6 +105,8 @@ Showable {
105 visible: overlay.active
105 visible: overlay.active
106
106
107 MouseArea {
107 MouseArea {
108+ objectName: "backgroundShadeMouseArea"
109+
108 anchors.fill: parent
110 anchors.fill: parent
109 enabled: overlay.edge == "none" && overlay.opacity == 1.0
111 enabled: overlay.edge == "none" && overlay.opacity == 1.0
110 onClicked: overlay.doSkip()
112 onClicked: overlay.doSkip()
Components/EdgeDragArea.qml+12−4
@@ -29,8 +29,16 @@ DirectionalDragArea {
29 //
29 //
30 // The idea here is that it's better having lax rules than false negatives.
30 // The idea here is that it's better having lax rules than false negatives.
31 // False negatives are very frustrating to the user.
31 // False negatives are very frustrating to the user.
32− maxDeviation: units.gu(3)
32+ maxDeviation: defaultMaxDeviation
33− wideningAngle: 50
33+ wideningAngle: defaultWideningAngle
34− distanceThreshold: units.gu(1.5)
34+ distanceThreshold: defaultDistanceThreshold
35+ minSpeed: defaultMinSpeed
36+ maxSilenceTime: defaultMaxSilenceTime
37+
38+ readonly property real defaultMaxDeviation: units.gu(3)
39+ readonly property real defaultWideningAngle: 50
40+ readonly property real defaultDistanceThreshold: units.gu(1.5)
35− minSpeed: units.gu(0) // some people were getting false negatives with it enabled.
41+ // some people were getting false negatives with it enabled.
42+ readonly property real defaultMinSpeed: units.gu(0)
43+ readonly property int defaultMaxSilenceTime: 200
36}
44}
Components/PinPadButton.qml+40−13
@@ -21,24 +21,51 @@ Item {
21 id: root
21 id: root
22
22
23 property alias text: label.text
23 property alias text: label.text
24− property alias iconName: icon.name
24+ property alias subText: subTextLabel.text
25+ property string iconName
25
26
26 signal clicked()
27 signal clicked()
27
28
28− Label {
29+ Column {
29− id: label
30 anchors.centerIn: parent
30 anchors.centerIn: parent
31− color: "#f3f3e7"
31+ width: parent.width
32− fontSize: "large"
32+ height: childrenRect.height
33− font.weight: Font.DemiBold
34− }
35
33
34+ Item {
35+ anchors {
36+ left: parent.left
37+ right: parent.right
38+ }
39+ height: label.visible || icon.visible ? Math.max(label.height, icon.height) : 0
40+
41+ Label {
42+ id: label
43+ anchors.centerIn: parent
44+ width: parent.width
45+ horizontalAlignment: Text.AlignHCenter
46+ color: "#f3f3e7"
47+ fontSize: "large"
48+ font.weight: Font.DemiBold
49+ visible: text.length > 0
50+ }
51+
36− Icon {
52+ Icon {
37− id: icon
53+ id: icon
38− height: units.gu(3)
54+ height: units.gu(3)
39− width: height
55+ width: height
40− anchors.centerIn: parent
56+ anchors.centerIn: parent
57+ name: root.iconName
41− color: "#f3f3e7"
58+ color: "#f3f3e7"
59+ visible: name.length > 0
60+ }
61+ }
62+ Label {
63+ id: subTextLabel
64+ fontSize: "small"
65+ color: "grey"
66+ anchors.horizontalCenter: parent.horizontalCenter
67+ visible: text.length > 0
68+ }
42 }
69 }
43
70
44 MouseArea {
71 MouseArea {
Components/Revealer.qml+1−2
@@ -16,7 +16,6 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19−import "Math.js" as MathLocal
20
19
21Item {
20Item {
22 id: revealer
21 id: revealer
@@ -95,7 +94,7 @@ Item {
95 onClosedValueChanged: if (!__opened && !dragging) target[boundProperty] = closedValue
94 onClosedValueChanged: if (!__opened && !dragging) target[boundProperty] = closedValue
96
95
97 function __computeValue(dragPosition) {
96 function __computeValue(dragPosition) {
98− return MathLocal.clamp(dragToValue(dragPosition), __hintValue, openedValue)
97+ return MathUtils.clamp(dragToValue(dragPosition), __hintValue, openedValue)
99 }
98 }
100
99
101 function __open() {
100 function __open() {
Components/Stage.qml+8−7
@@ -482,19 +482,20 @@ Showable {
482 switchToApplicationAnimationController.progress += 0.4 * delta
482 switchToApplicationAnimationController.progress += 0.4 * delta
483 }
483 }
484
484
485− property bool gotRejected: false
485+ property int lastStatus: -1
486
486
487 onStatusChanged: {
487 onStatusChanged: {
488 if (status == DirectionalDragArea.Undecided) {
488 if (status == DirectionalDragArea.Undecided) {
489− gotRejected = false
490 onUndecided();
489 onUndecided();
491− } else if (status == DirectionalDragArea.Rejected) {
492− switchToApplicationAnimationController.completeToBeginningWithSignal();
493− gotRejected = true;
494 } else if (status == DirectionalDragArea.WaitingForTouch) {
490 } else if (status == DirectionalDragArea.WaitingForTouch) {
495− if (!gotRejected)
491+ if (lastStatus == DirectionalDragArea.Undecided) {
492+ // got rejected
493+ switchToApplicationAnimationController.completeToBeginningWithSignal();
494+ } else {
496− onGestureEnded()
495+ onGestureEnded();
496+ }
497 }
497 }
498+ lastStatus = status;
498 }
499 }
499
500
500 function onUndecided() {
501 function onUndecided() {
Components/Time.js+9−9
@@ -16,15 +16,15 @@
16
16
17.pragma library
17.pragma library
18
18
19−var factors = {
19+var factors = [
20− "second": [ 1000, "a second ago", "in a second", "%1 seconds ago", "in %1 seconds" ],
20+ [ 1000, "a second ago", "in a second", "%1 seconds ago", "in %1 seconds" ],
21− "minute": [ 60, "a minute ago", "in a minute", "%1 minutes ago", "in %1 minutes" ],
21+ [ 60, "a minute ago", "in a minute", "%1 minutes ago", "in %1 minutes" ],
22− "hour": [ 60, "an hour ago", "in an hour", "%1 hours ago", "in %1 hours" ],
22+ [ 60, "an hour ago", "in an hour", "%1 hours ago", "in %1 hours" ],
23− "day": [ 24, "yesterday", "tomorrow", "%1 days ago", "in %1 days" ],
23+ [ 24, "yesterday", "tomorrow", "%1 days ago", "in %1 days" ],
24− "week": [ 7, "a week ago", "in a week", "about %1 weeks ago", "in about %1 weeks" ],
24+ [ 7, "a week ago", "in a week", "about %1 weeks ago", "in about %1 weeks" ],
25− "month": [ 4.35, "a month ago", "in a month", "%1 months ago", "in %1 months" ], // == 365.25 days / 12 months / 7 days
25+ [ 4.35, "a month ago", "in a month", "%1 months ago", "in %1 months" ], // == 365.25 days / 12 months / 7 days
26− "year": [ 12, "a year ago", "in a year", "%1 years ago", "in %1 years" ]
26+ [ 12, "a year ago", "in a year", "%1 years ago", "in %1 years" ]
27−}
27+]
28
28
29function readableFromNow(date, now) {
29function readableFromNow(date, now) {
30 var then = new Date(date);
30 var then = new Date(date);
Components/UbuntuShapeForItem.qml+1
@@ -31,6 +31,7 @@ Item {
31
31
32 ShaderEffectSource {
32 ShaderEffectSource {
33 id: source
33 id: source
34+ anchors.centerIn: parent // Placed under shape, so it's hidden
34 width: 1
35 width: 1
35 height: 1
36 height: 1
36 hideSource: true
37 hideSource: true
Dash/Apps/RunningApplicationTile.qml−2
@@ -105,8 +105,6 @@ AbstractButton {
105 baseline: parent.bottom
105 baseline: parent.bottom
106 left: parent.left
106 left: parent.left
107 right: parent.right
107 right: parent.right
108− leftMargin: units.gu(1)
109− rightMargin: units.gu(1)
110 }
108 }
111 text: (application) ? application.name : ""
109 text: (application) ? application.name : ""
112
110
Dash/Generic/GenericCarouselLoader.qmlnew file+30
@@ -0,0 +1,30 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+
20+Loader {
21+ property var model: null
22+ property url carouselUrl: "GenericCarousel.qml"
23+ property url filtergridUrl: "GenericFilterGrid.qml"
24+
25+ source: model.count > 6 ? carouselUrl : filtergridUrl // FIXME do not hardcode 6, but retrieve correct minimum required count
26+
27+ onLoaded: {
28+ item.model = Qt.binding(function() { return model; })
29+ }
30+}
Dash/GenericScopeView.qml+9−8
@@ -262,26 +262,27 @@ ScopeView {
262 rendererId = getDefaultRendererId(contentType);
262 rendererId = getDefaultRendererId(contentType);
263 }
263 }
264 switch (rendererId) {
264 switch (rendererId) {
265+ case "carousel": {
266+ switch (contentType) {
267+ case "music": return "Music/MusicCarouselLoader.qml";
268+ case "video": return "Video/VideoCarouselLoader.qml";
269+ default: return "Generic/GenericCarouselLoader.qml";
270+ }
271+ }
265 case "grid": {
272 case "grid": {
266 switch (contentType) {
273 switch (contentType) {
267− case "video": return "Video/VideoFilterGrid.qml";
268− case "music": return "Music/MusicFilterGrid.qml";
269 case "apps": {
274 case "apps": {
270 if (rendererHint == "toggled")
275 if (rendererHint == "toggled")
271 return "Apps/DashPluginFilterGrid.qml";
276 return "Apps/DashPluginFilterGrid.qml";
272 else
277 else
273 return "Generic/GenericFilterGrid.qml";
278 return "Generic/GenericFilterGrid.qml";
274 }
279 }
280+ case "music": return "Music/MusicFilterGrid.qml";
281+ case "video": return "Video/VideoFilterGrid.qml";
275 case "weather": return "Generic/WeatherFilterGrid.qml";
282 case "weather": return "Generic/WeatherFilterGrid.qml";
276 default: return "Generic/GenericFilterGrid.qml";
283 default: return "Generic/GenericFilterGrid.qml";
277 }
284 }
278 }
285 }
279− case "carousel": {
280− switch (contentType) {
281− case "music": return "Music/MusicCarousel.qml";
282− default: return "Generic/GenericCarousel.qml";
283− }
284− }
285 case "special": {
286 case "special": {
286 switch (contentType) {
287 switch (contentType) {
287 case "apps": return "Apps/RunningApplicationsGrid.qml";
288 case "apps": return "Apps/RunningApplicationsGrid.qml";
tests/mocks/QMenuModel/UnityMenuModel.qml → Dash/Music/MusicCarouselLoader.qmlrenamed+5−7
@@ -1,9 +1,6 @@
1/*
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
3 *
4− * Authors:
5− * Mirco Müller <mirco.mueller@canonical.com>
6− *
7 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3.
6 * the Free Software Foundation; version 3.
@@ -18,9 +15,10 @@
18 */
15 */
19
16
20import QtQuick 2.0
17import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import "../Generic"
21
20
22−QtObject {
21+GenericCarouselLoader {
23− property variant busName
22+ carouselUrl: "MusicCarousel.qml"
24− property variant actions
23+ filtergridUrl: "MusicFilterGrid.qml"
25− property variant menuObjectPath
26}
24}
Dash/Video/VideosCarousel.qml → Dash/Video/VideoCarousel.qmlrenamed

The content is the same.

Components/Math.js → Dash/Video/VideoCarouselLoader.qmlrenamed+6−8
@@ -14,13 +14,11 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17−.pragma library
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import "../Generic"
18
20
19−function clamp(value, min, max) {
21+GenericCarouselLoader {
20− if (min <= max) {
22+ carouselUrl: "VideoCarousel.qml"
21− return Math.max(min, Math.min(max, value))
23+ filtergridUrl: "VideoFilterGrid.qml"
22− } else {
23− // swap min/max if min > max
24− return clamp(value, max, min)
25− }
26}
24}
Greeter/Greeter.qml+3−3
@@ -19,7 +19,6 @@ import Ubuntu.Components 0.1
19import Ubuntu.Gestures 0.1
19import Ubuntu.Gestures 0.1
20import LightDM 0.1 as LightDM
20import LightDM 0.1 as LightDM
21import "../Components"
21import "../Components"
22−import "../Components/Math.js" as MathLocal
23
22
24Showable {
23Showable {
25 id: greeter
24 id: greeter
@@ -29,7 +28,7 @@ Showable {
29 property url defaultBackground
28 property url defaultBackground
30
29
31 // 1 when fully shown and 0 when fully hidden
30 // 1 when fully shown and 0 when fully hidden
32− property real showProgress: MathLocal.clamp((width + x) / width, 0, 1)
31+ property real showProgress: MathUtils.clamp((width + x) / width, 0, 1)
33
32
34 showAnimation: StandardAnimation { property: "x"; to: 0 }
33 showAnimation: StandardAnimation { property: "x"; to: 0 }
35 hideAnimation: StandardAnimation { property: "x"; to: -width }
34 hideAnimation: StandardAnimation { property: "x"; to: -width }
@@ -52,7 +51,7 @@ Showable {
52 signal unlocked(int uid)
51 signal unlocked(int uid)
53
52
54 onRightTeaserPressedChanged: {
53 onRightTeaserPressedChanged: {
55− if (rightTeaserPressed && !locked) {
54+ if (rightTeaserPressed && !locked && x == 0) {
56 teasingTimer.start();
55 teasingTimer.start();
57 }
56 }
58 }
57 }
@@ -64,6 +63,7 @@ Showable {
64 property var model: LightDM.Users
63 property var model: LightDM.Users
65 property int currentIndex: 0
64 property int currentIndex: 0
66 property var infographicModel: LightDM.Infographic
65 property var infographicModel: LightDM.Infographic
66+ readonly property int backgroundTopMargin: -greeter.y
67
67
68 source: required ? "GreeterContent.qml" : ""
68 source: required ? "GreeterContent.qml" : ""
69
69
Greeter/GreeterContent.qml+23−20
@@ -24,7 +24,7 @@ MouseArea {
24 id: root
24 id: root
25 anchors.fill: parent
25 anchors.fill: parent
26
26
27− property bool ready: wallpaper.source == "" || wallpaper.status == Image.Ready || wallpaper.status == Image.Error
27+ property bool ready: background.source == "" || background.status == Image.Ready || background.status == Image.Error
28 property bool leftTeaserPressed: teasingMouseArea.pressed &&
28 property bool leftTeaserPressed: teasingMouseArea.pressed &&
29 teasingMouseArea.mouseX < teasingMouseArea.width / 2
29 teasingMouseArea.mouseX < teasingMouseArea.width / 2
30 property bool rightTeaserPressed: teasingMouseArea.pressed &&
30 property bool rightTeaserPressed: teasingMouseArea.pressed &&
@@ -34,33 +34,36 @@ MouseArea {
34 signal unlocked(int uid)
34 signal unlocked(int uid)
35
35
36 Rectangle {
36 Rectangle {
37− // In case wallpaper fails to load
37+ // In case background fails to load
38− id: wallpaperBackup
38+ id: backgroundBackup
39 anchors.fill: parent
39 anchors.fill: parent
40 color: "black"
40 color: "black"
41 }
41 }
42
42
43 property url backgroundValue: AccountsService.backgroundFile != undefined && AccountsService.backgroundFile.length > 0 ? AccountsService.backgroundFile : greeter.defaultBackground
43 property url backgroundValue: AccountsService.backgroundFile != undefined && AccountsService.backgroundFile.length > 0 ? AccountsService.backgroundFile : greeter.defaultBackground
44− onBackgroundValueChanged: wallpaper.source = backgroundValue
44+ onBackgroundValueChanged: background.source = backgroundValue
45
45
46 CrossFadeImage {
46 CrossFadeImage {
47− id: wallpaper
47+ id: background
48− objectName: "wallpaper"
48+ objectName: "greeterBackground"
49+ anchors {
49− anchors.fill: parent
50+ fill: parent
51+ topMargin: backgroundTopMargin
52+ }
50 fillMode: Image.PreserveAspectCrop
53 fillMode: Image.PreserveAspectCrop
51 }
54 }
52
55
53 // See Shell.qml's backgroundSettings treatment for why we need a separate
56 // See Shell.qml's backgroundSettings treatment for why we need a separate
54 // Image, but it boils down to avoiding binding loop detection.
57 // Image, but it boils down to avoiding binding loop detection.
55 Image {
58 Image {
56− source: wallpaper.source
59+ source: background.source
57 height: 0
60 height: 0
58 width: 0
61 width: 0
59 sourceSize.height: 0
62 sourceSize.height: 0
60 sourceSize.width: 0
63 sourceSize.width: 0
61 onStatusChanged: {
64 onStatusChanged: {
62 if (status == Image.Error && source != greeter.defaultBackground) {
65 if (status == Image.Error && source != greeter.defaultBackground) {
63− wallpaper.source = greeter.defaultBackground
66+ background.source = greeter.defaultBackground
64 }
67 }
65 }
68 }
66 }
69 }
@@ -71,17 +74,6 @@ MouseArea {
71 opacity: 0.4
74 opacity: 0.4
72 }
75 }
73
76
74− Clock {
75− id: clock
76− visible: narrowMode
77−
78− anchors {
79− top: parent.top
80− topMargin: units.gu(2)
81− horizontalCenter: parent.horizontalCenter
82− }
83− }
84−
85 MouseArea {
77 MouseArea {
86 id: teasingMouseArea
78 id: teasingMouseArea
87 anchors.fill: parent
79 anchors.fill: parent
@@ -160,4 +152,15 @@ MouseArea {
160 right: root.right
152 right: root.right
161 }
153 }
162 }
154 }
155+
156+ Clock {
157+ id: clock
158+ visible: narrowMode
159+
160+ anchors {
161+ top: parent.top
162+ topMargin: units.gu(2)
163+ horizontalCenter: parent.horizontalCenter
164+ }
165+ }
163}
166}
Greeter/Lockscreen.qml+8−4
@@ -54,15 +54,19 @@ Showable {
54 }
54 }
55
55
56 Rectangle {
56 Rectangle {
57− // In case wallpaper fails to load or is undefined
57+ // In case background fails to load or is undefined
58− id: wallpaperBackup
58+ id: backgroundBackup
59 anchors.fill: parent
59 anchors.fill: parent
60 color: "black"
60 color: "black"
61 }
61 }
62
62
63 Image {
63 Image {
64− id: wallpaper
64+ id: backgroundImage
65+ objectName: "lockscreenBackground"
66+ anchors {
65− anchors.fill: parent
67+ fill: parent
68+ topMargin: backgroundTopMargin
69+ }
66 source: root.required ? root.background : ""
70 source: root.required ? root.background : ""
67 fillMode: Image.PreserveAspectCrop
71 fillMode: Image.PreserveAspectCrop
68 }
72 }
Greeter/PinLockscreen.qml+34−4
@@ -27,7 +27,7 @@ Column {
27 property alias placeholderText: pinentryField.placeholderText
27 property alias placeholderText: pinentryField.placeholderText
28 property int padWidth: units.gu(34)
28 property int padWidth: units.gu(34)
29 property int padHeight: units.gu(28)
29 property int padHeight: units.gu(28)
30− property int pinLength: 4
30+ property int pinLength: -1
31
31
32 signal entered(string passphrase)
32 signal entered(string passphrase)
33 signal cancel()
33 signal cancel()
@@ -65,6 +65,9 @@ Column {
65 Label {
65 Label {
66 id: pinentryFieldLabel
66 id: pinentryFieldLabel
67 anchors.centerIn: parent
67 anchors.centerIn: parent
68+ width: parent.width - (backspaceIcon.width + backspaceIcon.anchors.rightMargin) * 2
69+ elide: Text.ElideMiddle
70+ horizontalAlignment: Text.AlignHCenter
68 font.pixelSize: units.dp(44)
71 font.pixelSize: units.dp(44)
69 color: "#f3f3e7"
72 color: "#f3f3e7"
70 opacity: 0.6
73 opacity: 0.6
@@ -76,6 +79,26 @@ Column {
76 text: parent.placeholderText
79 text: parent.placeholderText
77 visible: pinentryFieldLabel.text.length == 0
80 visible: pinentryFieldLabel.text.length == 0
78 }
81 }
82+
83+ Icon {
84+ id: backspaceIcon
85+ objectName: "backspaceIcon"
86+ anchors {
87+ top: parent.top
88+ topMargin: units.gu(1)
89+ right: parent.right
90+ rightMargin: units.gu(2)
91+ bottom: parent.bottom
92+ bottomMargin: units.gu(1)
93+ }
94+ visible: root.pinLength == -1
95+ width: height
96+ name: "erase"
97+ MouseArea {
98+ anchors.fill: parent
99+ onClicked: pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1);
100+ }
101+ }
79 }
102 }
80
103
81 UbuntuShape {
104 UbuntuShape {
@@ -154,7 +177,7 @@ Column {
154 objectName: "pinPadButtonBack"
177 objectName: "pinPadButtonBack"
155 width: root.padWidth / 3
178 width: root.padWidth / 3
156 height: root.padHeight / 4
179 height: root.padHeight / 4
157− iconName: "back"
180+ subText: "CANCEL"
158 onClicked: root.cancel();
181 onClicked: root.cancel();
159 }
182 }
160
183
@@ -171,8 +194,15 @@ Column {
171 objectName: "pinPadButtonErase"
194 objectName: "pinPadButtonErase"
172 width: root.padWidth / 3
195 width: root.padWidth / 3
173 height: root.padHeight / 4
196 height: root.padHeight / 4
174− iconName: "erase"
197+ iconName: root.pinLength == -1 ? "" : "erase"
198+ subText: root.pinLength == -1 ? "DONE" : ""
199+ onClicked: {
200+ if (root.pinLength !== -1) {
175− onClicked: pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1)
201+ pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1);
202+ } else {
203+ root.entered(pinentryField.text);
204+ }
205+ }
176 enabled: entryEnabled
206 enabled: entryEnabled
177 }
207 }
178 }
208 }
Launcher/Launcher.qml+2−2
@@ -28,8 +28,8 @@ Item {
28
28
29 property int panelWidth: units.gu(8)
29 property int panelWidth: units.gu(8)
30 property int dragAreaWidth: units.gu(1)
30 property int dragAreaWidth: units.gu(1)
31− property int minimizeDistance: panelWidth * 2.5
31+ property int minimizeDistance: units.gu(26)
32− property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
32+ property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
33 (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0
33 (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0
34
34
35 readonly property bool shown: panel.x > -panel.width
35 readonly property bool shown: panel.x > -panel.width
Notifications/NotificationMenuItemFactory.qml+20−6
@@ -54,7 +54,8 @@ Loader {
54
54
55 Component.onCompleted: {
55 Component.onCompleted: {
56 menuModel.loadExtendedAttributes(menuIndex, {"x-echo-mode-password": "bool"});
56 menuModel.loadExtendedAttributes(menuIndex, {"x-echo-mode-password": "bool"});
57− textfield.echoMode = menuData.ext.xEchoModePassword ? TextInput.Password : TextInput.Normal
57+ checkBox.checked = menuData.ext.xEchoModePassword ? false : true
58+ checkBoxRow.visible = menuData.ext.xEchoModePassword
58 }
59 }
59
60
60 Label {
61 Label {
@@ -65,11 +66,29 @@ Loader {
65 id: textfield
66 id: textfield
66
67
67 anchors.left: parent.left; anchors.right: parent.right
68 anchors.left: parent.left; anchors.right: parent.right
69+ echoMode: checkBox.checked ? TextInput.Normal : TextInput.Password
68 height: units.gu(5)
70 height: units.gu(5)
69 onTextChanged: {
71 onTextChanged: {
70 menuModel.changeState(menuIndex, text);
72 menuModel.changeState(menuIndex, text);
71 }
73 }
72 }
74 }
75+
76+ Row {
77+ id: checkBoxRow
78+
79+ spacing: units.gu(.5)
80+
81+ CheckBox {
82+ id: checkBox
83+
84+ checked: false
85+ }
86+
87+ Label {
88+ anchors.verticalCenter: checkBox.verticalCenter
89+ text: i18n.tr("Show password")
90+ }
91+ }
73 }
92 }
74 }
93 }
75
94
@@ -78,11 +97,6 @@ Loader {
78 PinLockscreen {
97 PinLockscreen {
79 anchors.left: parent.left; anchors.right: parent.right
98 anchors.left: parent.left; anchors.right: parent.right
80
99
81− Component.onCompleted: {
82− menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-pin-length': 'int'});
83− pinLength = menuData.ext.xCanonicalPinLength;
84− }
85−
86 onEntered: {
100 onEntered: {
87 menuModel.changeState(menuIndex, passphrase);
101 menuModel.changeState(menuIndex, passphrase);
88 entryEnabled = false;
102 entryEnabled = false;
Panel/Indicators.qml+1−2
@@ -21,7 +21,6 @@ import Unity.Indicators 0.1 as Indicators
21
21
22import "../Components"
22import "../Components"
23import "../Components/ListItems"
23import "../Components/ListItems"
24−import "../Components/Math.js" as MathLocal
25
24
26Showable {
25Showable {
27 id: indicators
26 id: indicators
@@ -100,7 +99,7 @@ Showable {
100 Otherwise it contains the bar's location as a fraction of the distance between hintValue (is 0) and lockThreshold (is 1).
99 Otherwise it contains the bar's location as a fraction of the distance between hintValue (is 0) and lockThreshold (is 1).
101 */
100 */
102 var verticalProgress =
101 var verticalProgress =
103− MathLocal.clamp((indicators.height - handle.height - hintValue) /
102+ MathUtils.clamp((indicators.height - handle.height - hintValue) /
104 (lockThreshold - hintValue), 0, 1);
103 (lockThreshold - hintValue), 0, 1);
105
104
106 /*
105 /*
Panel/Indicators/DefaultIndicatorWidget.qml+32−10
@@ -24,7 +24,7 @@ import Unity.Indicators 0.1 as Indicators
24Indicators.IndicatorWidget {
24Indicators.IndicatorWidget {
25 id: indicatorWidget
25 id: indicatorWidget
26
26
27− width: itemRow.width + units.gu(0.5)
27+ width: itemRow.width
28
28
29 property alias leftLabel: itemLeftLabel.text
29 property alias leftLabel: itemLeftLabel.text
30 property alias rightLabel: itemRightLabel.text
30 property alias rightLabel: itemRightLabel.text
@@ -32,16 +32,17 @@ Indicators.IndicatorWidget {
32
32
33 Row {
33 Row {
34 id: itemRow
34 id: itemRow
35+ width: childrenRect.width
35 objectName: "itemRow"
36 objectName: "itemRow"
36 anchors {
37 anchors {
37 top: parent.top
38 top: parent.top
38 bottom: parent.bottom
39 bottom: parent.bottom
39 horizontalCenter: parent.horizontalCenter
40 horizontalCenter: parent.horizontalCenter
40 }
41 }
41− spacing: units.gu(0.5)
42
42
43 Label {
43 Label {
44 id: itemLeftLabel
44 id: itemLeftLabel
45+ width: guRoundUp(implicitWidth)
45 objectName: "leftLabel"
46 objectName: "leftLabel"
46 color: Theme.palette.selected.backgroundText
47 color: Theme.palette.selected.backgroundText
47 opacity: 0.8
48 opacity: 0.8
@@ -57,25 +58,35 @@ Indicators.IndicatorWidget {
57 top: parent.top
58 top: parent.top
58 bottom: parent.bottom
59 bottom: parent.bottom
59 }
60 }
60− spacing: units.gu(0.5)
61
61
62 Repeater {
62 Repeater {
63 model: indicatorWidget.icons
63 model: indicatorWidget.icons
64
64
65− Image {
65+ Item {
66− id: itemImage
66+ width: guRoundUp(itemImage.width)
67− objectName: "itemImage"
68− visible: source != ""
69− source: modelData
70 height: indicatorWidget.iconSize
67 height: indicatorWidget.iconSize
68+
69+ Image {
70+ id: itemImage
71+ objectName: "itemImage"
72+ visible: source != ""
73+ source: modelData
74+ height: parent.height
75+ anchors.horizontalCenter: parent.horizontalCenter
76+ fillMode: Image.PreserveAspectFit
77+
78+ sourceSize {
71− width: indicatorWidget.iconSize
79+ width: indicatorWidget.iconSize
72− anchors.verticalCenter: parent.verticalCenter
80+ height: indicatorWidget.iconSize
81+ }
82+ }
73 }
83 }
74 }
84 }
75 }
85 }
76
86
77 Label {
87 Label {
78 id: itemRightLabel
88 id: itemRightLabel
89+ width: guRoundUp(implicitWidth)
79 objectName: "rightLabel"
90 objectName: "rightLabel"
80 color: Theme.palette.selected.backgroundText
91 color: Theme.palette.selected.backgroundText
81 opacity: 0.8
92 opacity: 0.8
@@ -86,6 +97,17 @@ Indicators.IndicatorWidget {
86 }
97 }
87 }
98 }
88
99
100+ // TODO: Use toolkit function https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1242575
101+ function guRoundUp(width) {
102+ if (width == 0) {
103+ return 0;
104+ }
105+ var gu1 = units.gu(1.0);
106+ var mod = (width % gu1);
107+
108+ return mod == 0 ? width : width + (gu1 - mod);
109+ }
110+
89 onRootActionStateChanged: {
111 onRootActionStateChanged: {
90 if (rootActionState == undefined) {
112 if (rootActionState == undefined) {
91 leftLabel = "";
113 leftLabel = "";
Shell.qml+9−3
@@ -30,7 +30,6 @@ import "Launcher"
30import "Panel"
30import "Panel"
31import "Hud"
31import "Hud"
32import "Components"
32import "Components"
33−import "Components/Math.js" as MathLocal
34import "Bottombar"
33import "Bottombar"
35import "SideStage"
34import "SideStage"
36import "Notifications"
35import "Notifications"
@@ -237,7 +236,7 @@ FocusScope {
237 Behavior on x {SmoothedAnimation{velocity: 600}}
236 Behavior on x {SmoothedAnimation{velocity: 600}}
238
237
239 property real showProgress:
238 property real showProgress:
240− MathLocal.clamp(1 - (x + stages.x) / shell.width, 0, 1)
239+ MathUtils.clamp(1 - (x + stages.x) / shell.width, 0, 1)
241
240
242 Showable {
241 Showable {
243 id: stages
242 id: stages
@@ -402,6 +401,10 @@ FocusScope {
402
401
403 Lockscreen {
402 Lockscreen {
404 id: lockscreen
403 id: lockscreen
404+ objectName: "lockscreen"
405+
406+ readonly property int backgroundTopMargin: -panel.panelHeight
407+
405 hides: [launcher, panel.indicators, hud]
408 hides: [launcher, panel.indicators, hud]
406 shown: false
409 shown: false
407 enabled: true
410 enabled: true
@@ -647,19 +650,22 @@ FocusScope {
647 Launcher {
650 Launcher {
648 id: launcher
651 id: launcher
649
652
653+ readonly property bool dashSwipe: progress > 0
654+
650 anchors.top: parent.top
655 anchors.top: parent.top
651 anchors.bottom: parent.bottom
656 anchors.bottom: parent.bottom
652 width: parent.width
657 width: parent.width
653 dragAreaWidth: shell.edgeSize
658 dragAreaWidth: shell.edgeSize
654 available: (!greeter.shown || greeter.narrowMode) && edgeDemo.launcherEnabled
659 available: (!greeter.shown || greeter.narrowMode) && edgeDemo.launcherEnabled
660+
655 onDashItemSelected: showHome()
661 onDashItemSelected: showHome()
656 onDash: {
662 onDash: {
657 if (stages.shown) {
663 if (stages.shown) {
658− dash.setCurrentScope("applications.scope", true /* animate */, true /* reset */)
659 stages.hide();
664 stages.hide();
660 launcher.hide();
665 launcher.hide();
661 }
666 }
662 }
667 }
668+ onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("applications.scope", false, true)
663 onLauncherApplicationSelected:{
669 onLauncherApplicationSelected:{
664 greeter.hide()
670 greeter.hide()
665 shell.activateApplication(appId)
671 shell.activateApplication(appId)
debian/changelog+66
@@ -1,3 +1,69 @@
1+unity8 (7.83+14.04.20131106-0ubuntu1) trusty; urgency=low
2+
3+ [ Andrea Cimitan ]
4+ * Place ShaderEffectSource of UbuntuShapeForItem under the Shape Item.
5+ (LP: #1239317)
6+
7+ [ Omer Akram ]
8+ * test: make sure the search indicator hides when an app has focus.
9+
10+ [ Nick Dedekind ]
11+ * Fixed indicator slider menu item alignment to label field and icon.
12+ (LP: #1240756)
13+
14+ [ chris.gagnon ]
15+ * Update to autopilot 1.4.
16+
17+ [ Ubuntu daily release ]
18+ * Automatic snapshot from revision 500
19+
20+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 06 Nov 2013 03:37:02 +0000
21+
22+unity8 (7.83+14.04.20131105.1-0ubuntu1) trusty; urgency=low
23+
24+ [ Michał Sawicz ]
25+ * Implement switching between previews by swiping. (LP: #1220651,
26+ #1088572)
27+
28+ [ Nick Dedekind ]
29+ * Faster loading of indicator menus. (LP: #1226650)
30+
31+ [ Albert Astals ]
32+ * Make sure we have ssh started when we need it .
33+ * Fix a few warnings in DashContent.qml on shutdown
34+ Dash/DashContent.qml:119: TypeError: Cannot read property
35+ 'previewShown' of null Dash/DashContent.qml:120: TypeError: Cannot
36+ read property 'moving' of null .
37+ * Don't use deprecated Panel methods.
38+
39+ [ Christopher Lee ]
40+ * Adds an easy to consume function that attempts to unlock the unity
41+ greeter. (LP: #1240261)
42+
43+ [ Lars Uebernickel ]
44+ * Indicators: add TimeFormatter and use it in the messaging menu This
45+ component can be used to turn a timestamp and a format string into a
46+ string with the corresponding time and format. The string will
47+ change whenever the timezone changes. (LP: #1236413)
48+
49+ [ Andrea Cimitan ]
50+ * Allow drag over bounds, but not overshoot. (LP: #1204300)
51+ * Threshold to activate the left edge swipe to reveal dash is now 26
52+ GU. (LP: #1236286)
53+
54+ [ Michael Zanetti ]
55+ * replace the launcher quicklist's Popover with an own quicklist
56+ implementation The Popover probably won't ever support what the
57+ launcher needs.
58+ * Implement switching between previews by swiping. (LP: #1220651,
59+ #1088572)
60+ * don't trigger the greeter teasing during a movement of the greeter.
61+
62+ [ Ubuntu daily release ]
63+ * Automatic snapshot from revision 495
64+
65+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 05 Nov 2013 12:22:04 +0000
66+
1unity8 (7.83+14.04.20131031-0ubuntu1) trusty; urgency=low
67unity8 (7.83+14.04.20131031-0ubuntu1) trusty; urgency=low
2
68
3 [ Michał Sawicz ]
69 [ Michał Sawicz ]
debian/control+1−1
@@ -91,7 +91,7 @@ Description: Unity 8 shell
91Package: unity8-autopilot
91Package: unity8-autopilot
92Architecture: all
92Architecture: all
93Depends: gir1.2-glib-2.0,
93Depends: gir1.2-glib-2.0,
94− libautopilot-qt,
94+ libautopilot-qt (>= 1.4),
95 libqt5test5,
95 libqt5test5,
96 libqt5widgets5,
96 libqt5widgets5,
97 python-evdev,
97 python-evdev,
plugins/Ubuntu/Gestures/AxisVelocityCalculator.cpp+9−18
@@ -21,25 +21,19 @@
21#include "AxisVelocityCalculator.h"
21#include "AxisVelocityCalculator.h"
22#include <QtCore/QElapsedTimer>
22#include <QtCore/QElapsedTimer>
23
23
24−class RealTimeSource : public UbuntuGestures::TimeSource {
25−public:
26− RealTimeSource()
27− : UbuntuGestures::TimeSource() {
24+using namespace UbuntuGestures;
28− m_timer.start();
29− }
30− virtual qint64 msecsSinceReference() {
31− return m_timer.elapsed();
32− }
33−private:
34− QElapsedTimer m_timer;
35−};
36
25
37AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
26AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
27+ : AxisVelocityCalculator(SharedTimeSource(new RealTimeSource), parent)
28+{
29+}
30+
31+AxisVelocityCalculator::AxisVelocityCalculator(const SharedTimeSource &timeSource,
32+ QObject *parent)
38 : QObject(parent)
33 : QObject(parent)
39− , m_timeSource(new RealTimeSource)
34+ , m_timeSource(timeSource)
40 , m_trackedPosition(0.0)
35 , m_trackedPosition(0.0)
41{
36{
42− m_timeSource->setParent(this);
43 reset();
37 reset();
44}
38}
45
39
@@ -142,11 +136,8 @@ int AxisVelocityCalculator::numSamples() const
142 }
136 }
143}
137}
144
138
145−void AxisVelocityCalculator::setTimeSource(UbuntuGestures::TimeSource *timeSource)
139+void AxisVelocityCalculator::setTimeSource(const SharedTimeSource &timeSource)
146{
140{
147− if (m_timeSource && m_timeSource->parent() == this)
148− delete m_timeSource;
149−
150 m_timeSource = timeSource;
141 m_timeSource = timeSource;
151
142
152 if (numSamples() > 0) {
143 if (numSamples() > 0) {
plugins/Ubuntu/Gestures/AxisVelocityCalculator.h+9−16
@@ -24,19 +24,7 @@
24#include "UbuntuGesturesGlobal.h"
24#include "UbuntuGesturesGlobal.h"
25#include <stdint.h>
25#include <stdint.h>
26#include <QtCore/QObject>
26#include <QtCore/QObject>
27−
27+#include "TimeSource.h"
28−namespace UbuntuGestures {
29−/*
30− Interface for a time source.
31− */
32−class UBUNTUGESTURES_EXPORT TimeSource : public QObject {
33− Q_OBJECT
34−public:
35− virtual ~TimeSource() {}
36− /* Returns the current time in milliseconds since some reference time in the past. */
37− virtual qint64 msecsSinceReference() = 0;
38−};
39−}
40
28
41/*
29/*
42 Estimates the current velocity of a finger based on recent movement along an axis
30 Estimates the current velocity of a finger based on recent movement along an axis
@@ -73,10 +61,15 @@ class UBUNTUGESTURES_EXPORT AxisVelocityCalculator : public QObject
73public:
61public:
74
62
75 /*
63 /*
76− Regular constructor
64+ Regular, simple, constructor
77 */
65 */
78 AxisVelocityCalculator(QObject *parent = 0);
66 AxisVelocityCalculator(QObject *parent = 0);
79
67
68+ /*
69+ Constructor that takes a TimeSource
70+ */
71+ AxisVelocityCalculator(const UbuntuGestures::SharedTimeSource &timeSource, QObject *parent = 0);
72+
80 virtual ~AxisVelocityCalculator();
73 virtual ~AxisVelocityCalculator();
81
74
82 qreal trackedPosition() const;
75 qreal trackedPosition() const;
@@ -97,7 +90,7 @@ public:
97 /*
90 /*
98 Replaces the TimeSource with the given one. Useful for testing purposes.
91 Replaces the TimeSource with the given one. Useful for testing purposes.
99 */
92 */
100− void setTimeSource(UbuntuGestures::TimeSource *timeSource);
93+ void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
101
94
102 /*
95 /*
103 The minimum amount of samples needed for a velocity calculation.
96 The minimum amount of samples needed for a velocity calculation.
@@ -145,7 +138,7 @@ private:
145 int m_samplesRead; /* index of the oldest sample available. -1 if buffer is empty */
138 int m_samplesRead; /* index of the oldest sample available. -1 if buffer is empty */
146 int m_samplesWrite; /* index where the next sample will be written */
139 int m_samplesWrite; /* index where the next sample will be written */
147
140
148− UbuntuGestures::TimeSource *m_timeSource;
141+ UbuntuGestures::SharedTimeSource m_timeSource;
149
142
150 qreal m_trackedPosition;
143 qreal m_trackedPosition;
151};
144};
plugins/Ubuntu/Gestures/CMakeLists.txt+1
@@ -6,6 +6,7 @@ set(UbuntuGestureQml_SOURCES
6 AxisVelocityCalculator.cpp
6 AxisVelocityCalculator.cpp
7 Direction.cpp
7 Direction.cpp
8 DirectionalDragArea.cpp
8 DirectionalDragArea.cpp
9+ TimeSource.cpp
9)
10)
10
11
11add_definitions(-DUBUNTUGESTURES_LIBRARY)
12add_definitions(-DUBUNTUGESTURES_LIBRARY)
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+307−71
@@ -18,6 +18,75 @@
18
18
19#include <QtCore/qmath.h>
19#include <QtCore/qmath.h>
20#include <QtCore/QTimer>
20#include <QtCore/QTimer>
21+#include <QDebug>
22+
23+using namespace UbuntuGestures;
24+
25+#define DIRECTIONALDRAGAREA_DEBUG 0
26+
27+#if DIRECTIONALDRAGAREA_DEBUG
28+#define DDA_DEBUG(msg) qDebug("[DDA] " msg)
29+namespace {
30+QString touchPointStateToString(Qt::TouchPointState state) {
31+ switch (state) {
32+ case Qt::TouchPointPressed:
33+ return QString("pressed");
34+ case Qt::TouchPointMoved:
35+ return QString("moved");
36+ case Qt::TouchPointStationary:
37+ return QString("stationary");
38+ default: // Qt::TouchPointReleased:
39+ return QString("released");
40+ }
41+}
42+QString touchEventToString(QTouchEvent *ev)
43+{
44+ QString message;
45+
46+ switch (ev->type()) {
47+ case QEvent::TouchBegin:
48+ message.append("TouchBegin ");
49+ break;
50+ case QEvent::TouchUpdate:
51+ message.append("TouchUpdate ");
52+ break;
53+ case QEvent::TouchEnd:
54+ message.append("TouchEnd ");
55+ break;
56+ default: //QEvent::TouchCancel
57+ message.append("TouchCancel ");
58+ }
59+
60+ for (int i=0; i < ev->touchPoints().size(); ++i) {
61+
62+ const QTouchEvent::TouchPoint& touchPoint = ev->touchPoints().at(i);
63+ message.append(
64+ QString("(id:%1, state:%2, scenePos:(%3,%4)) ")
65+ .arg(touchPoint.id())
66+ .arg(touchPointStateToString(touchPoint.state()))
67+ .arg(touchPoint.scenePos().x())
68+ .arg(touchPoint.scenePos().y())
69+ );
70+ }
71+
72+ return message;
73+}
74+
75+const char *statusToString(DirectionalDragArea::Status status)
76+{
77+ if (status == DirectionalDragArea::WaitingForTouch) {
78+ return "WaitingForTouch";
79+ } else if (status == DirectionalDragArea::Undecided) {
80+ return "Undecided";
81+ } else {
82+ return "Recognized";
83+ }
84+}
85+
86+} // namespace {
87+#else // DIRECTIONALDRAGAREA_DEBUG
88+#define DDA_DEBUG(msg) do{}while(0)
89+#endif // DIRECTIONALDRAGAREA_DEBUG
21
90
22// Essentially a QTimer wrapper
91// Essentially a QTimer wrapper
23class RecognitionTimer : public UbuntuGestures::AbstractTimer
92class RecognitionTimer : public UbuntuGestures::AbstractTimer
@@ -48,9 +117,12 @@ DirectionalDragArea::DirectionalDragArea(QQuickItem *parent)
48 , m_minSpeed(0)
117 , m_minSpeed(0)
49 , m_maxSilenceTime(200)
118 , m_maxSilenceTime(200)
50 , m_silenceTime(0)
119 , m_silenceTime(0)
120+ , m_compositionTime(60)
51 , m_numSamplesOnLastSpeedCheck(0)
121 , m_numSamplesOnLastSpeedCheck(0)
52 , m_recognitionTimer(0)
122 , m_recognitionTimer(0)
53 , m_velocityCalculator(0)
123 , m_velocityCalculator(0)
124+ , m_timeSource(new RealTimeSource)
125+ , m_activeTouches(m_timeSource)
54{
126{
55 setRecognitionTimer(new RecognitionTimer(this));
127 setRecognitionTimer(new RecognitionTimer(this));
56 m_recognitionTimer->setInterval(60);
128 m_recognitionTimer->setInterval(60);
@@ -73,8 +145,8 @@ void DirectionalDragArea::setDirection(Direction::Type direction)
73
145
74void DirectionalDragArea::setMaxDeviation(qreal value)
146void DirectionalDragArea::setMaxDeviation(qreal value)
75{
147{
76− if (m_dampedPos.maxDelta() != value) {
148+ if (m_dampedScenePos.maxDelta() != value) {
77− m_dampedPos.setMaxDelta(value);
149+ m_dampedScenePos.setMaxDelta(value);
78 Q_EMIT maxDeviationChanged(value);
150 Q_EMIT maxDeviationChanged(value);
79 }
151 }
80}
152}
@@ -118,6 +190,14 @@ void DirectionalDragArea::setMaxSilenceTime(int value)
118 }
190 }
119}
191}
120
192
193+void DirectionalDragArea::setCompositionTime(int value)
194+{
195+ if (m_compositionTime != value) {
196+ m_compositionTime = value;
197+ Q_EMIT compositionTimeChanged(value);
198+ }
199+}
200+
121void DirectionalDragArea::setRecognitionTimer(UbuntuGestures::AbstractTimer *timer)
201void DirectionalDragArea::setRecognitionTimer(UbuntuGestures::AbstractTimer *timer)
122{
202{
123 int interval = 0;
203 int interval = 0;
@@ -141,9 +221,11 @@ void DirectionalDragArea::setRecognitionTimer(UbuntuGestures::AbstractTimer *tim
141 }
221 }
142}
222}
143
223
144−void DirectionalDragArea::setTimeSource(UbuntuGestures::TimeSource *timeSource)
224+void DirectionalDragArea::setTimeSource(const SharedTimeSource &timeSource)
145{
225{
226+ m_timeSource = timeSource;
146 m_velocityCalculator->setTimeSource(timeSource);
227 m_velocityCalculator->setTimeSource(timeSource);
228+ m_activeTouches.m_timeSource = timeSource;
147}
229}
148
230
149qreal DirectionalDragArea::distance() const
231qreal DirectionalDragArea::distance() const
@@ -186,6 +268,12 @@ qreal DirectionalDragArea::touchSceneY() const
186
268
187void DirectionalDragArea::touchEvent(QTouchEvent *event)
269void DirectionalDragArea::touchEvent(QTouchEvent *event)
188{
270{
271+ #if DIRECTIONALDRAGAREA_DEBUG
272+ // TODO Consider using qCDebug() when available (Qt 5.2)
273+ qDebug() << "[DDA]" << m_timeSource->msecsSinceReference()
274+ << qPrintable(touchEventToString(event));
275+ #endif
276+
189 if (!isEnabled() || !isVisible()) {
277 if (!isEnabled() || !isVisible()) {
190 QQuickItem::touchEvent(event);
278 QQuickItem::touchEvent(event);
191 return;
279 return;
@@ -198,76 +286,124 @@ void DirectionalDragArea::touchEvent(QTouchEvent *event)
198 case Undecided:
286 case Undecided:
199 touchEvent_undecided(event);
287 touchEvent_undecided(event);
200 break;
288 break;
201− case Recognized:
289+ default: // Recognized:
202 touchEvent_recognized(event);
290 touchEvent_recognized(event);
203 break;
291 break;
204− default: // Rejected
205− touchEvent_rejected(event);
206− break;
207 }
292 }
293+
294+ m_activeTouches.update(event);
208}
295}
209
296
210void DirectionalDragArea::touchEvent_absent(QTouchEvent *event)
297void DirectionalDragArea::touchEvent_absent(QTouchEvent *event)
211{
298{
212− if ((event->touchPointStates() && (Qt::TouchPointPressed || Qt::TouchPointMoved))
299+ if (!event->touchPointStates().testFlag(Qt::TouchPointPressed)) {
213− && event->touchPoints().count() == 1) {
300+ // Nothing to see here. No touch starting in this event.
214− const QTouchEvent::TouchPoint &touchPoint = event->touchPoints()[0];
301+ return;
215− m_startPos = touchPoint.pos();
302+ }
216− m_startScenePos = touchPoint.scenePos();
217− m_touchId = touchPoint.id();
218− m_dampedPos.reset(m_startPos);
219− updateVelocityCalculator(m_startPos);
220− m_velocityCalculator->reset();
221− m_numSamplesOnLastSpeedCheck = 0;
222− m_silenceTime = 0;
223− setPreviousPos(m_startPos);
224− setPreviousScenePos(m_startScenePos);
225
303
226− if (m_distanceThreshold > 0)
304+ if (isWithinTouchCompositionWindow()) {
227− setStatus(Undecided);
305+ // too close to the last touch start. So we consider them as starting roughly at the same time.
228− else
306+ // Can't be a single-touch gesture.
229− setStatus(Recognized);
307+ #if DIRECTIONALDRAGAREA_DEBUG
308+ qDebug("[DDA] A new touch point came in but we're still within time composition window. Ignoring it.");
309+ #endif
310+ return;
230 }
311 }
312+
313+ const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
314+
315+ const QTouchEvent::TouchPoint *newTouchPoint = nullptr;
316+ for (int i = 0; i < touchPoints.count(); ++i) {
317+ const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
318+ if (touchPoint.state() == Qt::TouchPointPressed) {
319+ if (newTouchPoint) {
320+ // more than one touch starting in this QTouchEvent. Can't be a single-touch gesture
321+ return;
322+ } else {
323+ // that's our candidate
324+ m_touchId = touchPoint.id();
325+ newTouchPoint = &touchPoint;
326+ }
327+ }
328+ }
329+
330+ Q_ASSERT(newTouchPoint);
331+
332+ // If we have made this far, we are good to go to the next status.
333+
334+ m_startPos = newTouchPoint->pos();
335+ m_startScenePos = newTouchPoint->scenePos();
336+ m_touchId = newTouchPoint->id();
337+ m_dampedScenePos.reset(m_startScenePos);
338+ updateVelocityCalculator(m_startScenePos);
339+ m_velocityCalculator->reset();
340+ m_numSamplesOnLastSpeedCheck = 0;
341+ m_silenceTime = 0;
342+ setPreviousPos(m_startPos);
343+ setPreviousScenePos(m_startScenePos);
344+
345+ setStatus(Undecided);
231}
346}
232
347
233void DirectionalDragArea::touchEvent_undecided(QTouchEvent *event)
348void DirectionalDragArea::touchEvent_undecided(QTouchEvent *event)
234{
349{
235 const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
350 const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
351+
352+ if (!touchPoint) {
353+ qCritical() << "DirectionalDragArea[status=Undecided]: touch " << m_touchId
354+ << "missing from QTouchEvent without first reaching state Qt::TouchPointReleased. "
355+ "Considering it as released.";
356+ setStatus(WaitingForTouch);
357+ return;
358+ }
359+
236− const QPointF &touchPos = touchPoint->pos();
360+ const QPointF &touchScenePos = touchPoint->scenePos();
237
361
238 if (touchPoint->state() == Qt::TouchPointReleased) {
362 if (touchPoint->state() == Qt::TouchPointReleased) {
239 // touch has ended before recognition concluded
363 // touch has ended before recognition concluded
364+ DDA_DEBUG("Touch has ended before recognition concluded");
240 setStatus(WaitingForTouch);
365 setStatus(WaitingForTouch);
241 return;
366 return;
242 }
367 }
243
368
244− if (event->touchPointStates().testFlag(Qt::TouchPointPressed)
369+ if (event->touchPointStates().testFlag(Qt::TouchPointPressed) && isWithinTouchCompositionWindow()) {
245− || event->touchPoints().count() > 1) {
246 // multi-finger drags are not accepted
370 // multi-finger drags are not accepted
371+ DDA_DEBUG("Multi-finger drags are not accepted");
247− setStatus(Rejected);
372+ setStatus(WaitingForTouch);
248 return;
373 return;
249 }
374 }
250
375
251− m_previousDampedPos.setX(m_dampedPos.x());
376+ m_previousDampedScenePos.setX(m_dampedScenePos.x());
252− m_previousDampedPos.setY(m_dampedPos.y());
377+ m_previousDampedScenePos.setY(m_dampedScenePos.y());
253− m_dampedPos.update(touchPos);
378+ m_dampedScenePos.update(touchScenePos);
254− updateVelocityCalculator(touchPos);
379+ updateVelocityCalculator(touchScenePos);
255
380
256 if (!pointInsideAllowedArea()) {
381 if (!pointInsideAllowedArea()) {
382+ DDA_DEBUG("Rejecting gesture because touch point is outside allowed area.");
257− setStatus(Rejected);
383+ setStatus(WaitingForTouch);
258 return;
384 return;
259 }
385 }
260
386
261 if (!movingInRightDirection()) {
387 if (!movingInRightDirection()) {
388+ DDA_DEBUG("Rejecting gesture becauuse touch point is moving in the wrong direction.");
262− setStatus(Rejected);
389+ setStatus(WaitingForTouch);
263 return;
390 return;
264 }
391 }
265
392
266− setPreviousPos(touchPos);
393+ setPreviousPos(touchPoint->pos());
267− setPreviousScenePos(touchPoint->scenePos());
394+ setPreviousScenePos(touchScenePos);
268
395
396+ if (isWithinTouchCompositionWindow()) {
397+ // There's still time for some new touch to appear and ruin our party as it would be combined
398+ // with our m_touchId one and therefore deny the possibility of a single-finger gesture.
399+ DDA_DEBUG("Sill within composition window. Let's wait more.");
400+ return;
401+ }
402+
269− if (movedFarEnough(touchPos)) {
403+ if (movedFarEnough(touchScenePos)) {
270 setStatus(Recognized);
404 setStatus(Recognized);
405+ } else {
406+ DDA_DEBUG("Didn't move far enough yet. Let's wait more.");
271 }
407 }
272}
408}
273
409
@@ -275,20 +411,18 @@ void DirectionalDragArea::touchEvent_recognized(QTouchEvent *event)
275{
411{
276 const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
412 const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
277
413
278− setPreviousPos(touchPoint->pos());
279− setPreviousScenePos(touchPoint->scenePos());
280−
281− if (touchPoint->state() == Qt::TouchPointReleased) {
414+ if (!touchPoint) {
415+ qCritical() << "DirectionalDragArea[status=Recognized]: touch " << m_touchId
416+ << "missing from QTouchEvent without first reaching state Qt::TouchPointReleased. "
417+ "Considering it as released.";
282 setStatus(WaitingForTouch);
418 setStatus(WaitingForTouch);
283− }
419+ } else {
284−}
420+ setPreviousPos(touchPoint->pos());
285−
421+ setPreviousScenePos(touchPoint->scenePos());
286−void DirectionalDragArea::touchEvent_rejected(QTouchEvent *event)
287−{
288− const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
289
422
290− if (!touchPoint || touchPoint->state() == Qt::TouchPointReleased) {
423+ if (touchPoint->state() == Qt::TouchPointReleased) {
291− setStatus(WaitingForTouch);
424+ setStatus(WaitingForTouch);
425+ }
292 }
426 }
293}
427}
294
428
@@ -307,8 +441,8 @@ const QTouchEvent::TouchPoint *DirectionalDragArea::fetchTargetTouchPoint(QTouch
307
441
308bool DirectionalDragArea::pointInsideAllowedArea() const
442bool DirectionalDragArea::pointInsideAllowedArea() const
309{
443{
310− qreal dX = m_dampedPos.x() - m_startPos.x();
444+ qreal dX = m_dampedScenePos.x() - m_startScenePos.x();
311− qreal dY = m_dampedPos.y() - m_startPos.y();
445+ qreal dY = m_dampedScenePos.y() - m_startScenePos.y();
312
446
313 switch (m_direction) {
447 switch (m_direction) {
314 case Direction::Upwards:
448 case Direction::Upwards:
@@ -326,22 +460,26 @@ bool DirectionalDragArea::movingInRightDirection() const
326{
460{
327 switch (m_direction) {
461 switch (m_direction) {
328 case Direction::Upwards:
462 case Direction::Upwards:
329− return m_dampedPos.y() <= m_previousDampedPos.y();
463+ return m_dampedScenePos.y() <= m_previousDampedScenePos.y();
330 case Direction::Downwards:
464 case Direction::Downwards:
331− return m_dampedPos.y() >= m_previousDampedPos.y();
465+ return m_dampedScenePos.y() >= m_previousDampedScenePos.y();
332 case Direction::Leftwards:
466 case Direction::Leftwards:
333− return m_dampedPos.x() <= m_previousDampedPos.x();
467+ return m_dampedScenePos.x() <= m_previousDampedScenePos.x();
334 default: // Direction::Rightwards:
468 default: // Direction::Rightwards:
335− return m_dampedPos.x() >= m_previousDampedPos.x();
469+ return m_dampedScenePos.x() >= m_previousDampedScenePos.x();
336 }
470 }
337}
471}
338
472
339bool DirectionalDragArea::movedFarEnough(const QPointF &point) const
473bool DirectionalDragArea::movedFarEnough(const QPointF &point) const
340{
474{
475+ if (m_distanceThreshold > 0) {
341− if (Direction::isHorizontal(m_direction))
476+ if (Direction::isHorizontal(m_direction))
342− return qFabs(point.x() - m_startPos.x()) > m_distanceThreshold;
477+ return qFabs(point.x() - m_startScenePos.x()) > m_distanceThreshold;
343− else
478+ else
344− return qFabs(point.y() - m_startPos.y()) > m_distanceThreshold;
479+ return qFabs(point.y() - m_startScenePos.y()) > m_distanceThreshold;
480+ } else {
481+ return true;
482+ }
345}
483}
346
484
347void DirectionalDragArea::checkSpeed()
485void DirectionalDragArea::checkSpeed()
@@ -351,7 +489,8 @@ void DirectionalDragArea::checkSpeed()
351 qreal minSpeedMsecs = m_minSpeed / 1000.0;
489 qreal minSpeedMsecs = m_minSpeed / 1000.0;
352
490
353 if (speed < minSpeedMsecs) {
491 if (speed < minSpeedMsecs) {
492+ DDA_DEBUG("Rejecting gesture because it's below minimum speed.");
354− setStatus(Rejected);
493+ setStatus(WaitingForTouch);
355 }
494 }
356 }
495 }
357
496
@@ -359,7 +498,8 @@ void DirectionalDragArea::checkSpeed()
359 m_silenceTime += m_recognitionTimer->interval();
498 m_silenceTime += m_recognitionTimer->interval();
360
499
361 if (m_silenceTime > m_maxSilenceTime) {
500 if (m_silenceTime > m_maxSilenceTime) {
501+ DDA_DEBUG("Rejecting gesture because it's silence time has been exceeded.");
362− setStatus(Rejected);
502+ setStatus(WaitingForTouch);
363 }
503 }
364 } else {
504 } else {
365 m_silenceTime = 0;
505 m_silenceTime = 0;
@@ -381,11 +521,13 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
381 m_status = newStatus;
521 m_status = newStatus;
382 Q_EMIT statusChanged(m_status);
522 Q_EMIT statusChanged(m_status);
383
523
524+ #if DIRECTIONALDRAGAREA_DEBUG
525+ qDebug() << "[DDA]" << statusToString(oldStatus) << "->" << statusToString(newStatus);
526+ #endif
527+
384 switch (newStatus) {
528 switch (newStatus) {
385 case WaitingForTouch:
529 case WaitingForTouch:
386− if (oldStatus != DirectionalDragArea::Rejected) {
387− Q_EMIT draggingChanged(false);
530+ Q_EMIT draggingChanged(false);
388− }
389 break;
531 break;
390 case Undecided:
532 case Undecided:
391 m_recognitionTimer->start();
533 m_recognitionTimer->start();
@@ -395,9 +537,6 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
395 if (oldStatus == WaitingForTouch)
537 if (oldStatus == WaitingForTouch)
396 Q_EMIT draggingChanged(true);
538 Q_EMIT draggingChanged(true);
397 break;
539 break;
398− case Rejected:
399− Q_EMIT draggingChanged(false);
400− break;
401 default:
540 default:
402 // no-op
541 // no-op
403 break;
542 break;
@@ -406,8 +545,6 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
406
545
407void DirectionalDragArea::setPreviousPos(const QPointF &point)
546void DirectionalDragArea::setPreviousPos(const QPointF &point)
408{
547{
409− Q_ASSERT(m_status != Rejected);
410−
411 bool xChanged = m_previousPos.x() != point.x();
548 bool xChanged = m_previousPos.x() != point.x();
412 bool yChanged = m_previousPos.y() != point.y();
549 bool yChanged = m_previousPos.y() != point.y();
413
550
@@ -428,8 +565,6 @@ void DirectionalDragArea::setPreviousPos(const QPointF &point)
428
565
429void DirectionalDragArea::setPreviousScenePos(const QPointF &point)
566void DirectionalDragArea::setPreviousScenePos(const QPointF &point)
430{
567{
431− Q_ASSERT(m_status != Rejected);
432−
433 bool xChanged = m_previousScenePos.x() != point.x();
568 bool xChanged = m_previousScenePos.x() != point.x();
434 bool yChanged = m_previousScenePos.y() != point.y();
569 bool yChanged = m_previousScenePos.y() != point.y();
435
570
@@ -457,5 +592,106 @@ void DirectionalDragArea::updateVelocityCalculator(const QPointF &point)
457 }
592 }
458}
593}
459
594
595+bool DirectionalDragArea::isWithinTouchCompositionWindow()
596+{
597+ return !m_activeTouches.isEmpty() &&
598+ m_timeSource->msecsSinceReference() <=
599+ m_activeTouches.mostRecentStartTime() + (qint64)compositionTime();
600+}
601+
602+//************************** ActiveTouchesInfo **************************
603+
604+DirectionalDragArea::ActiveTouchesInfo::ActiveTouchesInfo(const SharedTimeSource &timeSource)
605+ : m_timeSource(timeSource), m_lastUsedIndex(-1)
606+{
607+ // Estimate of the maximum number of active touches we might reach.
608+ // Not a problem if it ends up being an underestimate as this is just
609+ // an optimization.
610+ m_vector.resize(3);
611+}
612+
613+void DirectionalDragArea::ActiveTouchesInfo::update(QTouchEvent *event)
614+{
615+ if (!(event->touchPointStates() & (Qt::TouchPointPressed | Qt::TouchPointReleased))) {
616+ // nothing to update
617+ return;
618+ }
619+
620+ const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
621+ for (int i = 0; i < touchPoints.count(); ++i) {
622+ const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
623+ if (touchPoint.state() == Qt::TouchPointPressed) {
624+ addTouchPoint(touchPoint);
625+ } else if (touchPoint.state() == Qt::TouchPointReleased) {
626+ removeTouchPoint(touchPoint);
627+ }
628+ }
629+}
630+
631+void DirectionalDragArea::ActiveTouchesInfo::addTouchPoint(const QTouchEvent::TouchPoint &touchPoint)
632+{
633+ ActiveTouchInfo &activeTouchInfo = getEmptySlot();
634+ activeTouchInfo.id = touchPoint.id();
635+ activeTouchInfo.startTime = m_timeSource->msecsSinceReference();
636+}
637+
638+void DirectionalDragArea::ActiveTouchesInfo::removeTouchPoint(const QTouchEvent::TouchPoint &touchPoint)
639+{
640+ for (int i = 0; i <= m_lastUsedIndex; ++i) {
641+ if (touchPoint.id() == m_vector.at(i).id) {
642+ freeSlot(i);
643+ return;
644+ }
645+ }
646+ Q_ASSERT(false); // shouldn't reach this point
647+}
648+
649+DirectionalDragArea::ActiveTouchInfo &DirectionalDragArea::ActiveTouchesInfo::getEmptySlot()
650+{
651+ Q_ASSERT(m_lastUsedIndex < m_vector.size());
652+
653+ // Look for an in-between vacancy first
654+ for (int i = 0; i < m_lastUsedIndex; ++i) {
655+ ActiveTouchInfo &activeTouchInfo = m_vector[i];
656+ if (!activeTouchInfo.isValid()) {
657+ return activeTouchInfo;
658+ }
659+ }
660+
661+ ++m_lastUsedIndex;
662+ if (m_lastUsedIndex >= m_vector.size()) {
663+ m_vector.resize(m_lastUsedIndex + 1);
664+ }
665+
666+ return m_vector[m_lastUsedIndex];
667+}
668+
669+void DirectionalDragArea::ActiveTouchesInfo::freeSlot(int index)
670+{
671+ m_vector[index].reset();
672+ if (index == m_lastUsedIndex) {
673+ do {
674+ --m_lastUsedIndex;
675+ } while (m_lastUsedIndex >= 0 && !m_vector.at(m_lastUsedIndex).isValid());
676+ }
677+}
678+
679+qint64 DirectionalDragArea::ActiveTouchesInfo::mostRecentStartTime()
680+{
681+ Q_ASSERT(m_lastUsedIndex >= 0);
682+
683+ qint64 highestStartTime = m_vector.at(0).startTime;
684+ int i = 1;
685+ do {
686+ const ActiveTouchInfo &activeTouchInfo = m_vector.at(i);
687+ if (activeTouchInfo.isValid() && activeTouchInfo.startTime > highestStartTime) {
688+ highestStartTime = activeTouchInfo.startTime;
689+ }
690+ ++i;
691+ } while (i < m_lastUsedIndex);
692+
693+ return highestStartTime;
694+}
695+
460// Because we are defining a new QObject-based class (RecognitionTimer) here.
696// Because we are defining a new QObject-based class (RecognitionTimer) here.
461#include "DirectionalDragArea.moc"
697#include "DirectionalDragArea.moc"
plugins/Ubuntu/Gestures/DirectionalDragArea.h+50−13
@@ -117,9 +117,17 @@ class UBUNTUGESTURES_EXPORT DirectionalDragArea : public QQuickItem {
117 Q_PROPERTY(int maxSilenceTime READ maxSilenceTime
117 Q_PROPERTY(int maxSilenceTime READ maxSilenceTime
118 WRITE setMaxSilenceTime
118 WRITE setMaxSilenceTime
119 NOTIFY maxSilenceTimeChanged)
119 NOTIFY maxSilenceTimeChanged)
120+
120 //
121 //
121 /////
122 /////
122
123
124+ // Maximum time (in milliseconds) after the start of a given touch point where
125+ // subsequent touch starts are grouped with the first one into an N-touches gesture
126+ // (e.g. a two-fingers tap or drag).
127+ Q_PROPERTY(int compositionTime READ compositionTime
128+ WRITE setCompositionTime
129+ NOTIFY compositionTimeChanged)
130+
123 Q_ENUMS(Direction)
131 Q_ENUMS(Direction)
124 Q_ENUMS(Status)
132 Q_ENUMS(Status)
125public:
133public:
@@ -130,26 +138,23 @@ public:
130
138
131 // Describes the state of the directional drag gesture.
139 // Describes the state of the directional drag gesture.
132 enum Status {
140 enum Status {
133− // There's no touch point over this area.
141+ // Waiting for a new touch point to land on this area. No gesture is being processed
142+ // or tracked.
134 WaitingForTouch,
143 WaitingForTouch,
135
144
136 // A touch point has landed on this area but it's not know yet whether it is
145 // A touch point has landed on this area but it's not know yet whether it is
137 // performing a drag in the correct direction.
146 // performing a drag in the correct direction.
147+ // If it's decided that the touch point is not performing a directional drag gesture,
148+ // it will be rejected/ignored and status will return to WaitingForTouch.
138 Undecided, //Recognizing,
149 Undecided, //Recognizing,
139
150
140 // There's a touch point in this area and it performed a drag in the correct
151 // There's a touch point in this area and it performed a drag in the correct
141 // direction.
152 // direction.
142 //
153 //
143− // Once recognized, the gesture state will move back to Absent only once
154+ // Once recognized, the gesture state will move back to WaitingForTouch only once
144 // that touch point ends. The gesture will remain in the Recognized state even if
155 // that touch point ends. The gesture will remain in the Recognized state even if
145 // the touch point starts moving in other directions or halts.
156 // the touch point starts moving in other directions or halts.
146 Recognized,
157 Recognized,
147−
148− // A gesture was performed but it wasn't a single-touch drag in the correct
149− // direction.
150− // It will remain in this state until there are no more touch points over this
151− // area, at which point it will move to Absent state.
152− Rejected
153 };
158 };
154 Status status() const { return m_status; }
159 Status status() const { return m_status; }
155
160
@@ -164,7 +169,7 @@ public:
164
169
165 bool dragging() const { return (m_status == Undecided) || (m_status == Recognized); }
170 bool dragging() const { return (m_status == Undecided) || (m_status == Recognized); }
166
171
167− qreal maxDeviation() const { return m_dampedPos.maxDelta(); }
172+ qreal maxDeviation() const { return m_dampedScenePos.maxDelta(); }
168 void setMaxDeviation(qreal value);
173 void setMaxDeviation(qreal value);
169
174
170 qreal wideningAngle() const;
175 qreal wideningAngle() const;
@@ -179,13 +184,16 @@ public:
179 int maxSilenceTime() const { return m_maxSilenceTime; }
184 int maxSilenceTime() const { return m_maxSilenceTime; }
180 void setMaxSilenceTime(int value);
185 void setMaxSilenceTime(int value);
181
186
187+ int compositionTime() const { return m_compositionTime; }
188+ void setCompositionTime(int value);
189+
182 // Replaces the existing Timer with the given one.
190 // Replaces the existing Timer with the given one.
183 //
191 //
184 // Useful for providing a fake timer when testing.
192 // Useful for providing a fake timer when testing.
185 void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
193 void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
186
194
187 // Useful for testing, where a fake time source can be supplied
195 // Useful for testing, where a fake time source can be supplied
188− void setTimeSource(UbuntuGestures::TimeSource *timeSource);
196+ void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
189
197
190Q_SIGNALS:
198Q_SIGNALS:
191 void directionChanged(Direction::Type direction);
199 void directionChanged(Direction::Type direction);
@@ -198,6 +206,7 @@ Q_SIGNALS:
198 void distanceThresholdChanged(qreal value);
206 void distanceThresholdChanged(qreal value);
199 void minSpeedChanged(qreal value);
207 void minSpeedChanged(qreal value);
200 void maxSilenceTimeChanged(int value);
208 void maxSilenceTimeChanged(int value);
209+ void compositionTimeChanged(int value);
201 void touchXChanged(qreal value);
210 void touchXChanged(qreal value);
202 void touchYChanged(qreal value);
211 void touchYChanged(qreal value);
203 void touchSceneXChanged(qreal value);
212 void touchSceneXChanged(qreal value);
@@ -213,7 +222,6 @@ private:
213 void touchEvent_absent(QTouchEvent *event);
222 void touchEvent_absent(QTouchEvent *event);
214 void touchEvent_undecided(QTouchEvent *event);
223 void touchEvent_undecided(QTouchEvent *event);
215 void touchEvent_recognized(QTouchEvent *event);
224 void touchEvent_recognized(QTouchEvent *event);
216− void touchEvent_rejected(QTouchEvent *event);
217 bool pointInsideAllowedArea() const;
225 bool pointInsideAllowedArea() const;
218 bool movingInRightDirection() const;
226 bool movingInRightDirection() const;
219 bool movedFarEnough(const QPointF &point) const;
227 bool movedFarEnough(const QPointF &point) const;
@@ -222,6 +230,7 @@ private:
222 void setPreviousPos(const QPointF &point);
230 void setPreviousPos(const QPointF &point);
223 void setPreviousScenePos(const QPointF &point);
231 void setPreviousScenePos(const QPointF &point);
224 void updateVelocityCalculator(const QPointF &point);
232 void updateVelocityCalculator(const QPointF &point);
233+ bool isWithinTouchCompositionWindow();
225
234
226 Status m_status;
235 Status m_status;
227
236
@@ -233,8 +242,8 @@ private:
233
242
234 // A movement damper is used in some of the gesture recognition calculations
243 // A movement damper is used in some of the gesture recognition calculations
235 // to get rid of noise or small oscillations in the touch position.
244 // to get rid of noise or small oscillations in the touch position.
236− DampedPointF m_dampedPos;
245+ DampedPointF m_dampedScenePos;
237− QPointF m_previousDampedPos;
246+ QPointF m_previousDampedScenePos;
238
247
239 Direction::Type m_direction;
248 Direction::Type m_direction;
240 qreal m_wideningAngle; // in degrees
249 qreal m_wideningAngle; // in degrees
@@ -243,9 +252,37 @@ private:
243 qreal m_minSpeed;
252 qreal m_minSpeed;
244 int m_maxSilenceTime; // in milliseconds
253 int m_maxSilenceTime; // in milliseconds
245 int m_silenceTime; // in milliseconds
254 int m_silenceTime; // in milliseconds
255+ int m_compositionTime; // in milliseconds
246 int m_numSamplesOnLastSpeedCheck;
256 int m_numSamplesOnLastSpeedCheck;
247 UbuntuGestures::AbstractTimer *m_recognitionTimer;
257 UbuntuGestures::AbstractTimer *m_recognitionTimer;
248 AxisVelocityCalculator *m_velocityCalculator;
258 AxisVelocityCalculator *m_velocityCalculator;
259+
260+ UbuntuGestures::SharedTimeSource m_timeSource;
261+
262+ // Information about an active touch point
263+ struct ActiveTouchInfo {
264+ ActiveTouchInfo() : id(-1), startTime(-1) {}
265+ bool isValid() const { return id != -1; }
266+ void reset() { id = -1; }
267+ int id;
268+ qint64 startTime;
269+ };
270+ class ActiveTouchesInfo {
271+ public:
272+ ActiveTouchesInfo(const UbuntuGestures::SharedTimeSource &timeSource);
273+ void update(QTouchEvent *event);
274+ ActiveTouchInfo &touchInfo(int id);
275+ qint64 mostRecentStartTime();
276+ UbuntuGestures::SharedTimeSource m_timeSource;
277+ bool isEmpty() const { return m_lastUsedIndex == -1; }
278+ private:
279+ void addTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
280+ ActiveTouchInfo &getEmptySlot();
281+ void freeSlot(int index);
282+ void removeTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
283+ QVector<struct ActiveTouchInfo> m_vector;
284+ int m_lastUsedIndex;
285+ } m_activeTouches;
249};
286};
250
287
251#endif // DIRECTIONAL_DRAG_AREA_H
288#endif // DIRECTIONAL_DRAG_AREA_H
plugins/Ubuntu/Gestures/TimeSource.cppnew file+49
@@ -0,0 +1,49 @@
1+/*
2+ * Copyright (C) 2013 - Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU Lesser General Public License, as
6+ * published by the Free Software Foundation; either version 2.1 or 3.0
7+ * of the License.
8+ *
9+ * This program is distributed in the hope that it will be useful, but
10+ * WITHOUT ANY WARRANTY; without even the implied warranties of
11+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12+ * PURPOSE. See the applicable version of the GNU Lesser General Public
13+ * License for more details.
14+ *
15+ * You should have received a copy of both the GNU Lesser General Public
16+ * License along with this program. If not, see <http://www.gnu.org/licenses/>
17+ *
18+ * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19+ */
20+
21+#include "TimeSource.h"
22+
23+#include <QElapsedTimer>
24+
25+namespace UbuntuGestures {
26+class RealTimeSourcePrivate {
27+public:
28+ QElapsedTimer timer;
29+};
30+}
31+
32+using namespace UbuntuGestures;
33+
34+RealTimeSource::RealTimeSource()
35+ : UbuntuGestures::TimeSource()
36+ , d(new RealTimeSourcePrivate)
37+{
38+ d->timer.start();
39+}
40+
41+RealTimeSource::~RealTimeSource()
42+{
43+ delete d;
44+}
45+
46+qint64 RealTimeSource::msecsSinceReference()
47+{
48+ return d->timer.elapsed();
49+}
plugins/Ubuntu/Gestures/TimeSource.hnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2013 - Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU Lesser General Public License, as
6+ * published by the Free Software Foundation; either version 2.1 or 3.0
7+ * of the License.
8+ *
9+ * This program is distributed in the hope that it will be useful, but
10+ * WITHOUT ANY WARRANTY; without even the implied warranties of
11+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12+ * PURPOSE. See the applicable version of the GNU Lesser General Public
13+ * License for more details.
14+ *
15+ * You should have received a copy of both the GNU Lesser General Public
16+ * License along with this program. If not, see <http://www.gnu.org/licenses/>
17+ *
18+ * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19+ */
20+
21+#ifndef UBUNTUGESTURES_TIMESOURCE_H
22+#define UBUNTUGESTURES_TIMESOURCE_H
23+
24+#include "UbuntuGesturesGlobal.h"
25+#include <QSharedPointer>
26+
27+namespace UbuntuGestures {
28+/*
29+ Interface for a time source.
30+ */
31+class UBUNTUGESTURES_EXPORT TimeSource {
32+public:
33+ virtual ~TimeSource() {}
34+ /* Returns the current time in milliseconds since some reference time in the past. */
35+ virtual qint64 msecsSinceReference() = 0;
36+};
37+typedef QSharedPointer<TimeSource> SharedTimeSource;
38+
39+/*
40+ Implementation of a time source
41+ */
42+class RealTimeSourcePrivate;
43+class RealTimeSource : public TimeSource {
44+public:
45+ RealTimeSource();
46+ virtual ~RealTimeSource();
47+ qint64 msecsSinceReference() override;
48+private:
49+ RealTimeSourcePrivate *d;
50+};
51+
52+} // namespace UbuntuGestures
53+
54+#endif // UBUNTUGESTURES_TIMESOURCE_H
plugins/Unity/Indicators/qml/IndicatorWidget.qml+1−1
@@ -24,5 +24,5 @@ IndicatorBase {
24 id: indicatorWidget
24 id: indicatorWidget
25
25
26 enabled: false
26 enabled: false
27− property int iconSize: height - units.gu(0.5)
27+ property int iconSize: height
28}
28}
plugins/Unity/Indicators/qml/SliderMenuItem.qml+3−2
@@ -51,12 +51,12 @@ FramedMenuItem {
51
51
52 control: Item {
52 control: Item {
53 id: row
53 id: row
54− width: sliderMenu.text ? units.gu(20) : menuItem.width - (2 * menuItem.__contentsMargins)
54+ width: menuItem.text ? units.gu(20) : menuItem.width - (2 * menuItem.__contentsMargins)
55 height: slider.height
55 height: slider.height
56
56
57 Image {
57 Image {
58 id: leftImage
58 id: leftImage
59− visible: source != ""
59+ visible: status === Image.Ready
60 anchors.left: row.left
60 anchors.left: row.left
61 anchors.verticalCenter: row.verticalCenter
61 anchors.verticalCenter: row.verticalCenter
62 height: units.gu(4)
62 height: units.gu(4)
@@ -96,6 +96,7 @@ FramedMenuItem {
96
96
97 Image {
97 Image {
98 id: rightImage
98 id: rightImage
99+ visible: status === Image.Ready
99 anchors.right: row.right
100 anchors.right: row.right
100 anchors.verticalCenter: row.verticalCenter
101 anchors.verticalCenter: row.verticalCenter
101 height: units.gu(4)
102 height: units.gu(4)
plugins/Unity/Indicators/unitymenumodelstack.cpp+98−7
@@ -19,6 +19,64 @@
19
19
20#include "unitymenumodelstack.h"
20#include "unitymenumodelstack.h"
21
21
22+#include <QDebug>
23+#include <unitymenumodel.h>
24+
25+class UnityMenuModelEntry : public QObject {
26+ Q_OBJECT
27+public:
28+ UnityMenuModelEntry(UnityMenuModel* model, UnityMenuModel* parentModel, int index)
29+ : m_model(model),
30+ m_parentModel(parentModel),
31+ m_index(index)
32+ {
33+ if (m_parentModel) {
34+ QObject::connect(m_parentModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(onRowsInserted(QModelIndex, int, int)));
35+ QObject::connect(m_parentModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(onRowsRemoved(QModelIndex, int, int)));
36+ QObject::connect(m_parentModel, SIGNAL(modelReset()), this, SLOT(onModelReset()));
37+ }
38+ }
39+
40+ UnityMenuModel* model() const { return m_model; }
41+
42+private Q_SLOTS:
43+ void onRowsInserted(const QModelIndex&, int start, int end)
44+ {
45+ int delta = end-start + 1;
46+ if (start <= m_index) {
47+ m_index += delta;
48+ }
49+ }
50+
51+ void onRowsRemoved(const QModelIndex&, int start, int end)
52+ {
53+ int delta = end-start + 1;
54+ if (start <= m_index) {
55+ if (start + delta > m_index) {
56+ // in the range removed
57+ Q_EMIT remove();
58+ disconnect(m_parentModel, 0, this, 0);
59+ } else {
60+ m_index -= delta;
61+ }
62+ }
63+ }
64+
65+ void onModelReset()
66+ {
67+ Q_EMIT remove();
68+ disconnect(m_parentModel, 0, this, 0);
69+ }
70+
71+Q_SIGNALS:
72+ void remove();
73+
74+private:
75+ UnityMenuModel* m_model;
76+ UnityMenuModel* m_parentModel;
77+ int m_index;
78+};
79+
22UnityMenuModelStack::UnityMenuModelStack(QObject* parent)
80UnityMenuModelStack::UnityMenuModelStack(QObject* parent)
23 : QObject(parent)
81 : QObject(parent)
24{
82{
@@ -26,31 +84,44 @@ UnityMenuModelStack::UnityMenuModelStack(QObject* parent)
26
84
27UnityMenuModelStack::~UnityMenuModelStack()
85UnityMenuModelStack::~UnityMenuModelStack()
28{
86{
87+ qDeleteAll(m_menuModels);
88+ m_menuModels.clear();
29}
89}
30
90
31UnityMenuModel* UnityMenuModelStack::head() const
91UnityMenuModel* UnityMenuModelStack::head() const
32{
92{
33− return !m_menuModels.isEmpty() ? m_menuModels.first() : NULL;
93+ return !m_menuModels.isEmpty() ? m_menuModels.first()->model() : NULL;
34}
94}
35
95
36void UnityMenuModelStack::setHead(UnityMenuModel* model)
96void UnityMenuModelStack::setHead(UnityMenuModel* model)
37{
97{
38 if (head() != model) {
98 if (head() != model) {
99+ qDeleteAll(m_menuModels);
39 m_menuModels.clear();
100 m_menuModels.clear();
101+
40− push(model);
102+ push(model, 0);
41 Q_EMIT headChanged(model);
103 Q_EMIT headChanged(model);
42 }
104 }
43}
105}
44
106
45UnityMenuModel* UnityMenuModelStack::tail() const
107UnityMenuModel* UnityMenuModelStack::tail() const
46{
108{
47− return !m_menuModels.isEmpty() ? m_menuModels.last() : NULL;
109+ return !m_menuModels.isEmpty() ? m_menuModels.last()->model() : NULL;
110+}
111+
112+int UnityMenuModelStack::count() const
113+{
114+ return m_menuModels.count();
48}
115}
49
116
50−void UnityMenuModelStack::push(UnityMenuModel* model)
117+void UnityMenuModelStack::push(UnityMenuModel* model, int index)
51{
118{
119+ UnityMenuModelEntry* entry = new UnityMenuModelEntry(model, tail(), index);
120+ QObject::connect(entry, SIGNAL(remove()), SLOT(onRemove()));
121+
52− m_menuModels << model;
122+ m_menuModels << entry;
53 Q_EMIT tailChanged(model);
123 Q_EMIT tailChanged(model);
124+ Q_EMIT countChanged(m_menuModels.count());
54}
125}
55
126
56UnityMenuModel* UnityMenuModelStack::pop()
127UnityMenuModel* UnityMenuModelStack::pop()
@@ -58,12 +129,32 @@ UnityMenuModel* UnityMenuModelStack::pop()
58 if (m_menuModels.isEmpty()) {
129 if (m_menuModels.isEmpty()) {
59 return NULL;
130 return NULL;
60 }
131 }
61− UnityMenuModel* model = m_menuModels.takeLast();
132+ UnityMenuModelEntry* entry = m_menuModels.takeLast();
133+ UnityMenuModel* model = entry->model();
134+ entry->deleteLater();
62
135
63 Q_EMIT tailChanged(tail());
136 Q_EMIT tailChanged(tail());
64 if (m_menuModels.isEmpty()) {
137 if (m_menuModels.isEmpty()) {
65 Q_EMIT headChanged(NULL);
138 Q_EMIT headChanged(NULL);
66 }
139 }
140+ Q_EMIT countChanged(m_menuModels.count());
67
141
68 return model;
142 return model;
69−}
143+}
144+
145+void UnityMenuModelStack::onRemove()
146+{
147+ UnityMenuModelEntry* removed = qobject_cast<UnityMenuModelEntry*>(sender());
148+ if (!m_menuModels.contains(removed))
149+ return;
150+
151+ for (int i = m_menuModels.count() -1; i >= 0; i--) {
152+ UnityMenuModelEntry* entry = m_menuModels[i];
153+ pop();
154+ if (entry == removed) {
155+ break;
156+ }
157+ }
158+}
159+
160+#include "unitymenumodelstack.moc"
plugins/Unity/Indicators/unitymenumodelstack.h+10−2
@@ -25,6 +25,7 @@
25#include <QObject>
25#include <QObject>
26#include <QList>
26#include <QList>
27
27
28+class UnityMenuModelEntry;
28class UnityMenuModel;
29class UnityMenuModel;
29
30
30// A LIFO queue for storing the current submenu of a UnityMenuModel.
31// A LIFO queue for storing the current submenu of a UnityMenuModel.
@@ -37,6 +38,7 @@ class UNITYINDICATORS_EXPORT UnityMenuModelStack : public QObject
37 Q_OBJECT
38 Q_OBJECT
38 Q_PROPERTY(UnityMenuModel* head READ head WRITE setHead NOTIFY headChanged)
39 Q_PROPERTY(UnityMenuModel* head READ head WRITE setHead NOTIFY headChanged)
39 Q_PROPERTY(UnityMenuModel* tail READ tail NOTIFY tailChanged)
40 Q_PROPERTY(UnityMenuModel* tail READ tail NOTIFY tailChanged)
41+ Q_PROPERTY(int count READ count NOTIFY countChanged)
40public:
42public:
41 UnityMenuModelStack(QObject*parent=NULL);
43 UnityMenuModelStack(QObject*parent=NULL);
42 ~UnityMenuModelStack();
44 ~UnityMenuModelStack();
@@ -46,15 +48,21 @@ public:
46
48
47 UnityMenuModel* tail() const;
49 UnityMenuModel* tail() const;
48
50
51+ int count() const;
52+
49− Q_INVOKABLE void push(UnityMenuModel* model);
53+ Q_INVOKABLE void push(UnityMenuModel* model, int menuIndex);
50 Q_INVOKABLE UnityMenuModel* pop();
54 Q_INVOKABLE UnityMenuModel* pop();
51
55
52Q_SIGNALS:
56Q_SIGNALS:
53 void headChanged(UnityMenuModel* head);
57 void headChanged(UnityMenuModel* head);
54 void tailChanged(UnityMenuModel* tail);
58 void tailChanged(UnityMenuModel* tail);
59+ void countChanged(int count);
60+
61+private Q_SLOTS:
62+ void onRemove();
55
63
56private:
64private:
57− QList<UnityMenuModel*> m_menuModels;
65+ QList<UnityMenuModelEntry*> m_menuModels;
58};
66};
59
67
60#endif // UNITYMENUMODELSTACK_H
68#endif // UNITYMENUMODELSTACK_H
po/ar.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-20 19:41+0000\n"
11"PO-Revision-Date: 2013-10-20 19:41+0000\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
13"Language-Team: Arabic <ar@li.org>\n"
13"Language-Team: Arabic <ar@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
19−"X-Launchpad-Export-Date: 2013-10-21 05:04+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
20−"X-Generator: Launchpad (build 16807)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -213,11 +213,15 @@ msgstr "تكلم الآن..."
213msgid "Speaking..."
213msgid "Speaking..."
214msgstr "تتكلم الآن..."
214msgstr "تتكلم الآن..."
215
215
216+#: Notifications/NotificationMenuItemFactory.qml:89
217+msgid "Show password"
218+msgstr ""
219+
216#: Panel/SearchIndicator.qml:27
220#: Panel/SearchIndicator.qml:27
217msgid "Search"
221msgid "Search"
218msgstr "ابحث"
222msgstr "ابحث"
219
223
220−#: plugins/Unity/scope.cpp:398
224+#: plugins/Unity/scope.cpp:408
221msgid "Sorry, there is nothing that matches your search."
225msgid "Sorry, there is nothing that matches your search."
222msgstr "عذراً، لا يوجد ما يطابق بحثك."
226msgstr "عذراً، لا يوجد ما يطابق بحثك."
223
227
po/ast.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-03 14:02+0000\n"
11"PO-Revision-Date: 2013-10-03 14:02+0000\n"
12"Last-Translator: ivarela <ivarela@ubuntu.com>\n"
12"Last-Translator: ivarela <ivarela@ubuntu.com>\n"
13"Language-Team: Asturian <ast@li.org>\n"
13"Language-Team: Asturian <ast@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -209,11 +209,15 @@ msgstr "Fala agora…"
209msgid "Speaking..."
209msgid "Speaking..."
210msgstr "Falando…"
210msgstr "Falando…"
211
211
212+#: Notifications/NotificationMenuItemFactory.qml:89
213+msgid "Show password"
214+msgstr ""
215+
212#: Panel/SearchIndicator.qml:27
216#: Panel/SearchIndicator.qml:27
213msgid "Search"
217msgid "Search"
214msgstr "Guetar"
218msgstr "Guetar"
215
219
216−#: plugins/Unity/scope.cpp:398
220+#: plugins/Unity/scope.cpp:408
217msgid "Sorry, there is nothing that matches your search."
221msgid "Sorry, there is nothing that matches your search."
218msgstr "Sentímoslo, nun hai res que concase cola gueta"
222msgstr "Sentímoslo, nun hai res que concase cola gueta"
219
223
@@ -225,24 +229,3 @@ msgstr "Too"
225#, qt-format
229#, qt-format
226msgid "Please enter %1"
230msgid "Please enter %1"
227msgstr "Introduz %1"
231msgstr "Introduz %1"
228−
229−#~ msgid "New Releases"
230−#~ msgstr "Llanzamientos nuevos"
231−
232−#~ msgid "Featured"
233−#~ msgstr "Destacaos"
234−
235−#~ msgid "Top Charting"
236−#~ msgstr "Meyor posicionaes"
237−
238−#~ msgid "Recent"
239−#~ msgstr "Recientes"
240−
241−#~ msgid "Videos"
242−#~ msgstr "Vídeos"
243−
244−#~ msgid "Music"
245−#~ msgstr "Música"
246−
247−#~ msgid "Popular Online"
248−#~ msgstr "Populares en llinia"
po/az.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-26 23:48+0000\n"
11"PO-Revision-Date: 2013-06-26 23:48+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Söyləyin..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Söylənilir..."
206msgstr "Söylənilir..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Axtar"
214msgstr "Axtar"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
218msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Musiqi"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Videolar"
po/bg.po+8−16
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 00:06+0000\n"
11"PO-Revision-Date: 2013-06-27 00:06+0000\n"
12"Last-Translator: Miroslav E. Hadzhiev (Хаджиев) "
12"Last-Translator: Miroslav E. Hadzhiev (Хаджиев) "
13"<miroslav.hadzhiev@gmail.com>\n"
13"<miroslav.hadzhiev@gmail.com>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=2; plural=n != 1;\n"
18"Plural-Forms: nplurals=2; plural=n != 1;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -206,11 +206,15 @@ msgstr ""
206msgid "Speaking..."
206msgid "Speaking..."
207msgstr ""
207msgstr ""
208
208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209#: Panel/SearchIndicator.qml:27
213#: Panel/SearchIndicator.qml:27
210msgid "Search"
214msgid "Search"
211msgstr "Търсене"
215msgstr "Търсене"
212
216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
218msgid "Sorry, there is nothing that matches your search."
215msgstr "Съжаляваме, няма нищо, което да отговаря на вашето търсене."
219msgstr "Съжаляваме, няма нищо, което да отговаря на вашето търсене."
216
220
@@ -222,15 +226,3 @@ msgstr ""
222#, qt-format
226#, qt-format
223msgid "Please enter %1"
227msgid "Please enter %1"
224msgstr ""
228msgstr ""
225−
226−#~ msgid "Featured"
227−#~ msgstr "Най-отличени"
228−
229−#~ msgid "Recent"
230−#~ msgstr "Най-нови"
231−
232−#~ msgid "Music"
233−#~ msgstr "Музика"
234−
235−#~ msgid "Videos"
236−#~ msgstr "Видеоклипове"
po/ca.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-09-28 07:38+0000\n"
11"PO-Revision-Date: 2013-09-28 07:38+0000\n"
12"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
12"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
13"Language-Team: Catalan <ca@li.org>\n"
13"Language-Team: Catalan <ca@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -211,11 +211,15 @@ msgstr "Parleu..."
211msgid "Speaking..."
211msgid "Speaking..."
212msgstr "S'està parlant..."
212msgstr "S'està parlant..."
213
213
214+#: Notifications/NotificationMenuItemFactory.qml:89
215+msgid "Show password"
216+msgstr ""
217+
214#: Panel/SearchIndicator.qml:27
218#: Panel/SearchIndicator.qml:27
215msgid "Search"
219msgid "Search"
216msgstr "Cerca"
220msgstr "Cerca"
217
221
218−#: plugins/Unity/scope.cpp:398
222+#: plugins/Unity/scope.cpp:408
219msgid "Sorry, there is nothing that matches your search."
223msgid "Sorry, there is nothing that matches your search."
220msgstr "No hi ha res que coincideixi amb la cerca"
224msgstr "No hi ha res que coincideixi amb la cerca"
221
225
@@ -227,24 +231,3 @@ msgstr ""
227#, qt-format
231#, qt-format
228msgid "Please enter %1"
232msgid "Please enter %1"
229msgstr "Introduïu %1"
233msgstr "Introduïu %1"
230−
231−#~ msgid "Music"
232−#~ msgstr "Música"
233−
234−#~ msgid "Videos"
235−#~ msgstr "Vídeos"
236−
237−#~ msgid "Recent"
238−#~ msgstr "Recents"
239−
240−#~ msgid "Featured"
241−#~ msgstr "Destacats"
242−
243−#~ msgid "New Releases"
244−#~ msgstr "Novetats"
245−
246−#~ msgid "Top Charting"
247−#~ msgstr "El millor de les llistes"
248−
249−#~ msgid "Popular Online"
250−#~ msgstr "Popular a la xarxa"
po/cs.po+8−19
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-08 08:09+0000\n"
11"PO-Revision-Date: 2013-10-08 08:09+0000\n"
12"Last-Translator: Tadeáš Pařík <tadeas.parik@gmail.com>\n"
12"Last-Translator: Tadeáš Pařík <tadeas.parik@gmail.com>\n"
13"Language-Team: Czech <cs@li.org>\n"
13"Language-Team: Czech <cs@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -206,11 +206,15 @@ msgstr "Mluvte..."
206msgid "Speaking..."
206msgid "Speaking..."
207msgstr "Mluvte..."
207msgstr "Mluvte..."
208
208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209#: Panel/SearchIndicator.qml:27
213#: Panel/SearchIndicator.qml:27
210msgid "Search"
214msgid "Search"
211msgstr "Hledat"
215msgstr "Hledat"
212
216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
218msgid "Sorry, there is nothing that matches your search."
215msgstr "Je nám líto, ale nic neodpovídá zadání"
219msgstr "Je nám líto, ale nic neodpovídá zadání"
216
220
@@ -222,18 +226,3 @@ msgstr "Vše"
222#, qt-format
226#, qt-format
223msgid "Please enter %1"
227msgid "Please enter %1"
224msgstr "Zadejte prosím %1"
228msgstr "Zadejte prosím %1"
225−
226−#~ msgid "Featured"
227−#~ msgstr "Oblíbené"
228−
229−#~ msgid "Recent"
230−#~ msgstr "Nedávné"
231−
232−#~ msgid "Videos"
233−#~ msgstr "Videa"
234−
235−#~ msgid "Music"
236−#~ msgstr "Hudba"
237−
238−#~ msgid "Popular Online"
239−#~ msgstr "Oblíbené on-line"
po/de.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-18 12:26+0000\n"
11"PO-Revision-Date: 2013-10-18 12:26+0000\n"
12"Last-Translator: Phillip Sz <Unknown>\n"
12"Last-Translator: Phillip Sz <Unknown>\n"
13"Language-Team: German <de@li.org>\n"
13"Language-Team: German <de@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-19 05:30+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16807)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -209,11 +209,15 @@ msgstr "Sprechen Sie jetzt …"
209msgid "Speaking..."
209msgid "Speaking..."
210msgstr "Sie sprechen …"
210msgstr "Sie sprechen …"
211
211
212+#: Notifications/NotificationMenuItemFactory.qml:89
213+msgid "Show password"
214+msgstr ""
215+
212#: Panel/SearchIndicator.qml:27
216#: Panel/SearchIndicator.qml:27
213msgid "Search"
217msgid "Search"
214msgstr "Suchen"
218msgstr "Suchen"
215
219
216−#: plugins/Unity/scope.cpp:398
220+#: plugins/Unity/scope.cpp:408
217msgid "Sorry, there is nothing that matches your search."
221msgid "Sorry, there is nothing that matches your search."
218msgstr "Entschuldigung, es wurden keine Treffer erzielt."
222msgstr "Entschuldigung, es wurden keine Treffer erzielt."
219
223
po/el.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 00:53+0000\n"
11"PO-Revision-Date: 2013-06-27 00:53+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Greek <el@li.org>\n"
13"Language-Team: Greek <el@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Μιλήστε τώρα..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Ομιλία..."
206msgstr "Ομιλία..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Αναζήτηση"
214msgstr "Αναζήτηση"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να ταιριάζει στην αναζήτησή σας."
218msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να ταιριάζει στην αναζήτησή σας."
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Μουσική"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Βίντεο"
po/en_AU.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-09-28 07:46+0000\n"
11"PO-Revision-Date: 2013-09-28 07:46+0000\n"
12"Last-Translator: Jared Norris <jarednorris@ubuntu.com>\n"
12"Last-Translator: Jared Norris <jarednorris@ubuntu.com>\n"
13"Language-Team: English (Australia) <en_AU@li.org>\n"
13"Language-Team: English (Australia) <en_AU@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Speak Now..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Speaking..."
206msgstr "Speaking..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Search"
214msgstr "Search"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Sorry, there is nothing that matches your search."
218msgstr "Sorry, there is nothing that matches your search."
215
219
@@ -221,24 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr "Please enter %1"
227msgstr "Please enter %1"
224−
225−#~ msgid "Featured"
226−#~ msgstr "Featured"
227−
228−#~ msgid "Recent"
229−#~ msgstr "Recent"
230−
231−#~ msgid "New Releases"
232−#~ msgstr "New Releases"
233−
234−#~ msgid "Top Charting"
235−#~ msgstr "Top Charting"
236−
237−#~ msgid "Music"
238−#~ msgstr "Music"
239−
240−#~ msgid "Popular Online"
241−#~ msgstr "Popular Online"
242−
243−#~ msgid "Videos"
244−#~ msgstr "Videos"
po/en_GB.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 08:53+0000\n"
11"PO-Revision-Date: 2013-06-27 08:53+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
13"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Speak Now..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Speaking..."
206msgstr "Speaking..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Search"
214msgstr "Search"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Sorry, there is nothing that matches your search."
218msgstr "Sorry, there is nothing that matches your search."
215
219
@@ -221,24 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr "Please enter %1"
227msgstr "Please enter %1"
224−
225−#~ msgid "Featured"
226−#~ msgstr "Featured"
227−
228−#~ msgid "Recent"
229−#~ msgstr "Recent"
230−
231−#~ msgid "New Releases"
232−#~ msgstr "New Releases"
233−
234−#~ msgid "Top Charting"
235−#~ msgstr "Top Charting"
236−
237−#~ msgid "Music"
238−#~ msgstr "Music"
239−
240−#~ msgid "Popular Online"
241−#~ msgstr "Popular Online"
242−
243−#~ msgid "Videos"
244−#~ msgstr "Videos"
po/eo.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-26 22:35+0000\n"
11"PO-Revision-Date: 2013-06-26 22:35+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Esperanto <eo@li.org>\n"
13"Language-Team: Esperanto <eo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
po/es.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-02 04:59+0000\n"
11"PO-Revision-Date: 2013-10-02 04:59+0000\n"
12"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
12"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
13"Language-Team: Spanish <es@li.org>\n"
13"Language-Team: Spanish <es@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -209,11 +209,15 @@ msgstr "Hable ahora…"
209msgid "Speaking..."
209msgid "Speaking..."
210msgstr "Hablando…"
210msgstr "Hablando…"
211
211
212+#: Notifications/NotificationMenuItemFactory.qml:89
213+msgid "Show password"
214+msgstr ""
215+
212#: Panel/SearchIndicator.qml:27
216#: Panel/SearchIndicator.qml:27
213msgid "Search"
217msgid "Search"
214msgstr "Buscar"
218msgstr "Buscar"
215
219
216−#: plugins/Unity/scope.cpp:398
220+#: plugins/Unity/scope.cpp:408
217msgid "Sorry, there is nothing that matches your search."
221msgid "Sorry, there is nothing that matches your search."
218msgstr "No hay nada que coincida con su búsqueda."
222msgstr "No hay nada que coincida con su búsqueda."
219
223
@@ -225,24 +229,3 @@ msgstr "Todo"
225#, qt-format
229#, qt-format
226msgid "Please enter %1"
230msgid "Please enter %1"
227msgstr "Introduzca %1"
231msgstr "Introduzca %1"
228−
229−#~ msgid "Featured"
230−#~ msgstr "Destacados"
231−
232−#~ msgid "Recent"
233−#~ msgstr "Recientes"
234−
235−#~ msgid "New Releases"
236−#~ msgstr "Lanzamientos nuevos"
237−
238−#~ msgid "Top Charting"
239−#~ msgstr "Mejor posicionadas"
240−
241−#~ msgid "Music"
242−#~ msgstr "Música"
243−
244−#~ msgid "Popular Online"
245−#~ msgstr "Populares en línea"
246−
247−#~ msgid "Videos"
248−#~ msgstr "Vídeos"
po/fa.po+7−3
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-31 19:02+0000\n"
11"PO-Revision-Date: 2013-10-31 19:02+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Persian <fa@li.org>\n"
13"Language-Team: Persian <fa@li.org>\n"
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-11-01 06:44+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19"X-Generator: Launchpad (build 16820)\n"
19"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
po/fi.po+9−26
@@ -7,16 +7,16 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11−"PO-Revision-Date: 2013-10-03 09:21+0000\n"
11+"PO-Revision-Date: 2013-11-11 14:07+0000\n"
12"Last-Translator: Jiri Grönroos <Unknown>\n"
12"Last-Translator: Jiri Grönroos <Unknown>\n"
13"Language-Team: Finnish <fi@li.org>\n"
13"Language-Team: Finnish <fi@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-12 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -207,11 +207,15 @@ msgstr "Puhu nyt..."
207msgid "Speaking..."
207msgid "Speaking..."
208msgstr "Puhutaan..."
208msgstr "Puhutaan..."
209
209
210+#: Notifications/NotificationMenuItemFactory.qml:89
211+msgid "Show password"
212+msgstr "Näytä salasana"
213+
210#: Panel/SearchIndicator.qml:27
214#: Panel/SearchIndicator.qml:27
211msgid "Search"
215msgid "Search"
212msgstr "Hae"
216msgstr "Hae"
213
217
214−#: plugins/Unity/scope.cpp:398
218+#: plugins/Unity/scope.cpp:408
215msgid "Sorry, there is nothing that matches your search."
219msgid "Sorry, there is nothing that matches your search."
216msgstr "Hakuun täsmääviä tuloksia ei löydy."
220msgstr "Hakuun täsmääviä tuloksia ei löydy."
217
221
@@ -223,24 +227,3 @@ msgstr "Kaikki"
223#, qt-format
227#, qt-format
224msgid "Please enter %1"
228msgid "Please enter %1"
225msgstr "Kirjoita %1"
229msgstr "Kirjoita %1"
226−
227−#~ msgid "Featured"
228−#~ msgstr "Suositellut"
229−
230−#~ msgid "Recent"
231−#~ msgstr "Viimeisimmät"
232−
233−#~ msgid "New Releases"
234−#~ msgstr "Uudet julkaisut"
235−
236−#~ msgid "Top Charting"
237−#~ msgstr "Nousukiidossa"
238−
239−#~ msgid "Music"
240−#~ msgstr "Musiikki"
241−
242−#~ msgid "Popular Online"
243−#~ msgstr "Suosittua verkossa"
244−
245−#~ msgid "Videos"
246−#~ msgstr "Videot"
po/fo.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-01 15:13+0000\n"
11"PO-Revision-Date: 2013-10-01 15:13+0000\n"
12"Last-Translator: Jógvan Olsen <jeggy@jebster.net>\n"
12"Last-Translator: Jógvan Olsen <jeggy@jebster.net>\n"
13"Language-Team: Faroese <fo@li.org>\n"
13"Language-Team: Faroese <fo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Snakka nú..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Snakkar..."
206msgstr "Snakkar..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Leita"
214msgstr "Leita"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
218msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Tónleikur"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Sjónbond"
po/fr.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 03:21+0000\n"
11"PO-Revision-Date: 2013-06-27 03:21+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: French <fr@li.org>\n"
13"Language-Team: French <fr@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Musique"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Vidéos"
po/gd.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-09-30 10:34+0000\n"
11"PO-Revision-Date: 2013-09-30 10:34+0000\n"
12"Last-Translator: Akerbeltz <fios@akerbeltz.org>\n"
12"Last-Translator: Akerbeltz <fios@akerbeltz.org>\n"
13"Language-Team: Gaelic; Scottish <gd@li.org>\n"
13"Language-Team: Gaelic; Scottish <gd@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : "
17"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : "
18"(n > 2 && n < 20) ? 2 : 3;\n"
18"(n > 2 && n < 20) ? 2 : 3;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -214,11 +214,15 @@ msgstr "Can rud a-nis..."
214msgid "Speaking..."
214msgid "Speaking..."
215msgstr "A' bruidhinn..."
215msgstr "A' bruidhinn..."
216
216
217+#: Notifications/NotificationMenuItemFactory.qml:89
218+msgid "Show password"
219+msgstr ""
220+
217#: Panel/SearchIndicator.qml:27
221#: Panel/SearchIndicator.qml:27
218msgid "Search"
222msgid "Search"
219msgstr "Lorg"
223msgstr "Lorg"
220
224
221−#: plugins/Unity/scope.cpp:398
225+#: plugins/Unity/scope.cpp:408
222msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
223msgstr "Tha sinn duilich ach chan eil dad a' freagairt ris na lorg thu."
227msgstr "Tha sinn duilich ach chan eil dad a' freagairt ris na lorg thu."
224
228
@@ -230,24 +234,3 @@ msgstr ""
230#, qt-format
234#, qt-format
231msgid "Please enter %1"
235msgid "Please enter %1"
232msgstr "Cuir a-steach %1"
236msgstr "Cuir a-steach %1"
233−
234−#~ msgid "Top Charting"
235−#~ msgstr "Gràinnean-mullaich nan cairt"
236−
237−#~ msgid "Featured"
238−#~ msgstr "Brosnaichte"
239−
240−#~ msgid "Recent"
241−#~ msgstr "O chionn goirid"
242−
243−#~ msgid "New Releases"
244−#~ msgstr "Air ùr-sgaoileadh"
245−
246−#~ msgid "Videos"
247−#~ msgstr "Videothan"
248−
249−#~ msgid "Music"
250−#~ msgstr "Ceòl"
251−
252−#~ msgid "Popular Online"
253−#~ msgstr "Fèill mhòr air air loidhne"
po/gl.po+8−22
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-03 18:49+0000\n"
11"PO-Revision-Date: 2013-10-03 18:49+0000\n"
12"Last-Translator: Marcos Lans <Unknown>\n"
12"Last-Translator: Marcos Lans <Unknown>\n"
13"Language-Team: Galician <gl@li.org>\n"
13"Language-Team: Galician <gl@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -207,11 +207,15 @@ msgstr "Fale agora…"
207msgid "Speaking..."
207msgid "Speaking..."
208msgstr "Falando…"
208msgstr "Falando…"
209
209
210+#: Notifications/NotificationMenuItemFactory.qml:89
211+msgid "Show password"
212+msgstr ""
213+
210#: Panel/SearchIndicator.qml:27
214#: Panel/SearchIndicator.qml:27
211msgid "Search"
215msgid "Search"
212msgstr "Buscar"
216msgstr "Buscar"
213
217
214−#: plugins/Unity/scope.cpp:398
218+#: plugins/Unity/scope.cpp:408
215msgid "Sorry, there is nothing that matches your search."
219msgid "Sorry, there is nothing that matches your search."
216msgstr "Sentímolo, non hai nada que coincida con esta busca."
220msgstr "Sentímolo, non hai nada que coincida con esta busca."
217
221
@@ -223,21 +227,3 @@ msgstr "Todo"
223#, qt-format
227#, qt-format
224msgid "Please enter %1"
228msgid "Please enter %1"
225msgstr "Introduza %1"
229msgstr "Introduza %1"
226−
227−#~ msgid "Music"
228−#~ msgstr "Música"
229−
230−#~ msgid "Videos"
231−#~ msgstr "Vídeos"
232−
233−#~ msgid "Featured"
234−#~ msgstr "Destacado"
235−
236−#~ msgid "Recent"
237−#~ msgstr "Recentes"
238−
239−#~ msgid "New Releases"
240−#~ msgstr "Novas versións"
241−
242−#~ msgid "Popular Online"
243−#~ msgstr "Populares en liña"
po/he.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-01 09:19+0000\n"
11"PO-Revision-Date: 2013-10-01 09:19+0000\n"
12"Last-Translator: Yaron <sh.yaron@gmail.com>\n"
12"Last-Translator: Yaron <sh.yaron@gmail.com>\n"
13"Language-Team: Hebrew <he@li.org>\n"
13"Language-Team: Hebrew <he@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "יש לדבר כעת..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "הדיבור מושמע…"
206msgstr "הדיבור מושמע…"
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "חיפוש"
214msgstr "חיפוש"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה."
218msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה."
215
219
@@ -221,24 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr "נא להזין %1"
227msgstr "נא להזין %1"
224−
225−#~ msgid "Music"
226−#~ msgstr "מוזיקה"
227−
228−#~ msgid "Videos"
229−#~ msgstr "סרטונים"
230−
231−#~ msgid "Top Charting"
232−#~ msgstr "בראש הטבלה"
233−
234−#~ msgid "Featured"
235−#~ msgstr "מומלצים"
236−
237−#~ msgid "Recent"
238−#~ msgstr "אחרונים"
239−
240−#~ msgid "New Releases"
241−#~ msgstr "מהדורות חדשות"
242−
243−#~ msgid "Popular Online"
244−#~ msgstr "פופולריים ברחבי הרשת"
po/hr.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 04:14+0000\n"
11"PO-Revision-Date: 2013-06-27 04:14+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Croatian <hr@li.org>\n"
13"Language-Team: Croatian <hr@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -206,11 +206,15 @@ msgstr "Recite..."
206msgid "Speaking..."
206msgid "Speaking..."
207msgstr "Govor..."
207msgstr "Govor..."
208
208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209#: Panel/SearchIndicator.qml:27
213#: Panel/SearchIndicator.qml:27
210msgid "Search"
214msgid "Search"
211msgstr "Pretraživanje"
215msgstr "Pretraživanje"
212
216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
218msgid "Sorry, there is nothing that matches your search."
215msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
219msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
216
220
@@ -222,9 +226,3 @@ msgstr ""
222#, qt-format
226#, qt-format
223msgid "Please enter %1"
227msgid "Please enter %1"
224msgstr ""
228msgstr ""
225−
226−#~ msgid "Music"
227−#~ msgstr "Glazba"
228−
229−#~ msgid "Videos"
230−#~ msgstr "Video"
po/hu.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 04:28+0000\n"
11"PO-Revision-Date: 2013-06-27 04:28+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Beszéljen most…"
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Beszéd…"
206msgstr "Beszéd…"
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Keresés"
214msgstr "Keresés"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Elnézést, nincs találat a keresésre."
218msgstr "Elnézést, nincs találat a keresésre."
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Zene"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Videók"
po/hy.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 04:43+0000\n"
11"PO-Revision-Date: 2013-06-27 04:43+0000\n"
12"Last-Translator: iAbaS <sosabazyan@yandex.ru>\n"
12"Last-Translator: iAbaS <sosabazyan@yandex.ru>\n"
13"Language-Team: Armenian <hy@li.org>\n"
13"Language-Team: Armenian <hy@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Խոսի՛ր"
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Խոսում եմ..."
206msgstr "Խոսում եմ..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Որոնում"
214msgstr "Որոնում"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
218msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Երգեր"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Վիդեոներ"
po/id.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-26 22:35+0000\n"
11"PO-Revision-Date: 2013-06-26 22:35+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Indonesian <id@li.org>\n"
13"Language-Team: Indonesian <id@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
po/is.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-09-18 16:22+0000\n"
11"PO-Revision-Date: 2013-09-18 16:22+0000\n"
12"Last-Translator: Andri Thorlacius <Unknown>\n"
12"Last-Translator: Andri Thorlacius <Unknown>\n"
13"Language-Team: Icelandic <is@li.org>\n"
13"Language-Team: Icelandic <is@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -206,11 +206,15 @@ msgstr "Talaðu Núna..."
206msgid "Speaking..."
206msgid "Speaking..."
207msgstr "Tala..."
207msgstr "Tala..."
208
208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209#: Panel/SearchIndicator.qml:27
213#: Panel/SearchIndicator.qml:27
210msgid "Search"
214msgid "Search"
211msgstr "Leita"
215msgstr "Leita"
212
216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
218msgid "Sorry, there is nothing that matches your search."
215msgstr "Því miður, það var ekkert sem passaði við leitarorðið þitt."
219msgstr "Því miður, það var ekkert sem passaði við leitarorðið þitt."
216
220
@@ -222,24 +226,3 @@ msgstr ""
222#, qt-format
226#, qt-format
223msgid "Please enter %1"
227msgid "Please enter %1"
224msgstr ""
228msgstr ""
225−
226−#~ msgid "Top Charting"
227−#~ msgstr "Topp Listi"
228−
229−#~ msgid "Featured"
230−#~ msgstr "Efst á baugi"
231−
232−#~ msgid "Recent"
233−#~ msgstr "Nýlegt"
234−
235−#~ msgid "New Releases"
236−#~ msgstr "Nýjar Útgáfur"
237−
238−#~ msgid "Videos"
239−#~ msgstr "Myndbönd"
240−
241−#~ msgid "Music"
242−#~ msgstr "Tónlist"
243−
244−#~ msgid "Popular Online"
245−#~ msgstr "Vinsælt á Netinu"
po/it.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-07 09:34+0000\n"
11"PO-Revision-Date: 2013-10-07 09:34+0000\n"
12"Last-Translator: Claudio Arseni <claudio.arseni@gmail.com>\n"
12"Last-Translator: Claudio Arseni <claudio.arseni@gmail.com>\n"
13"Language-Team: Italian <it@li.org>\n"
13"Language-Team: Italian <it@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -212,11 +212,15 @@ msgstr "Parla ora..."
212msgid "Speaking..."
212msgid "Speaking..."
213msgstr "Sto parlando..."
213msgstr "Sto parlando..."
214
214
215+#: Notifications/NotificationMenuItemFactory.qml:89
216+msgid "Show password"
217+msgstr ""
218+
215#: Panel/SearchIndicator.qml:27
219#: Panel/SearchIndicator.qml:27
216msgid "Search"
220msgid "Search"
217msgstr "Cerca"
221msgstr "Cerca"
218
222
219−#: plugins/Unity/scope.cpp:398
223+#: plugins/Unity/scope.cpp:408
220msgid "Sorry, there is nothing that matches your search."
224msgid "Sorry, there is nothing that matches your search."
221msgstr "Nessun risultato corrispondente alla ricerca."
225msgstr "Nessun risultato corrispondente alla ricerca."
222
226
@@ -228,24 +232,3 @@ msgstr "Tutto"
228#, qt-format
232#, qt-format
229msgid "Please enter %1"
233msgid "Please enter %1"
230msgstr "Inserire %1"
234msgstr "Inserire %1"
231−
232−#~ msgid "Music"
233−#~ msgstr "Musica"
234−
235−#~ msgid "Videos"
236−#~ msgstr "Video"
237−
238−#~ msgid "Recent"
239−#~ msgstr "Recenti"
240−
241−#~ msgid "New Releases"
242−#~ msgstr "Nuovi rilasci"
243−
244−#~ msgid "Featured"
245−#~ msgstr "In evidenza"
246−
247−#~ msgid "Popular Online"
248−#~ msgstr "Popolari online"
249−
250−#~ msgid "Top Charting"
251−#~ msgstr "Più votate"
po/ja.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-26 22:36+0000\n"
11"PO-Revision-Date: 2013-06-26 22:36+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Japanese <ja@li.org>\n"
13"Language-Team: Japanese <ja@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
po/km.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-11 08:49+0000\n"
11"PO-Revision-Date: 2013-10-11 08:49+0000\n"
12"Last-Translator: Khoem Sokhem <khoemsokhem@khmeros.info>\n"
12"Last-Translator: Khoem Sokhem <khoemsokhem@khmeros.info>\n"
13"Language-Team: Khmer <km@li.org>\n"
13"Language-Team: Khmer <km@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -209,11 +209,15 @@ msgstr "និយាយ​ឥឡូវ..."
209msgid "Speaking..."
209msgid "Speaking..."
210msgstr "កំពុង​និយាយ..."
210msgstr "កំពុង​និយាយ..."
211
211
212+#: Notifications/NotificationMenuItemFactory.qml:89
213+msgid "Show password"
214+msgstr ""
215+
212#: Panel/SearchIndicator.qml:27
216#: Panel/SearchIndicator.qml:27
213msgid "Search"
217msgid "Search"
214msgstr "ស្វែង​រក"
218msgstr "ស្វែង​រក"
215
219
216−#: plugins/Unity/scope.cpp:398
220+#: plugins/Unity/scope.cpp:408
217msgid "Sorry, there is nothing that matches your search."
221msgid "Sorry, there is nothing that matches your search."
218msgstr "សូម​ទោស មិនមាន​ពាក្យ​ដែល​អ្នក​ស្វែងរក​ទេ​។"
222msgstr "សូម​ទោស មិនមាន​ពាក្យ​ដែល​អ្នក​ស្វែងរក​ទេ​។"
219
223
@@ -225,24 +229,3 @@ msgstr "ទាំង​អស់"
225#, qt-format
229#, qt-format
226msgid "Please enter %1"
230msgid "Please enter %1"
227msgstr "សូម​បញ្ចូល %1"
231msgstr "សូម​បញ្ចូល %1"
228−
229−#~ msgid "Popular Online"
230−#~ msgstr "លើ​បណ្ដាញ​ប្រជាប្រិយ"
231−
232−#~ msgid "Music"
233−#~ msgstr "តន្ត្រី"
234−
235−#~ msgid "New Releases"
236−#~ msgstr "ការ​ចេញ​ផ្សាយ​ថ្មី"
237−
238−#~ msgid "Top Charting"
239−#~ msgstr "តារាង​ខាង​លើ"
240−
241−#~ msgid "Featured"
242−#~ msgstr "ដែល​ល្បី"
243−
244−#~ msgid "Recent"
245−#~ msgstr "ថ្មីៗ"
246−
247−#~ msgid "Videos"
248−#~ msgstr "វីដេអូ"
po/kn.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 05:43+0000\n"
11"PO-Revision-Date: 2013-06-27 05:43+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Kannada <kn@li.org>\n"
13"Language-Team: Kannada <kn@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "ಈಗ ಮಾತನಾಡಿ ..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "ಮಾತನಾಡುತಿದ್ದೀರಿ"
206msgstr "ಮಾತನಾಡುತಿದ್ದೀರಿ"
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "ಹುಡುಕು"
214msgstr "ಹುಡುಕು"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯಾದ ಹೊಂದಾಣಿಕೆಗಳು ದೊರಕುತ್ತಿಲ್ಲ"
218msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯಾದ ಹೊಂದಾಣಿಕೆಗಳು ದೊರಕುತ್ತಿಲ್ಲ"
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "ಸಂಗೀತ"
227−
228−#~ msgid "Videos"
229−#~ msgstr "ವೀಡಿಯೋಗಳು"
po/ko.po+8−7
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-10 07:04+0000\n"
11"PO-Revision-Date: 2013-10-10 07:04+0000\n"
12"Last-Translator: Kim Boram <boramism@gmail.com>\n"
12"Last-Translator: Kim Boram <boramism@gmail.com>\n"
13"Language-Team: Korean <ko@li.org>\n"
13"Language-Team: Korean <ko@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "검색"
214msgstr "검색"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
@@ -221,6 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "음악"
po/ky.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 06:17+0000\n"
11"PO-Revision-Date: 2013-06-27 06:17+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Kirghiz <ky@li.org>\n"
13"Language-Team: Kirghiz <ky@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Азыр сүйлөңүз..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Сүйлөнүүдө..."
206msgstr "Сүйлөнүүдө..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Издөө"
214msgstr "Издөө"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Тилекке каршы, сиздин издөөңүзгө эч нерсе дал келген жок."
218msgstr "Тилекке каршы, сиздин издөөңүзгө эч нерсе дал келген жок."
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Музыка"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Видеолор"
po/lo.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-02 10:00+0000\n"
11"PO-Revision-Date: 2013-10-02 10:00+0000\n"
12"Last-Translator: Anousak <anousak@gmail.com>\n"
12"Last-Translator: Anousak <anousak@gmail.com>\n"
13"Language-Team: Lao <lo@li.org>\n"
13"Language-Team: Lao <lo@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "ເວົ້າໂລດ"
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "ກໍາລັງເວົ້າ"
206msgstr "ກໍາລັງເວົ້າ"
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "ຊອກຫາ"
214msgstr "ຊອກຫາ"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
@@ -221,9 +225,3 @@ msgstr "ທັງໝົດ"
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr "ກະລູນາປ້ອນ %1"
227msgstr "ກະລູນາປ້ອນ %1"
224−
225−#~ msgid "Videos"
226−#~ msgstr "ວິດີໂອ"
227−
228−#~ msgid "Music"
229−#~ msgstr "ດົນຕີ"
po/lv.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-09-28 16:29+0000\n"
11"PO-Revision-Date: 2013-09-28 16:29+0000\n"
12"Last-Translator: Jānis-Marks Gailis <jeanmarc.gailis@gmail.com>\n"
12"Last-Translator: Jānis-Marks Gailis <jeanmarc.gailis@gmail.com>\n"
13"Language-Team: Latvian <lv@li.org>\n"
13"Language-Team: Latvian <lv@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Runajiet Tagad"
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Runa..."
206msgstr "Runa..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Meklēt"
214msgstr "Meklēt"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
218msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Mūzika"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Video"
po/my.po+8−19
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-09 11:35+0000\n"
11"PO-Revision-Date: 2013-10-09 11:35+0000\n"
12"Last-Translator: Pyae Sone <Unknown>\n"
12"Last-Translator: Pyae Sone <Unknown>\n"
13"Language-Team: Burmese <my@li.org>\n"
13"Language-Team: Burmese <my@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "ယခုပြောပါ"
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "ပြောနေသည်"
206msgstr "ပြောနေသည်"
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "ရှာဖွေ"
214msgstr "ရှာဖွေ"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့်တူညီတာဘာမှမရှိပါ။"
218msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့်တူညီတာဘာမှမရှိပါ။"
215
219
@@ -221,18 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "တေးဂီတ"
227−
228−#~ msgid "Videos"
229−#~ msgstr "ဗီဒီယိုများ"
230−
231−#~ msgid "New Releases"
232−#~ msgstr "အသစ်ထွက်ရှိသော"
233−
234−#~ msgid "Recent"
235−#~ msgstr "မကြာသေးခင်က"
236−
237−#~ msgid "Popular Online"
238−#~ msgstr "အွန်လိုင်းတွင်ပေါ်ပြူလာဖြစ်သော"
po/nb.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 07:02+0000\n"
11"PO-Revision-Date: 2013-06-27 07:02+0000\n"
12"Last-Translator: Joakim Langvand <jlangvand@gmail.com>\n"
12"Last-Translator: Joakim Langvand <jlangvand@gmail.com>\n"
13"Language-Team: Norwegian Bokmal <nb@li.org>\n"
13"Language-Team: Norwegian Bokmal <nb@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Snakk nå …"
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Snakker …"
206msgstr "Snakker …"
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Søk"
214msgstr "Søk"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Søket ga ingen treff."
218msgstr "Søket ga ingen treff."
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Musikk"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Videoer"
po/nl.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 07:19+0000\n"
11"PO-Revision-Date: 2013-06-27 07:19+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Dutch <nl@li.org>\n"
13"Language-Team: Dutch <nl@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:37+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "Nu inspreken…"
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "Inspreken…"
206msgstr "Inspreken…"
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "Zoeken"
214msgstr "Zoeken"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
218msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Muziek"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Video's"
po/pl.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-13 13:44+0000\n"
11"PO-Revision-Date: 2013-10-13 13:44+0000\n"
12"Last-Translator: GTriderXC <gtriderxc@yahoo.com>\n"
12"Last-Translator: GTriderXC <gtriderxc@yahoo.com>\n"
13"Language-Team: Polish <pl@li.org>\n"
13"Language-Team: Polish <pl@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
18"|| n%100>=20) ? 1 : 2;\n"
18"|| n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-14 05:47+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -211,11 +211,15 @@ msgstr "Mów teraz..."
211msgid "Speaking..."
211msgid "Speaking..."
212msgstr "Rozpoznanie..."
212msgstr "Rozpoznanie..."
213
213
214+#: Notifications/NotificationMenuItemFactory.qml:89
215+msgid "Show password"
216+msgstr ""
217+
214#: Panel/SearchIndicator.qml:27
218#: Panel/SearchIndicator.qml:27
215msgid "Search"
219msgid "Search"
216msgstr "Szukaj"
220msgstr "Szukaj"
217
221
218−#: plugins/Unity/scope.cpp:398
222+#: plugins/Unity/scope.cpp:408
219msgid "Sorry, there is nothing that matches your search."
223msgid "Sorry, there is nothing that matches your search."
220msgstr "Nie znaleziono pasujących wyników."
224msgstr "Nie znaleziono pasujących wyników."
221
225
po/pt_BR.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-01 13:05+0000\n"
11"PO-Revision-Date: 2013-10-01 13:05+0000\n"
12"Last-Translator: Rafael Neri <Unknown>\n"
12"Last-Translator: Rafael Neri <Unknown>\n"
13"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
13"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -207,11 +207,15 @@ msgstr "Fale agora..."
207msgid "Speaking..."
207msgid "Speaking..."
208msgstr "Falando..."
208msgstr "Falando..."
209
209
210+#: Notifications/NotificationMenuItemFactory.qml:89
211+msgid "Show password"
212+msgstr ""
213+
210#: Panel/SearchIndicator.qml:27
214#: Panel/SearchIndicator.qml:27
211msgid "Search"
215msgid "Search"
212msgstr "Pesquisar"
216msgstr "Pesquisar"
213
217
214−#: plugins/Unity/scope.cpp:398
218+#: plugins/Unity/scope.cpp:408
215msgid "Sorry, there is nothing that matches your search."
219msgid "Sorry, there is nothing that matches your search."
216msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
220msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
217
221
@@ -223,24 +227,3 @@ msgstr ""
223#, qt-format
227#, qt-format
224msgid "Please enter %1"
228msgid "Please enter %1"
225msgstr "Por favor, digite %1"
229msgstr "Por favor, digite %1"
226−
227−#~ msgid "Music"
228−#~ msgstr "Músicas"
229−
230−#~ msgid "Videos"
231−#~ msgstr "Vídeos"
232−
233−#~ msgid "New Releases"
234−#~ msgstr "Lançamentos"
235−
236−#~ msgid "Recent"
237−#~ msgstr "Recente"
238−
239−#~ msgid "Featured"
240−#~ msgstr "Em destaque"
241−
242−#~ msgid "Top Charting"
243−#~ msgstr "Top gráficos"
244−
245−#~ msgid "Popular Online"
246−#~ msgstr "Popular Online"
po/ro.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 07:53+0000\n"
11"PO-Revision-Date: 2013-06-27 07:53+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Romanian <ro@li.org>\n"
13"Language-Team: Romanian <ro@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
17"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
18"== 0) && (n != 0))) ? 2: 1));\n"
18"== 0) && (n != 0))) ? 2: 1));\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -206,11 +206,15 @@ msgstr "Vorbiți acum..."
206msgid "Speaking..."
206msgid "Speaking..."
207msgstr "Vorbire..."
207msgstr "Vorbire..."
208
208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209#: Panel/SearchIndicator.qml:27
213#: Panel/SearchIndicator.qml:27
210msgid "Search"
214msgid "Search"
211msgstr "Căutare"
215msgstr "Căutare"
212
216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
218msgid "Sorry, there is nothing that matches your search."
215msgstr ""
219msgstr ""
216"Ne pare rău, nu este nimic care se potrivește căutării dumneavoastră."
220"Ne pare rău, nu este nimic care se potrivește căutării dumneavoastră."
@@ -223,9 +227,3 @@ msgstr ""
223#, qt-format
227#, qt-format
224msgid "Please enter %1"
228msgid "Please enter %1"
225msgstr ""
229msgstr ""
226−
227−#~ msgid "Music"
228−#~ msgstr "Muzică"
229−
230−#~ msgid "Videos"
231−#~ msgstr "Video"
po/ru.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-01 05:55+0000\n"
11"PO-Revision-Date: 2013-10-01 05:55+0000\n"
12"Last-Translator: Zonov Roman <Unknown>\n"
12"Last-Translator: Zonov Roman <Unknown>\n"
13"Language-Team: Russian <ru@li.org>\n"
13"Language-Team: Russian <ru@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -210,11 +210,15 @@ msgstr "Говорите..."
210msgid "Speaking..."
210msgid "Speaking..."
211msgstr "Говорите..."
211msgstr "Говорите..."
212
212
213+#: Notifications/NotificationMenuItemFactory.qml:89
214+msgid "Show password"
215+msgstr ""
216+
213#: Panel/SearchIndicator.qml:27
217#: Panel/SearchIndicator.qml:27
214msgid "Search"
218msgid "Search"
215msgstr "Поиск"
219msgstr "Поиск"
216
220
217−#: plugins/Unity/scope.cpp:398
221+#: plugins/Unity/scope.cpp:408
218msgid "Sorry, there is nothing that matches your search."
222msgid "Sorry, there is nothing that matches your search."
219msgstr "Извините, поиск не дал результатов."
223msgstr "Извините, поиск не дал результатов."
220
224
@@ -226,24 +230,3 @@ msgstr ""
226#, qt-format
230#, qt-format
227msgid "Please enter %1"
231msgid "Please enter %1"
228msgstr "Пожалуйста, введите %1"
232msgstr "Пожалуйста, введите %1"
229−
230−#~ msgid "New Releases"
231−#~ msgstr "Новые релизы"
232−
233−#~ msgid "Music"
234−#~ msgstr "Музыка"
235−
236−#~ msgid "Videos"
237−#~ msgstr "Видео"
238−
239−#~ msgid "Recent"
240−#~ msgstr "Недавние"
241−
242−#~ msgid "Top Charting"
243−#~ msgstr "Наиболее популярное"
244−
245−#~ msgid "Popular Online"
246−#~ msgstr "Популярное в Интернете"
247−
248−#~ msgid "Featured"
249−#~ msgstr "Рекомендованное"
po/shn.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-07 11:46+0000\n"
11"PO-Revision-Date: 2013-10-07 11:46+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Shan <shn@li.org>\n"
13"Language-Team: Shan <shn@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=(n == 1) ? 0 : 1;\n"
17"Plural-Forms: nplurals=2; plural=(n == 1) ? 0 : 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
po/si.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-26 22:36+0000\n"
11"PO-Revision-Date: 2013-06-26 22:36+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Sinhalese <si@li.org>\n"
13"Language-Team: Sinhalese <si@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
po/sl.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-02 10:55+0000\n"
11"PO-Revision-Date: 2013-10-02 10:55+0000\n"
12"Last-Translator: Damir Jerovšek <Unknown>\n"
12"Last-Translator: Damir Jerovšek <Unknown>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
17"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
18"n%100==4 ? 3 : 0);\n"
18"n%100==4 ? 3 : 0);\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -212,11 +212,15 @@ msgstr "Govorite zdaj ..."
212msgid "Speaking..."
212msgid "Speaking..."
213msgstr "Govorjenje ..."
213msgstr "Govorjenje ..."
214
214
215+#: Notifications/NotificationMenuItemFactory.qml:89
216+msgid "Show password"
217+msgstr ""
218+
215#: Panel/SearchIndicator.qml:27
219#: Panel/SearchIndicator.qml:27
216msgid "Search"
220msgid "Search"
217msgstr "Iskanje"
221msgstr "Iskanje"
218
222
219−#: plugins/Unity/scope.cpp:398
223+#: plugins/Unity/scope.cpp:408
220msgid "Sorry, there is nothing that matches your search."
224msgid "Sorry, there is nothing that matches your search."
221msgstr "Nič se ne ujema z vašim iskalnim nizom."
225msgstr "Nič se ne ujema z vašim iskalnim nizom."
222
226
@@ -228,24 +232,3 @@ msgstr "Vse"
228#, qt-format
232#, qt-format
229msgid "Please enter %1"
233msgid "Please enter %1"
230msgstr "Vnesite %1"
234msgstr "Vnesite %1"
231−
232−#~ msgid "Music"
233−#~ msgstr "Glasba"
234−
235−#~ msgid "Videos"
236−#~ msgstr "Videi"
237−
238−#~ msgid "New Releases"
239−#~ msgstr "Nove izdaje"
240−
241−#~ msgid "Top Charting"
242−#~ msgstr "Najvišje na lestvici"
243−
244−#~ msgid "Featured"
245−#~ msgstr "Predstavljeno"
246−
247−#~ msgid "Recent"
248−#~ msgstr "Nedavno"
249−
250−#~ msgid "Popular Online"
251−#~ msgstr "Priljubljeno na spletu"
po/sr.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 09:19+0000\n"
11"PO-Revision-Date: 2013-06-27 09:19+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Serbian <sr@li.org>\n"
13"Language-Team: Serbian <sr@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -206,11 +206,15 @@ msgstr "Изговорите сада..."
206msgid "Speaking..."
206msgid "Speaking..."
207msgstr "Говор..."
207msgstr "Говор..."
208
208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209#: Panel/SearchIndicator.qml:27
213#: Panel/SearchIndicator.qml:27
210msgid "Search"
214msgid "Search"
211msgstr "Претрага"
215msgstr "Претрага"
212
216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
218msgid "Sorry, there is nothing that matches your search."
215msgstr "Нажалост, претрага није наишла на икакво подударање."
219msgstr "Нажалост, претрага није наишла на икакво подударање."
216
220
@@ -222,9 +226,3 @@ msgstr ""
222#, qt-format
226#, qt-format
223msgid "Please enter %1"
227msgid "Please enter %1"
224msgstr ""
228msgstr ""
225−
226−#~ msgid "Music"
227−#~ msgstr "Музика"
228−
229−#~ msgid "Videos"
230−#~ msgstr "Видео"
po/sv.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-26 22:36+0000\n"
11"PO-Revision-Date: 2013-06-26 22:36+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Swedish <sv@li.org>\n"
13"Language-Team: Swedish <sv@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
po/ta.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-24 11:36+0000\n"
11"PO-Revision-Date: 2013-10-24 11:36+0000\n"
12"Last-Translator: Thangamani Arun - தங்கமணி அருண் <thangam.arunx@gmail.com>\n"
12"Last-Translator: Thangamani Arun - தங்கமணி அருண் <thangam.arunx@gmail.com>\n"
13"Language-Team: Ubuntu Tamil Team/Free Tamil Computing/Thamizha\n"
13"Language-Team: Ubuntu Tamil Team/Free Tamil Computing/Thamizha\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-25 06:05+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16810)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20"Language: ta\n"
20"Language: ta\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
@@ -211,11 +211,15 @@ msgstr "இப்பொது பேசு..."
211msgid "Speaking..."
211msgid "Speaking..."
212msgstr "பேசுகிறது..."
212msgstr "பேசுகிறது..."
213
213
214+#: Notifications/NotificationMenuItemFactory.qml:89
215+msgid "Show password"
216+msgstr ""
217+
214#: Panel/SearchIndicator.qml:27
218#: Panel/SearchIndicator.qml:27
215msgid "Search"
219msgid "Search"
216msgstr "தெடு"
220msgstr "தெடு"
217
221
218−#: plugins/Unity/scope.cpp:398
222+#: plugins/Unity/scope.cpp:408
219msgid "Sorry, there is nothing that matches your search."
223msgid "Sorry, there is nothing that matches your search."
220msgstr "மன்னிக்கவும், உங்களுடைய தேடலுக்கு தகுந்த பொருத்தம் கிடைக்கவில்லை."
224msgstr "மன்னிக்கவும், உங்களுடைய தேடலுக்கு தகுந்த பொருத்தம் கிடைக்கவில்லை."
221
225
po/te.po+8−7
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 09:57+0000\n"
11"PO-Revision-Date: 2013-06-27 09:57+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Telugu <te@li.org>\n"
13"Language-Team: Telugu <te@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
@@ -221,6 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "సంగీతం"
po/tr.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-01 13:21+0000\n"
11"PO-Revision-Date: 2013-10-01 13:21+0000\n"
12"Last-Translator: Volkan Gezer <Unknown>\n"
12"Last-Translator: Volkan Gezer <Unknown>\n"
13"Language-Team: Turkish <tr@li.org>\n"
13"Language-Team: Turkish <tr@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -206,11 +206,15 @@ msgstr "Şimdi Konuşun..."
206msgid "Speaking..."
206msgid "Speaking..."
207msgstr "Konuşuyor..."
207msgstr "Konuşuyor..."
208
208
209+#: Notifications/NotificationMenuItemFactory.qml:89
210+msgid "Show password"
211+msgstr ""
212+
209#: Panel/SearchIndicator.qml:27
213#: Panel/SearchIndicator.qml:27
210msgid "Search"
214msgid "Search"
211msgstr "Ara"
215msgstr "Ara"
212
216
213−#: plugins/Unity/scope.cpp:398
217+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
218msgid "Sorry, there is nothing that matches your search."
215msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
219msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
216
220
@@ -222,24 +226,3 @@ msgstr ""
222#, qt-format
226#, qt-format
223msgid "Please enter %1"
227msgid "Please enter %1"
224msgstr "Lütfen %1 girin"
228msgstr "Lütfen %1 girin"
225−
226−#~ msgid "Featured"
227−#~ msgstr "Öne Çıkanlar"
228−
229−#~ msgid "Recent"
230−#~ msgstr "En Son"
231−
232−#~ msgid "Music"
233−#~ msgstr "Müzik"
234−
235−#~ msgid "Popular Online"
236−#~ msgstr "Genellikle Çevrimiçi"
237−
238−#~ msgid "Videos"
239−#~ msgstr "Videolar"
240−
241−#~ msgid "Top Charting"
242−#~ msgstr "En Çok Beğenilenler"
243−
244−#~ msgid "New Releases"
245−#~ msgstr "Yeni Sürümler"
po/ug.po+8−19
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-09 22:38+0000\n"
11"PO-Revision-Date: 2013-10-09 22:38+0000\n"
12"Last-Translator: Gheyret T.Kenji <Unknown>\n"
12"Last-Translator: Gheyret T.Kenji <Unknown>\n"
13"Language-Team: Uyghur <ug@li.org>\n"
13"Language-Team: Uyghur <ug@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -204,11 +204,15 @@ msgstr "ئەمدى سۆزلەڭ…"
204msgid "Speaking..."
204msgid "Speaking..."
205msgstr "سۆزلەۋاتىسىز…"
205msgstr "سۆزلەۋاتىسىز…"
206
206
207+#: Notifications/NotificationMenuItemFactory.qml:89
208+msgid "Show password"
209+msgstr ""
210+
207#: Panel/SearchIndicator.qml:27
211#: Panel/SearchIndicator.qml:27
208msgid "Search"
212msgid "Search"
209msgstr "ئىزدە"
213msgstr "ئىزدە"
210
214
211−#: plugins/Unity/scope.cpp:398
215+#: plugins/Unity/scope.cpp:408
212msgid "Sorry, there is nothing that matches your search."
216msgid "Sorry, there is nothing that matches your search."
213msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپىلمىدى."
217msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپىلمىدى."
214
218
@@ -220,18 +224,3 @@ msgstr "ھەممىسى"
220#, qt-format
224#, qt-format
221msgid "Please enter %1"
225msgid "Please enter %1"
222msgstr "%1 نى كىرگۈزۈڭ"
226msgstr "%1 نى كىرگۈزۈڭ"
223−
224−#~ msgid "Featured"
225−#~ msgstr "داڭلىق"
226−
227−#~ msgid "Recent"
228−#~ msgstr "يېقىنقى"
229−
230−#~ msgid "New Releases"
231−#~ msgstr "يېڭى ئېلان قىلىنغانلىرى"
232−
233−#~ msgid "Music"
234−#~ msgstr "مۇزىكا"
235−
236−#~ msgid "Videos"
237−#~ msgstr "سىنلار"
po/uk.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-19 16:44+0000\n"
11"PO-Revision-Date: 2013-10-19 16:44+0000\n"
12"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
12"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-10-20 05:20+0000\n"
19+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
20−"X-Generator: Launchpad (build 16807)\n"
20+"X-Generator: Launchpad (build 16820)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -212,11 +212,15 @@ msgstr "Можна говорити…"
212msgid "Speaking..."
212msgid "Speaking..."
213msgstr "Мовлення…"
213msgstr "Мовлення…"
214
214
215+#: Notifications/NotificationMenuItemFactory.qml:89
216+msgid "Show password"
217+msgstr ""
218+
215#: Panel/SearchIndicator.qml:27
219#: Panel/SearchIndicator.qml:27
216msgid "Search"
220msgid "Search"
217msgstr "Пошук"
221msgstr "Пошук"
218
222
219−#: plugins/Unity/scope.cpp:398
223+#: plugins/Unity/scope.cpp:408
220msgid "Sorry, there is nothing that matches your search."
224msgid "Sorry, there is nothing that matches your search."
221msgstr "Вибачте, для вказаних вами ключових слів нічого не знайдено."
225msgstr "Вибачте, для вказаних вами ключових слів нічого не знайдено."
222
226
po/unity8.pot+6−2
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"
10"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
11+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
po/xh.po+8−4
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity8\n"
8"Project-Id-Version: unity8\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-09-28 13:20+0000\n"
11"PO-Revision-Date: 2013-09-28 13:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Xhosa <xh@li.org>\n"
13"Language-Team: Xhosa <xh@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr ""
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr ""
206msgstr ""
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr ""
214msgstr ""
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr ""
218msgstr ""
215
219
po/zh_CN.po+8−25
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-10-09 13:51+0000\n"
11"PO-Revision-Date: 2013-10-09 13:51+0000\n"
12"Last-Translator: Aron Xu <Unknown>\n"
12"Last-Translator: Aron Xu <Unknown>\n"
13"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
13"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "现在请讲..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "讲话中..."
206msgstr "讲话中..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "搜索"
214msgstr "搜索"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "对不起,没有找到您想要的结果。"
218msgstr "对不起,没有找到您想要的结果。"
215
219
@@ -221,24 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Featured"
226−#~ msgstr "推荐"
227−
228−#~ msgid "New Releases"
229−#~ msgstr "新版本"
230−
231−#~ msgid "Top Charting"
232−#~ msgstr "排行榜图"
233−
234−#~ msgid "Music"
235−#~ msgstr "音乐"
236−
237−#~ msgid "Popular Online"
238−#~ msgstr "经常在线"
239−
240−#~ msgid "Videos"
241−#~ msgstr "视频"
242−
243−#~ msgid "Recent"
244−#~ msgstr "最近使用"
po/zh_TW.po+8−10
@@ -7,7 +7,7 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-10-11 12:12+0200\n"
10+"POT-Creation-Date: 2013-11-05 17:53+0100\n"
11"PO-Revision-Date: 2013-06-27 10:24+0000\n"
11"PO-Revision-Date: 2013-06-27 10:24+0000\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
12"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
13"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-10-13 05:43+0000\n"
18+"X-Launchpad-Export-Date: 2013-11-08 06:38+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16820)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -205,11 +205,15 @@ msgstr "請說..."
205msgid "Speaking..."
205msgid "Speaking..."
206msgstr "說話中..."
206msgstr "說話中..."
207
207
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
208#: Panel/SearchIndicator.qml:27
212#: Panel/SearchIndicator.qml:27
209msgid "Search"
213msgid "Search"
210msgstr "搜尋"
214msgstr "搜尋"
211
215
212−#: plugins/Unity/scope.cpp:398
216+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
217msgid "Sorry, there is nothing that matches your search."
214msgstr "很抱歉,找不到符合您想搜尋的結果。"
218msgstr "很抱歉,找不到符合您想搜尋的結果。"
215
219
@@ -221,9 +225,3 @@ msgstr ""
221#, qt-format
225#, qt-format
222msgid "Please enter %1"
226msgid "Please enter %1"
223msgstr ""
227msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "音樂"
227−
228−#~ msgid "Videos"
229−#~ msgstr "影片"
tests/autopilot/unity8/shell/emulators/create_interactive_notification.pymode 100755 → 100644

Only the mode changed.

tests/autopilot/unity8/shell/emulators/dash.py+7−17
@@ -18,42 +18,32 @@
18#
18#
19
19
20from unity8.shell.emulators import UnityEmulatorBase
20from unity8.shell.emulators import UnityEmulatorBase
21−from time import sleep
21+
22
22
23class Dash(UnityEmulatorBase):
23class Dash(UnityEmulatorBase):
24
24
25 """An emulator that understands the Dash."""
25 """An emulator that understands the Dash."""
26
26
27 def get_home_applications_grid(self):
27 def get_home_applications_grid(self):
28− for i in range(1,10):
29− get_grid = self.get_scope('home').select_single(
28+ get_grid = self.get_scope('home').wait_select_single(
30− "GenericFilterGrid",
29+ "GenericFilterGrid",
31− objectName="applications.scope"
30+ objectName="applications.scope"
32− )
31+ )
33− if get_grid != None:
34− break
35− sleep(1)
36 return get_grid
32 return get_grid
37
33
38 def get_application_icon(self, text):
34 def get_application_icon(self, text):
39 """Returns a 'Tile' icon that has the text 'text' from the application
35 """Returns a 'Tile' icon that has the text 'text' from the application
40 grid.
36 grid.
41
37
42− Will return None if the icon isn't found.
43−
44 :param text: String containing the text of the icon to search for.
38 :param text: String containing the text of the icon to search for.
45
39
46 """
40 """
47 app_grid = self.get_home_applications_grid()
41 app_grid = self.get_home_applications_grid()
48− for i in range(1,10):
49− resp_grid = app_grid.select_single('ResponsiveGridView')
42+ resp_grid = app_grid.wait_select_single('ResponsiveGridView')
50− if resp_grid != None:
51− break
52− sleep(1)
53 return resp_grid.select_single('Tile', text=text)
43 return resp_grid.select_single('Tile', text=text)
54
44
55 def get_scope(self, scope_name='home'):
45 def get_scope(self, scope_name='home'):
56− dash_content = self.select_single(
46+ dash_content = self.wait_select_single(
57 'QQuickListView',
47 'QQuickListView',
58 objectName='dashContentList'
48 objectName='dashContentList'
59 )
49 )
tests/autopilot/unity8/shell/emulators/hud.py+12−4
@@ -26,6 +26,7 @@ from autopilot.input import Touch
26
26
27SwipeCoords = namedtuple('SwipeCoords', 'start_x end_x start_y end_y')
27SwipeCoords = namedtuple('SwipeCoords', 'start_x end_x start_y end_y')
28
28
29+
29class Hud(UnityEmulatorBase, DragMixin):
30class Hud(UnityEmulatorBase, DragMixin):
30
31
31 """An emulator that understands the Hud."""
32 """An emulator that understands the Hud."""
@@ -34,13 +35,18 @@ class Hud(UnityEmulatorBase, DragMixin):
34 """Swipes open the Hud."""
35 """Swipes open the Hud."""
35 self.touch = Touch.create()
36 self.touch = Touch.create()
36
37
37− window = self.get_root_instance().select_single('QQuickView')
38+ window = self.get_root_instance().wait_select_single('QQuickView')
38− hud_show_button = window.select_single("HudButton")
39+ hud_show_button = window.wait_select_single("HudButton")
39
40
40 swipe_coords = self.get_button_swipe_coords(window, hud_show_button)
41 swipe_coords = self.get_button_swipe_coords(window, hud_show_button)
41
42
42 self.touch.press(swipe_coords.start_x, swipe_coords.start_y)
43 self.touch.press(swipe_coords.start_x, swipe_coords.start_y)
43− self._drag(swipe_coords.start_x, swipe_coords.start_y, swipe_coords.start_x, swipe_coords.end_y)
44+ self._drag(
45+ swipe_coords.start_x,
46+ swipe_coords.start_y,
47+ swipe_coords.start_x,
48+ swipe_coords.end_y
49+ )
44 try:
50 try:
45 hud_show_button.opacity.wait_for(1.0)
51 hud_show_button.opacity.wait_for(1.0)
46 self.touch.release()
52 self.touch.release()
@@ -74,6 +80,8 @@ class Hud(UnityEmulatorBase, DragMixin):
74 start_x = int(main_view.x + (main_view.width / 2))
80 start_x = int(main_view.x + (main_view.width / 2))
75 end_x = start_x
81 end_x = start_x
76 start_y = main_view.y + (main_view.height - 3)
82 start_y = main_view.y + (main_view.height - 3)
83+ end_y = main_view.y + int(
77− end_y = main_view.y + int(hud_show_button.y + (hud_show_button.height/2))
84+ hud_show_button.y + (hud_show_button.height/2)
85+ )
78
86
79 return SwipeCoords(start_x, end_x, start_y, end_y)
87 return SwipeCoords(start_x, end_x, start_y, end_y)
tests/autopilot/unity8/shell/emulators/main_window.py+7−1
@@ -38,11 +38,14 @@ class MainWindow(object):
38 return self.app.select_single(Greeter)
38 return self.app.select_single(Greeter)
39
39
40 def get_greeter_content_loader(self):
40 def get_greeter_content_loader(self):
41− return self.app.select_single(
41+ return self.app.wait_select_single(
42 "QQuickLoader",
42 "QQuickLoader",
43 objectName="greeterContentLoader"
43 objectName="greeterContentLoader"
44 )
44 )
45
45
46+ def get_greeter_background(self):
47+ return self.app.select_single("CrossFadeImage", objectName="greeterBackground")
48+
46 def get_login_loader(self):
49 def get_login_loader(self):
47 return self.app.select_single("QQuickLoader", objectName="loginLoader")
50 return self.app.select_single("QQuickLoader", objectName="loginLoader")
48
51
@@ -93,3 +96,6 @@ class MainWindow(object):
93
96
94 def get_pinentryField(self):
97 def get_pinentryField(self):
95 return self.app.select_single(objectName="pinentryField")
98 return self.app.select_single(objectName="pinentryField")
99+
100+ def get_shell_background(self):
101+ return self.app.select_single("CrossFadeImage", objectName="backgroundImage")
tests/autopilot/unity8/shell/tests/__init__.py+58−27
@@ -34,7 +34,7 @@ import logging
34import os.path
34import os.path
35import subprocess
35import subprocess
36import sys
36import sys
37−from testtools.matchers import Equals, NotEquals
37+from testtools.matchers import Equals
38
38
39from unity8 import (
39from unity8 import (
40 get_lib_path,
40 get_lib_path,
@@ -53,7 +53,7 @@ logger = logging.getLogger(__name__)
53UNITYSHELL_GSETTINGS_SCHEMA = "org.compiz.unityshell"
53UNITYSHELL_GSETTINGS_SCHEMA = "org.compiz.unityshell"
54UNITYSHELL_GSETTINGS_PATH = "/org/compiz/profiles/unity/plugins/unityshell/"
54UNITYSHELL_GSETTINGS_PATH = "/org/compiz/profiles/unity/plugins/unityshell/"
55UNITYSHELL_LAUNCHER_KEY = "launcher-hide-mode"
55UNITYSHELL_LAUNCHER_KEY = "launcher-hide-mode"
56−UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
56+UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
57
57
58
58
59def _get_device_emulation_scenarios(devices='All'):
59def _get_device_emulation_scenarios(devices='All'):
@@ -93,17 +93,25 @@ class UnityTestCase(AutopilotTestCase):
93 ], stderr=subprocess.STDOUT)
93 ], stderr=subprocess.STDOUT)
94 except subprocess.CalledProcessError, e:
94 except subprocess.CalledProcessError, e:
95 sys.stderr.write(
95 sys.stderr.write(
96− "Error: `initctl status unity8` failed, most probably the unity8 session could not be found:\n\n"
96+ "Error: `initctl status unity8` failed, most probably the "
97+ "unity8 session could not be found:\n\n"
97 "{0}\n"
98 "{0}\n"
98− "Please install unity8 or copy data/unity8.conf to {1}\n".format(
99+ "Please install unity8 or copy data/unity8.conf to "
100+ "{1}\n".format(
99 e.output,
101 e.output,
100− os.path.join(os.getenv("XDG_CONFIG_HOME", os.path.join(os.getenv("HOME"), ".config")), "upstart")
102+ os.path.join(os.getenv("XDG_CONFIG_HOME",
103+ os.path.join(os.getenv("HOME"),
104+ ".config")
105+ ),
106+ "upstart")
101− ))
107+ )
108+ )
102 sys.exit(1)
109 sys.exit(1)
103
110
104 if "start/" in output:
111 if "start/" in output:
105 sys.stderr.write(
112 sys.stderr.write(
106− "Error: Unity is currently running, these tests require it to be 'stopped'.\n"
113+ "Error: Unity is currently running, these tests require it to "
114+ "be 'stopped'.\n"
107 "Please run this command before running these tests: \n"
115 "Please run this command before running these tests: \n"
108 "initctl stop unity8\n"
116 "initctl stop unity8\n"
109 )
117 )
@@ -111,11 +119,22 @@ class UnityTestCase(AutopilotTestCase):
111
119
112 def setUp(self):
120 def setUp(self):
113 super(UnityTestCase, self).setUp()
121 super(UnityTestCase, self).setUp()
122+ if (Gio is not None and
123+ UNITYSHELL_GSETTINGS_SCHEMA in
114− if Gio is not None and UNITYSHELL_GSETTINGS_SCHEMA in Gio.Settings.list_relocatable_schemas():
124+ Gio.Settings.list_relocatable_schemas()):
125+
115 # Hide Unity launcher
126 # Hide Unity launcher
116− self._unityshell_schema = Gio.Settings.new_with_path(UNITYSHELL_GSETTINGS_SCHEMA, UNITYSHELL_GSETTINGS_PATH)
127+ self._unityshell_schema = Gio.Settings.new_with_path(
128+ UNITYSHELL_GSETTINGS_SCHEMA,
129+ UNITYSHELL_GSETTINGS_PATH,
130+ )
117− self._launcher_hide_mode = self._unityshell_schema.get_int(UNITYSHELL_LAUNCHER_KEY)
131+ self._launcher_hide_mode = self._unityshell_schema.get_int(
132+ UNITYSHELL_LAUNCHER_KEY,
133+ )
118− self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, UNITYSHELL_LAUNCHER_MODE)
134+ self._unityshell_schema.set_int(
135+ UNITYSHELL_LAUNCHER_KEY,
136+ UNITYSHELL_LAUNCHER_MODE,
137+ )
119 self.addCleanup(self._reset_launcher)
138 self.addCleanup(self._reset_launcher)
120
139
121 self._proxy = None
140 self._proxy = None
@@ -136,7 +155,10 @@ class UnityTestCase(AutopilotTestCase):
136
155
137 def _reset_launcher(self):
156 def _reset_launcher(self):
138 """Reset Unity launcher hide mode"""
157 """Reset Unity launcher hide mode"""
139− self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, self._launcher_hide_mode)
158+ self._unityshell_schema.set_int(
159+ UNITYSHELL_LAUNCHER_KEY,
160+ self._launcher_hide_mode,
161+ )
140
162
141 def _setup_display_details(self):
163 def _setup_display_details(self):
142 scale_divisor = self._determine_geometry()
164 scale_divisor = self._determine_geometry()
@@ -217,7 +239,10 @@ class UnityTestCase(AutopilotTestCase):
217 def _upstart_reset_env(self, key, value):
239 def _upstart_reset_env(self, key, value):
218 logger.info("Resetting upstart env %s to %s", key, value)
240 logger.info("Resetting upstart env %s to %s", key, value)
219 if value is None:
241 if value is None:
242+ subprocess.call(
220− subprocess.call(["/sbin/initctl", "unset-env", key], stderr=subprocess.STDOUT)
243+ ["/sbin/initctl", "unset-env", key],
244+ stderr=subprocess.STDOUT,
245+ )
221 else:
246 else:
222 subprocess.call([
247 subprocess.call([
223 "/sbin/initctl",
248 "/sbin/initctl",
@@ -244,9 +269,13 @@ class UnityTestCase(AutopilotTestCase):
244 self._setup_extra_mock_environment_patch()
269 self._setup_extra_mock_environment_patch()
245
270
246 # FIXME: we shouldn't be doing this
271 # FIXME: we shouldn't be doing this
247− # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and /tmp/mir_socket as last resort
272+ # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and
273+ # /tmp/mir_socket as last resort
248 try:
274 try:
275+ os.unlink(
276+ os.getenv('MIR_SOCKET',
249− os.unlink(os.getenv('MIR_SOCKET', os.path.join(os.getenv('XDG_RUNTIME_DIR', "/tmp"), "mir_socket")))
277+ os.path.join(os.getenv('XDG_RUNTIME_DIR', "/tmp"),
278+ "mir_socket")))
250 except OSError:
279 except OSError:
251 pass
280 pass
252 try:
281 try:
@@ -256,7 +285,7 @@ class UnityTestCase(AutopilotTestCase):
256
285
257 app_proxy = self._launch_unity_with_upstart(
286 app_proxy = self._launch_unity_with_upstart(
258 binary_path,
287 binary_path,
259− self.unity_geometry_args
288+ self.unity_geometry_args,
260 )
289 )
261
290
262 self._set_proxy(app_proxy)
291 self._set_proxy(app_proxy)
@@ -275,14 +304,16 @@ class UnityTestCase(AutopilotTestCase):
275 binary_arg = "BINARY=%s" % binary_path
304 binary_arg = "BINARY=%s" % binary_path
276 extra_args = "ARGS=%s" % " ".join(args)
305 extra_args = "ARGS=%s" % " ".join(args)
277
306
278− output = subprocess.check_output([
307+ output = subprocess.check_output(
308+ [
279− "/sbin/initctl",
309+ "/sbin/initctl",
280− "start",
310+ "start",
281− "unity8",
311+ "unity8",
282− binary_arg,
312+ binary_arg,
283− extra_args
313+ extra_args,
284− ] + ["%s=%s" % (k,v) for k,v in self._environment.iteritems()],
314+ ] + ["%s=%s" % (k, v) for k, v in self._environment.iteritems()],
285− stderr=subprocess.STDOUT)
315+ stderr=subprocess.STDOUT,
316+ )
286
317
287 self.addCleanup(self._cleanup_launching_upstart_unity)
318 self.addCleanup(self._cleanup_launching_upstart_unity)
288
319
@@ -296,7 +327,8 @@ class UnityTestCase(AutopilotTestCase):
296 def _cleanup_launching_upstart_unity(self):
327 def _cleanup_launching_upstart_unity(self):
297 logger.info("Stopping unity")
328 logger.info("Stopping unity")
298 try:
329 try:
330+ subprocess.check_output(
299− subprocess.check_output(["/sbin/initctl", "stop", "unity8"], stderr=subprocess.STDOUT)
331+ ["/sbin/initctl", "stop", "unity8"], stderr=subprocess.STDOUT)
300 except subprocess.CalledProcessError:
332 except subprocess.CalledProcessError:
301 logger.warning("Appears unity was already stopped!")
333 logger.warning("Appears unity was already stopped!")
302
334
@@ -366,8 +398,7 @@ class UnityTestCase(AutopilotTestCase):
366 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
398 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
367
399
368 def get_dash(self):
400 def get_dash(self):
369− dash = self._proxy.select_single(Dash)
401+ dash = self._proxy.wait_select_single(Dash)
370− self.assertThat(dash, NotEquals(None))
371 return dash
402 return dash
372
403
373 @property
404 @property
tests/autopilot/unity8/shell/tests/test_greeter.pynew file+38
@@ -0,0 +1,38 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 Canonical
5+#
6+# This program is free software: you can redistribute it and/or modify
7+# it under the terms of the GNU General Public License as published by
8+# the Free Software Foundation, either version 3 of the License, or
9+# (at your option) any later version.
10+#
11+# This program is distributed in the hope that it will be useful,
12+# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+# GNU General Public License for more details.
15+#
16+# You should have received a copy of the GNU General Public License
17+# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+#
19+
20+from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
21+
22+from testtools.matchers import Equals
23+
24+class TestGreeter(UnityTestCase):
25+
26+ """Tests the Shell Greeter."""
27+
28+ scenarios = _get_device_emulation_scenarios()
29+
30+ def test_greeter_background(self):
31+ """Test that the background of the greeter and the background of the shell are placed correctly
32+
33+ """
34+ self.launch_unity()
35+ self.main_window.get_greeter()
36+ greeter_background = self.main_window.get_greeter_background()
37+ shell_background = self.main_window.get_shell_background()
38+ self.assertThat(greeter_background.globalRect, Equals(shell_background.globalRect))
tests/autopilot/unity8/shell/tests/test_notifications.py+49−42
@@ -45,7 +45,7 @@ class NotificationsBase(UnityTestCase):
45 """Given an icons file name returns the full path (either system or
45 """Given an icons file name returns the full path (either system or
46 source tree.
46 source tree.
47
47
48− Consider the graphics directory as root so for example (runnign tests
48+ Consider the graphics directory as root so for example (running tests
49 from installed unity8-autopilot package):
49 from installed unity8-autopilot package):
50 >>> self.get_icon_path('clock.png')
50 >>> self.get_icon_path('clock.png')
51 /usr/share/unity8/graphics/clock.png
51 /usr/share/unity8/graphics/clock.png
@@ -145,8 +145,8 @@ class InteractiveNotificationBase(NotificationsBase):
145 hints,
145 hints,
146 )
146 )
147
147
148+ get_notification = lambda: notify_list.wait_select_single(
148− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
149+ 'Notification', objectName='notification1')
149− self.assertThat(get_notification, Eventually(NotEquals(None)))
150 notification = get_notification()
150 notification = get_notification()
151
151
152 self.touch.tap_object(
152 self.touch.tap_object(
@@ -156,7 +156,8 @@ class InteractiveNotificationBase(NotificationsBase):
156 self.assert_notification_action_id_was_called('action_id')
156 self.assert_notification_action_id_was_called('action_id')
157
157
158 def test_sd_incoming_call(self):
158 def test_sd_incoming_call(self):
159− """Rejecting a call should make notification expand and offer more options."""
159+ """Rejecting a call should make notification expand and
160+ offer more options."""
160 self.launch_unity()
161 self.launch_unity()
161 greeter = self.main_window.get_greeter()
162 greeter = self.main_window.get_greeter()
162 greeter.swipe()
163 greeter.swipe()
@@ -191,8 +192,8 @@ class InteractiveNotificationBase(NotificationsBase):
191 hints
192 hints
192 )
193 )
193
194
195+ get_notification = lambda: notify_list.wait_select_single(
194− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
196+ 'Notification', objectName='notification1')
195− self.assertThat(get_notification, Eventually(NotEquals(None)))
196 notification = get_notification()
197 notification = get_notification()
197 self._assert_notification(notification, None, None, True, True, 1.0)
198 self._assert_notification(notification, None, None, True, True, 1.0)
198 initial_height = notification.height
199 initial_height = notification.height
@@ -200,8 +201,10 @@ class InteractiveNotificationBase(NotificationsBase):
200 self.assertThat(
201 self.assertThat(
201 notification.height,
202 notification.height,
202 Eventually(Equals(initial_height +
203 Eventually(Equals(initial_height +
204+ 3 * notification.select_single(
203− 3 * notification.select_single(objectName="buttonColumn").spacing +
205+ objectName="buttonColumn").spacing +
204− 3 * notification.select_single(objectName="button4").height)))
206+ 3 * notification.select_single(
207+ objectName="button4").height)))
205 self.touch.tap_object(notification.select_single(objectName="button4"))
208 self.touch.tap_object(notification.select_single(objectName="button4"))
206 self.assert_notification_action_id_was_called("action_decline_4")
209 self.assert_notification_action_id_was_called("action_decline_4")
207
210
@@ -360,13 +363,20 @@ class EphemeralNotificationsTests(NotificationsBase):
360
363
361 notification.show()
364 notification.show()
362
365
366+ notification = lambda: notify_list.wait_select_single(
363− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
367+ 'Notification', objectName='notification1')
364− self.assertThat(get_notification, Eventually(NotEquals(None)))
365− notification = get_notification()
366− self._assert_notification(notification, summary, body, True, True, 1.0)
368+ self._assert_notification(
369+ notification(),
370+ summary,
371+ body,
372+ True,
373+ True,
374+ 1.0,
375+ )
367
376
368 def test_icon_summary(self):
377 def test_icon_summary(self):
369− """Notification must display the expected summary and secondary icon."""
378+ """Notification must display the expected summary and secondary
379+ icon."""
370 self.launch_unity()
380 self.launch_unity()
371 greeter = self.main_window.get_greeter()
381 greeter = self.main_window.get_greeter()
372 greeter.swipe()
382 greeter.swipe()
@@ -391,11 +401,11 @@ class EphemeralNotificationsTests(NotificationsBase):
391
401
392 notification.show()
402 notification.show()
393
403
404+ notification = lambda: notify_list.wait_select_single(
394− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
405+ 'Notification', objectName='notification1')
395− self.assertThat(get_notification, Eventually(NotEquals(None)))
406+
396− notification = get_notification()
397 self._assert_notification(
407 self._assert_notification(
398− notification,
408+ notification(),
399 summary,
409 summary,
400 None,
410 None,
401 False,
411 False,
@@ -404,7 +414,8 @@ class EphemeralNotificationsTests(NotificationsBase):
404 )
414 )
405
415
406 def test_urgency_order(self):
416 def test_urgency_order(self):
407− """Notifications must be displayed in order according to their urgency."""
417+ """Notifications must be displayed in order according to their
418+ urgency."""
408 self.launch_unity()
419 self.launch_unity()
409 greeter = self.main_window.get_greeter()
420 greeter = self.main_window.get_greeter()
410 greeter.swipe()
421 greeter.swipe()
@@ -448,11 +459,10 @@ class EphemeralNotificationsTests(NotificationsBase):
448 )
459 )
449 notification_critical.show()
460 notification_critical.show()
450
461
451− get_notification = lambda: notify_list.select_single(
462+ get_notification = lambda: notify_list.wait_select_single(
452 'Notification',
463 'Notification',
453 summary=summary_critical
464 summary=summary_critical
454 )
465 )
455− self.assertThat(get_notification, Eventually(NotEquals(None)))
456
466
457 notification = get_notification()
467 notification = get_notification()
458 self._assert_notification(
468 self._assert_notification(
@@ -464,11 +474,10 @@ class EphemeralNotificationsTests(NotificationsBase):
464 1.0
474 1.0
465 )
475 )
466
476
467− get_normal_notification = lambda: notify_list.select_single(
477+ get_normal_notification = lambda: notify_list.wait_select_single(
468 'Notification',
478 'Notification',
469 summary=summary_normal
479 summary=summary_normal
470 )
480 )
471− self.assertThat(get_normal_notification, Eventually(NotEquals(None)))
472 notification = get_normal_notification()
481 notification = get_normal_notification()
473 self._assert_notification(
482 self._assert_notification(
474 notification,
483 notification,
@@ -479,11 +488,10 @@ class EphemeralNotificationsTests(NotificationsBase):
479 1.0
488 1.0
480 )
489 )
481
490
482− get_low_notification = lambda: notify_list.select_single(
491+ get_low_notification = lambda: notify_list.wait_select_single(
483 'Notification',
492 'Notification',
484 summary=summary_low
493 summary=summary_low
485 )
494 )
486− self.assertThat(get_low_notification, Eventually(NotEquals(None)))
487 notification = get_low_notification()
495 notification = get_low_notification()
488 self._assert_notification(
496 self._assert_notification(
489 notification,
497 notification,
@@ -508,9 +516,8 @@ class EphemeralNotificationsTests(NotificationsBase):
508 notification = self._create_ephemeral_notification(summary, body)
516 notification = self._create_ephemeral_notification(summary, body)
509 notification.show()
517 notification.show()
510
518
519+ notification = notify_list.wait_select_single(
511− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
520+ 'Notification', objectName='notification1')
512− self.assertThat(get_notification, Eventually(NotEquals(None)))
513− notification = get_notification()
514 self._assert_notification(
521 self._assert_notification(
515 notification,
522 notification,
516 summary,
523 summary,
@@ -533,14 +540,14 @@ class EphemeralNotificationsTests(NotificationsBase):
533 notification = self._create_ephemeral_notification(summary)
540 notification = self._create_ephemeral_notification(summary)
534 notification.show()
541 notification.show()
535
542
543+ notification = notify_list.wait_select_single(
536− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
544+ 'Notification', objectName='notification1')
537− self.assertThat(get_notification, Eventually(NotEquals(None)))
538− notification = get_notification()
539
545
540 self._assert_notification(notification, summary, '', False, False, 1.0)
546 self._assert_notification(notification, summary, '', False, False, 1.0)
541
547
542 def test_update_notification_same_layout(self):
548 def test_update_notification_same_layout(self):
543− """Notification must allow updating its contents while being displayed."""
549+ """Notification must allow updating its contents while being
550+ displayed."""
544 self.launch_unity()
551 self.launch_unity()
545 greeter = self.main_window.get_greeter()
552 greeter = self.main_window.get_greeter()
546 greeter.swipe()
553 greeter.swipe()
@@ -558,8 +565,8 @@ class EphemeralNotificationsTests(NotificationsBase):
558 )
565 )
559 notification.show()
566 notification.show()
560
567
561− get_notification = lambda: notify_list.select_single('Notification', summary=summary)
568+ get_notification = lambda: notify_list.wait_select_single(
562− self.assertThat(get_notification, Eventually(NotEquals(None)))
569+ 'Notification', summary=summary)
563 self._assert_notification(
570 self._assert_notification(
564 get_notification(),
571 get_notification(),
565 summary,
572 summary,
@@ -575,11 +582,11 @@ class EphemeralNotificationsTests(NotificationsBase):
575 icon_path = self._get_icon_path('avatars/amanda.png')
582 icon_path = self._get_icon_path('avatars/amanda.png')
576 notification.update(summary, body, icon_path)
583 notification.update(summary, body, icon_path)
577 notification.show()
584 notification.show()
578− self.assertThat(get_notification, Eventually(NotEquals(None)))
579 self._assert_notification(get_notification(), summary, body)
585 self._assert_notification(get_notification(), summary, body)
580
586
581 def test_update_notification_layout_change(self):
587 def test_update_notification_layout_change(self):
582− """Notification must allow updating its contents and layout while being displayed."""
588+ """Notification must allow updating its contents and layout while
589+ being displayed."""
583 self.launch_unity()
590 self.launch_unity()
584 greeter = self.main_window.get_greeter()
591 greeter = self.main_window.get_greeter()
585 greeter.swipe()
592 greeter.swipe()
@@ -603,8 +610,8 @@ class EphemeralNotificationsTests(NotificationsBase):
603 )
610 )
604 notification.show()
611 notification.show()
605
612
613+ get_notification = lambda: notify_list.wait_select_single(
606− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
614+ 'Notification', objectName='notification1')
607− self.assertThat(get_notification, Eventually(NotEquals(None)))
608 self._assert_notification(
615 self._assert_notification(
609 get_notification(),
616 get_notification(),
610 summary,
617 summary,
@@ -645,8 +652,8 @@ class EphemeralNotificationsTests(NotificationsBase):
645
652
646 notification.show()
653 notification.show()
647
654
655+ get_notification = lambda: notify_list.wait_select_single(
648− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
656+ 'Notification', objectName='notification1')
649− self.assertThat(get_notification, Eventually(NotEquals(None)))
650 notification = get_notification()
657 notification = get_notification()
651 self._assert_notification(
658 self._assert_notification(
652 notification,
659 notification,
@@ -662,7 +669,8 @@ class EphemeralNotificationsTests(NotificationsBase):
662 'Did you watch the air-race in Oshkosh last week?',
669 'Did you watch the air-race in Oshkosh last week?',
663 'Phil owned the place like no one before him!',
670 'Phil owned the place like no one before him!',
664 'Did really everything in the race work according to regulations?',
671 'Did really everything in the race work according to regulations?',
665− 'Somehow I think to remember Burt Williams did cut corners and was not punished for this.',
672+ 'Somehow I think to remember Burt Williams did cut corners and '
673+ 'was not punished for this.',
666 'Hopefully the referees will watch the videos of the race.',
674 'Hopefully the referees will watch the videos of the race.',
667 'Burt could get fined with US$ 50000 for that rule-violation :)'
675 'Burt could get fined with US$ 50000 for that rule-violation :)'
668 ]
676 ]
@@ -677,11 +685,10 @@ class EphemeralNotificationsTests(NotificationsBase):
677 hints=[('x-canonical-append', 'true')]
685 hints=[('x-canonical-append', 'true')]
678 )
686 )
679 notification.show()
687 notification.show()
680− get_notification = lambda: notify_list.select_single(
688+ get_notification = lambda: notify_list.wait_select_single(
681 'Notification',
689 'Notification',
682 objectName='notification1'
690 objectName='notification1'
683 )
691 )
684− self.assertThat(get_notification, Eventually(NotEquals(None)))
685 notification = get_notification()
692 notification = get_notification()
686 self._assert_notification(
693 self._assert_notification(
687 notification,
694 notification,
tests/mocks/QMenuModel/CMakeLists.txt+23
@@ -9,3 +9,26 @@ add_custom_target(QMenuModelQmlFiles ALL
9 COMMAND cp ${QMLFILES} ${CMAKE_CURRENT_BINARY_DIR}
9 COMMAND cp ${QMLFILES} ${CMAKE_CURRENT_BINARY_DIR}
10 DEPENDS ${QMLFILES}
10 DEPENDS ${QMLFILES}
11)
11)
12+
13+include_directories(
14+ ${Qt5Core_INCLUDE_DIRS}
15+ ${Qt5Quick_INCLUDE_DIRS}
16+)
17+
18+set(QMenuModelQml_SOURCES
19+ actionstateparser.cpp
20+ plugin.cpp
21+ unitymenumodel.cpp
22+)
23+
24+add_library(QMenuModelQml SHARED ${QMenuModelQml_SOURCES})
25+target_link_libraries(QMenuModelQml
26+ ${Qt5Core_LIBRARIES}
27+ ${Qt5Quick_LIBRARIES}
28+)
29+
30+qt5_use_modules(QMenuModelQml Core Quick)
31+
32+set_target_properties(QMenuModelQml PROPERTIES
33+ OUTPUT_NAME qmenumodel
34+ VERSION 0)
tests/mocks/QMenuModel/UnityMenuAction.qmlnew file+30
@@ -0,0 +1,30 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+import QtQuick 2.0
21+import QMenuModel 0.1
22+
23+QtObject {
24+ property string name
25+ property UnityMenuModel model
26+ property int index
27+
28+ readonly property var state: undefined
29+ readonly property bool valid: false
30+}
tests/mocks/QMenuModel/actionstateparser.cppnew file+19
@@ -0,0 +1,19 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#include "actionstateparser.h"
tests/mocks/QMenuModel/actionstateparser.hnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef MOCK_ACTIONSTATEPARSER_H
20+#define MOCK_ACTIONSTATEPARSER_H
21+
22+#include <QObject>
23+#include <QVariant>
24+
25+typedef struct _GVariant GVariant;
26+
27+class Q_DECL_EXPORT ActionStateParser : public QObject
28+{
29+ Q_OBJECT
30+public:
31+ ActionStateParser(QObject* parent = 0):QObject(parent) {}
32+ virtual QVariant toQVariant(GVariant*) const { return QVariant(); }
33+};
34+
35+#endif // MOCK_ACTIONSTATEPARSER_H
tests/mocks/QMenuModel/plugin.cppnew file+30
@@ -0,0 +1,30 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#include "plugin.h"
20+#include "unitymenumodel.h"
21+#include "actionstateparser.h"
22+
23+#include <QtQml>
24+
25+void QMenuModelPlugin::registerTypes(const char *uri)
26+{
27+ Q_ASSERT(uri == QLatin1String("QMenuModel"));
28+ qmlRegisterType<UnityMenuModel>(uri, 0, 1, "UnityMenuModel");
29+ qmlRegisterType<ActionStateParser>(uri, 0, 1, "ActionStateParser");
30+}
tests/mocks/QMenuModel/plugin.hnew file+34
@@ -0,0 +1,34 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef MOCK_QMENUMODEL_PLUGIN_H
20+#define MOCK_QMENUMODEL_PLUGIN_H
21+
22+#include <QQmlEngine>
23+#include <QQmlExtensionPlugin>
24+
25+class QMenuModelPlugin : public QQmlExtensionPlugin
26+{
27+ Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29+
30+public:
31+ void registerTypes(const char *uri);
32+};
33+
34+#endif
tests/mocks/QMenuModel/qmldir+3−1
@@ -1,3 +1,5 @@
1module QMenuModel
1module QMenuModel
2+plugin qmenumodel
3+
2QDBusActionGroup 0.1 QDBusActionGroup.qml
4QDBusActionGroup 0.1 QDBusActionGroup.qml
3−UnityMenuModel 0.1 UnityMenuModel.qml
5+UnityMenuAction 0.1 UnityMenuAction.qml
tests/mocks/QMenuModel/unitymenumodel.cppnew file+239
@@ -0,0 +1,239 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#include "unitymenumodel.h"
20+#include <QDebug>
21+
22+enum MenuRoles {
23+ LabelRole = Qt::DisplayRole + 1,
24+ SensitiveRole,
25+ IsSeparatorRole,
26+ IconRole,
27+ TypeRole,
28+ ExtendedAttributesRole,
29+ ActionRole,
30+ ActionStateRole,
31+ IsCheckRole,
32+ IsRadioRole,
33+ IsToggledRole
34+};
35+
36+UnityMenuModel::UnityMenuModel(QObject *parent)
37+: QAbstractListModel(parent)
38+{
39+}
40+
41+QVariant UnityMenuModel::modelData() const
42+{
43+ return m_modelData;
44+}
45+
46+void UnityMenuModel::setModelData(const QVariant& data)
47+{
48+ beginResetModel();
49+
50+ m_modelData.clear();
51+ m_modelData = data.toList();
52+
53+ endResetModel();
54+}
55+
56+
57+void UnityMenuModel::insertRow(int row, const QVariant& data)
58+{
59+ row = qMin(row, rowCount());
60+
61+ beginInsertRows(QModelIndex(), row, row);
62+
63+ m_modelData.insert(row, data);
64+
65+ endInsertRows();
66+}
67+
68+void UnityMenuModel::appendRow(const QVariant& data)
69+{
70+ insertRow(rowCount(), data);
71+}
72+
73+void UnityMenuModel::removeRow(int row)
74+{
75+ if (row < 0 || rowCount() <= row) {
76+ return;
77+ }
78+
79+ beginRemoveRows(QModelIndex(), row, row);
80+
81+ m_modelData.removeAt(row);
82+
83+ endRemoveRows();
84+}
85+
86+UnityMenuModel::~UnityMenuModel()
87+{
88+}
89+
90+QByteArray UnityMenuModel::busName() const
91+{
92+ return m_busName;
93+}
94+
95+void UnityMenuModel::setBusName(const QByteArray &busName)
96+{
97+ this->m_busName = busName;
98+}
99+
100+QVariantMap UnityMenuModel::actions() const
101+{
102+ return m_actions;
103+}
104+
105+void UnityMenuModel::setActions(const QVariantMap &actions)
106+{
107+ this->m_actions = actions;
108+}
109+
110+QByteArray UnityMenuModel::menuObjectPath() const
111+{
112+ return m_menuObjectPath;
113+}
114+
115+void UnityMenuModel::setMenuObjectPath(const QByteArray &path)
116+{
117+ this->m_menuObjectPath = path;
118+}
119+
120+ActionStateParser* UnityMenuModel::actionStateParser() const
121+{
122+ return NULL;
123+}
124+
125+void UnityMenuModel::setActionStateParser(ActionStateParser*)
126+{
127+}
128+
129+int UnityMenuModel::rowCount(const QModelIndex&) const
130+{
131+ return m_modelData.count();
132+}
133+
134+int UnityMenuModel::columnCount(const QModelIndex&) const
135+{
136+ return 1;
137+}
138+
139+QVariant UnityMenuModel::data(const QModelIndex &index, int role) const
140+{
141+ return rowData(index.row())[roleNames()[role]];
142+}
143+
144+QVariantMap UnityMenuModel::rowData(int row) const
145+{
146+ return m_modelData[row].toMap()["rowData"].toMap();
147+}
148+
149+QVariant UnityMenuModel::subMenuData(int row) const
150+{
151+ return m_modelData[row].toMap()["submenu"];
152+}
153+
154+QModelIndex UnityMenuModel::index(int row, int column, const QModelIndex&) const
155+{
156+ return createIndex(row, column);
157+}
158+
159+QModelIndex UnityMenuModel::parent(const QModelIndex &) const
160+{
161+ return QModelIndex();
162+}
163+
164+QHash<int, QByteArray> UnityMenuModel::roleNames() const
165+{
166+ QHash<int, QByteArray> names;
167+
168+ names[LabelRole] = "label";
169+ names[SensitiveRole] = "sensitive";
170+ names[IsSeparatorRole] = "isSeparator";
171+ names[IconRole] = "icon";
172+ names[TypeRole] = "type";
173+ names[ExtendedAttributesRole] = "ext";
174+ names[ActionRole] = "action";
175+ names[ActionStateRole] = "actionState";
176+ names[IsCheckRole] = "isCheck";
177+ names[IsRadioRole] = "isRadio";
178+ names[IsToggledRole] = "isToggled";
179+
180+ return names;
181+}
182+
183+QObject * UnityMenuModel::submenu(int position, QQmlComponent*)
184+{
185+ if (position < 0 || m_modelData.count() < position) {
186+ return NULL;
187+ }
188+
189+ while (submenus.count() <= position) {
190+ submenus.append(NULL);
191+ }
192+
193+ QVariant submenuData = subMenuData(position);
194+ if (submenuData.type() == (int)QMetaType::QVariantList) {
195+ UnityMenuModel*& model = submenus[position];
196+ if (!model) {
197+ model = new UnityMenuModel(this);
198+ }
199+ if (model->modelData() != submenuData) {
200+ model->setModelData(submenuData);
201+ }
202+ return model;
203+ }
204+
205+ return NULL;
206+}
207+
208+bool UnityMenuModel::loadExtendedAttributes(int, const QVariantMap &)
209+{
210+ return false;
211+}
212+
213+QVariant UnityMenuModel::get(int row, const QByteArray &role)
214+{
215+ static QHash<QByteArray, int> roles;
216+ if (roles.isEmpty()) {
217+ QHash<int, QByteArray> names = roleNames();
218+ Q_FOREACH (int role, names.keys())
219+ roles.insert(names[role], role);
220+ }
221+
222+ return this->data(this->index(row, 0), roles[role]);
223+}
224+
225+void UnityMenuModel::activate(int, const QVariant&)
226+{
227+}
228+
229+void UnityMenuModel::changeState(int, const QVariant&)
230+{
231+}
232+
233+void UnityMenuModel::registerAction(UnityMenuAction*)
234+{
235+}
236+
237+void UnityMenuModel::unregisterAction(UnityMenuAction*)
238+{
239+}
tests/mocks/QMenuModel/unitymenumodel.hnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef MOCK_UNITYMENUMODEL_H
20+#define MOCK_UNITYMENUMODEL_H
21+
22+#include <QAbstractListModel>
23+class QQmlComponent;
24+class UnityMenuAction;
25+class ActionStateParser;
26+
27+class Q_DECL_EXPORT UnityMenuModel : public QAbstractListModel
28+{
29+ Q_OBJECT
30+ Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
31+ Q_PROPERTY(QByteArray busName READ busName WRITE setBusName NOTIFY busNameChanged)
32+ Q_PROPERTY(QVariantMap actions READ actions WRITE setActions NOTIFY actionsChanged)
33+ Q_PROPERTY(QByteArray menuObjectPath READ menuObjectPath WRITE setMenuObjectPath NOTIFY menuObjectPathChanged)
34+ Q_PROPERTY(ActionStateParser* actionStateParser READ actionStateParser WRITE setActionStateParser NOTIFY actionStateParserChanged)
35+
36+public:
37+ UnityMenuModel(QObject *parent = NULL);
38+ virtual ~UnityMenuModel();
39+
40+ Q_INVOKABLE void insertRow(int row, const QVariant& data);
41+ Q_INVOKABLE void appendRow(const QVariant& data);
42+ Q_INVOKABLE void removeRow(int row);
43+
44+ QVariant modelData() const;
45+ void setModelData(const QVariant& data);
46+
47+ QByteArray busName() const;
48+ void setBusName(const QByteArray &busName);
49+
50+ QVariantMap actions() const;
51+ void setActions(const QVariantMap &actions);
52+
53+ QByteArray menuObjectPath() const;
54+ void setMenuObjectPath(const QByteArray &path);
55+
56+ ActionStateParser* actionStateParser() const;
57+ void setActionStateParser(ActionStateParser* actionStateParser);
58+
59+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
60+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
61+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
62+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
63+ QModelIndex parent(const QModelIndex &index) const;
64+ QHash<int, QByteArray> roleNames() const;
65+
66+ Q_INVOKABLE QObject * submenu(int position, QQmlComponent* actionStateParser = NULL);
67+ Q_INVOKABLE bool loadExtendedAttributes(int position, const QVariantMap &schema);
68+ Q_INVOKABLE QVariant get(int row, const QByteArray &role);
69+
70+ Q_INVOKABLE void activate(int index, const QVariant& parameter = QVariant());
71+ Q_INVOKABLE void changeState(int index, const QVariant& parameter);
72+
73+ void registerAction(UnityMenuAction* action);
74+ void unregisterAction(UnityMenuAction* action);
75+
76+Q_SIGNALS:
77+ void busNameChanged();
78+ void actionsChanged();
79+ void menuObjectPathChanged();
80+ void actionStateParserChanged();
81+ void modelDataChanged();
82+
83+private:
84+ QVariantMap rowData(int row) const;
85+ QVariant subMenuData(int row) const;
86+
87+ class Row;
88+ QVariantList m_modelData;
89+ QList<UnityMenuModel*> submenus;
90+
91+ QByteArray m_busName;
92+ QVariantMap m_actions;
93+ QByteArray m_menuObjectPath;
94+};
95+
96+#endif // MOCK_UNITYMENUMODEL_H
tests/mocks/Unity/Indicators/IndicatorBase.qmlnew file+37
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+import QtQuick 2.0
21+import QMenuModel 0.1
22+
23+Item {
24+ id: indicatorBase
25+
26+ //const
27+ property string busName
28+ property string actionsObjectPath
29+ property string rootMenuType: "com.canonical.indicator.root"
30+ property string deviceMenuObjectPath
31+
32+ property var menuModel: UnityMenuModel {}
33+
34+ property RootActionState rootActionState: RootActionState {
35+ onUpdated: indicatorBase.rootActionStateChanged()
36+ }
37+}
tests/mocks/Unity/Indicators/IndicatorWidget.qmlnew file+28
@@ -0,0 +1,28 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+import QtQuick 2.0
21+import Unity.Indicators 0.1 as Indicators
22+
23+IndicatorBase {
24+ id: indicatorWidget
25+
26+ enabled: false
27+ property int iconSize: height
28+}
tests/mocks/Unity/Indicators/RootActionState.qml+17−9
@@ -20,14 +20,22 @@
20import QtQuick 2.0
20import QtQuick 2.0
21
21
22QtObject {
22QtObject {
23− property var menu
23+ property var menu
24− property bool valid: false
24+ property bool valid: false
25− property string title
25+ property string title
26− property string leftLabel
26+ property string leftLabel
27− property string rightLabel
27+ property string rightLabel
28− property var icons
28+ property var icons
29− property string accessibleName
29+ property string accessibleName
30− property bool visible: true
30+ property bool visible: true
31
31
32− signal updated
32+ signal updated
33+
34+ onValidChanged: updated()
35+ onTitleChanged: updated()
36+ onLeftLabelChanged: updated()
37+ onRightLabelChanged: updated()
38+ onIconsChanged: updated()
39+ onAccessibleNameChanged: updated()
40+ onVisibleChanged: updated()
33}
41}
tests/mocks/Unity/Indicators/qmldir+2
@@ -2,6 +2,8 @@ module Unity.Indicators
2plugin IndicatorsFakeQml
2plugin IndicatorsFakeQml
3
3
4CachedUnityMenuModel 0.1 CachedUnityMenuModel.qml
4CachedUnityMenuModel 0.1 CachedUnityMenuModel.qml
5+IndicatorBase 0.1 IndicatorBase.qml
6+IndicatorWidget 0.1 IndicatorWidget.qml
5IndicatorsModel 0.1 IndicatorsModel.qml
7IndicatorsModel 0.1 IndicatorsModel.qml
6FakeMenuPage 0.1 FakeMenuPage.qml
8FakeMenuPage 0.1 FakeMenuPage.qml
7RootActionState 0.1 RootActionState.qml
9RootActionState 0.1 RootActionState.qml
tests/mocks/Unity/fake_scope.cpp+3−20
@@ -25,25 +25,8 @@ static DeeModel* create_results_model(unsigned category_count, unsigned result_c
25
25
26// TODO: Implement remaining pieces
26// TODO: Implement remaining pieces
27
27
28−Scope::Scope(QObject* parent)
28+Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
29− : QObject(parent)
30− , m_visible(false)
31− , m_searching(false)
32− , m_isActive(false)
33− , m_categories(new Categories(this))
34− , m_results(new DeeListModel(this))
35{
29{
36− DeeModel* results_model = create_results_model(4, 30);
37− m_categories->setResultModel(results_model);
38− m_categories->setModel(create_categories_model(4));
39− m_results->setModel(results_model);
40−
41− m_timer.setInterval(1000);
42− m_timer.setSingleShot(true);
43− connect(&m_timer, &QTimer::timeout, [this]() {
44− Preview *p = new Preview(this);
45− Q_EMIT previewReady(p);
46− });
47}
30}
48
31
49Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
32Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
@@ -56,9 +39,9 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
56 , m_categories(new Categories(this))
39 , m_categories(new Categories(this))
57 , m_results(new DeeListModel(this))
40 , m_results(new DeeListModel(this))
58{
41{
59− DeeModel* results_model = create_results_model(4, 30);
42+ DeeModel* results_model = create_results_model(20, 300);
60 m_categories->setResultModel(results_model);
43 m_categories->setResultModel(results_model);
61− m_categories->setModel(create_categories_model(4));
44+ m_categories->setModel(create_categories_model(20));
62 m_results->setModel(results_model);
45 m_results->setModel(results_model);
63
46
64 m_timer.setInterval(1000);
47 m_timer.setInterval(1000);
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+3
@@ -1724,6 +1724,9 @@ private Q_SLOTS:
1724
1724
1725 void testMaximizeVisibleAreaMoveUpAndShowHeader()
1725 void testMaximizeVisibleAreaMoveUpAndShowHeader()
1726 {
1726 {
1727+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1728+ QSKIP("This test is extremely unstable in 5.0.x");
1729+#endif
1727 model->setProperty(0, "size", 800);
1730 model->setProperty(0, "size", 800);
1728 verifyItem(0, 50., 800., false);
1731 verifyItem(0, 50., 800., false);
1729
1732
tests/plugins/Ubuntu/Gestures/DownwardsLauncher.qml+2−10
@@ -31,10 +31,7 @@ Item {
31 y: followDragArea()
31 y: followDragArea()
32
32
33 function followDragArea() {
33 function followDragArea() {
34− if (dragArea.status === DirectionalDragArea.Rejected)
35− return -height
36− else
37− return dragArea.distance < height ? -height + dragArea.distance : 0
34+ return dragArea.distance < height ? -height + dragArea.distance : 0
38 }
35 }
39 }
36 }
40
37
@@ -66,15 +63,10 @@ Item {
66 dragAreaRect.opacity = 0.3
63 dragAreaRect.opacity = 0.3
67 launcher.y = Qt.binding(launcher.followDragArea)
64 launcher.y = Qt.binding(launcher.followDragArea)
68 break;
65 break;
69− case DirectionalDragArea.Recognized:
66+ defaut: // DirectionalDragArea.Recognized:
70 dragAreaRect.color = "green"
67 dragAreaRect.color = "green"
71 dragAreaRect.opacity = 0.5
68 dragAreaRect.opacity = 0.5
72 break;
69 break;
73− default: //case DirectionalDragArea.Rejected:
74− dragAreaRect.color = "red"
75− dragAreaRect.opacity = 0.5
76− launcher.y = -launcher.height
77− break;
78 }
70 }
79 }
71 }
80
72
tests/plugins/Ubuntu/Gestures/LeftwardsLauncher.qml+5−13
@@ -32,13 +32,10 @@ Item {
32 y: 0
32 y: 0
33
33
34 function followDragArea() {
34 function followDragArea() {
35− if (dragArea.status === DirectionalDragArea.Rejected)
36− return root.width
37− else
38− return dragArea.distance > -width ?
35+ return dragArea.distance > -width ?
39− root.width + dragArea.distance
36+ root.width + dragArea.distance
40− :
37+ :
41− root.width - width
38+ root.width - width
42 }
39 }
43 }
40 }
44
41
@@ -69,15 +66,10 @@ Item {
69 dragAreaRect.opacity = 0.3
66 dragAreaRect.opacity = 0.3
70 launcher.x = Qt.binding(launcher.followDragArea)
67 launcher.x = Qt.binding(launcher.followDragArea)
71 break;
68 break;
72− case DirectionalDragArea.Recognized:
69+ default: //case DirectionalDragArea.Recognized:
73 dragAreaRect.color = "green"
70 dragAreaRect.color = "green"
74 dragAreaRect.opacity = 0.5
71 dragAreaRect.opacity = 0.5
75 break;
72 break;
76− default: //case DirectionalDragArea.Rejected:
77− dragAreaRect.color = "red"
78− dragAreaRect.opacity = 0.5
79− launcher.x = -launcher.height
80− break;
81 }
73 }
82 }
74 }
83
75
tests/plugins/Ubuntu/Gestures/RightwardsLauncher.qml+3−10
@@ -19,6 +19,7 @@ import Ubuntu.Gestures 0.1
19import Ubuntu.Components 0.1
19import Ubuntu.Components 0.1
20
20
21Item {
21Item {
22+ objectName: "rightwardsLauncher"
22
23
23 function reset() { launcher.x = -launcher.width }
24 function reset() { launcher.x = -launcher.width }
24
25
@@ -31,10 +32,7 @@ Item {
31 y: 0
32 y: 0
32
33
33 function followDragArea() {
34 function followDragArea() {
34− if (dragArea.status === DirectionalDragArea.Rejected)
35− return -width
36− else
37− return dragArea.distance < width ? -width + dragArea.distance : 0
35+ return dragArea.distance < width ? -width + dragArea.distance : 0
38 }
36 }
39 }
37 }
40
38
@@ -66,15 +64,10 @@ Item {
66 dragAreaRect.opacity = 0.3
64 dragAreaRect.opacity = 0.3
67 launcher.x = Qt.binding(launcher.followDragArea)
65 launcher.x = Qt.binding(launcher.followDragArea)
68 break;
66 break;
69− case DirectionalDragArea.Recognized:
67+ default: //case DirectionalDragArea.Recognized:
70 dragAreaRect.color = "green"
68 dragAreaRect.color = "green"
71 dragAreaRect.opacity = 0.5
69 dragAreaRect.opacity = 0.5
72 break;
70 break;
73− default: //case DirectionalDragArea.Rejected:
74− dragAreaRect.color = "red"
75− dragAreaRect.opacity = 0.5
76− launcher.x = -launcher.height
77− break;
78 }
71 }
79 }
72 }
80
73
tests/plugins/Ubuntu/Gestures/UpwardsLauncher.qml+5−13
@@ -32,13 +32,10 @@ Item {
32 y: root.height
32 y: root.height
33
33
34 function followDragArea() {
34 function followDragArea() {
35− if (dragArea.status === DirectionalDragArea.Rejected)
36− return root.height
37− else
38− return dragArea.distance > -height ?
35+ return dragArea.distance > -height ?
39− root.height + dragArea.distance
36+ root.height + dragArea.distance
40− :
37+ :
41− root.height - height
38+ root.height - height
42 }
39 }
43 }
40 }
44
41
@@ -69,15 +66,10 @@ Item {
69 dragAreaRect.opacity = 0.3
66 dragAreaRect.opacity = 0.3
70 launcher.y = Qt.binding(launcher.followDragArea)
67 launcher.y = Qt.binding(launcher.followDragArea)
71 break;
68 break;
72− case DirectionalDragArea.Recognized:
69+ default: //case DirectionalDragArea.Recognized:
73 dragAreaRect.color = "green"
70 dragAreaRect.color = "green"
74 dragAreaRect.opacity = 0.5
71 dragAreaRect.opacity = 0.5
75 break;
72 break;
76− default: //case DirectionalDragArea.Rejected:
77− dragAreaRect.color = "red"
78− dragAreaRect.opacity = 0.5
79− launcher.y = -launcher.height
80− break;
81 }
73 }
82 }
74 }
83
75
tests/plugins/Ubuntu/Gestures/edgeDragExample.qml+7−1
@@ -33,7 +33,13 @@ Rectangle {
33 }
33 }
34 }
34 }
35
35
36+ // NB: Do not anchor it as we will move it programmatically from the test
36− RightwardsLauncher { id: hpLauncher; anchors.fill: parent }
37+ RightwardsLauncher {
38+ id: hpLauncher;
39+ width: parent.width
40+ height: parent.height
41+ }
42+
37 LeftwardsLauncher { id: hnLauncher; anchors.fill: parent }
43 LeftwardsLauncher { id: hnLauncher; anchors.fill: parent }
38 DownwardsLauncher { id: vpLauncher; anchors.fill: parent }
44 DownwardsLauncher { id: vpLauncher; anchors.fill: parent }
39 UpwardsLauncher { id: vnLauncher; anchors.fill: parent }
45 UpwardsLauncher { id: vnLauncher; anchors.fill: parent }
tests/plugins/Ubuntu/Gestures/tst_AxisVelocityCalculator.cpp+3−3
@@ -54,12 +54,12 @@ private Q_SLOTS:
54
54
55private:
55private:
56 AxisVelocityCalculator *velCalc;
56 AxisVelocityCalculator *velCalc;
57− FakeTimeSource *fakeTimeSource;
57+ QSharedPointer<FakeTimeSource> fakeTimeSource;
58};
58};
59
59
60void tst_AxisVelocityCalculator::init()
60void tst_AxisVelocityCalculator::init()
61{
61{
62− fakeTimeSource = new FakeTimeSource;
62+ fakeTimeSource.reset(new FakeTimeSource);
63
63
64 velCalc = new AxisVelocityCalculator;
64 velCalc = new AxisVelocityCalculator;
65 velCalc->setTimeSource(fakeTimeSource);
65 velCalc->setTimeSource(fakeTimeSource);
@@ -68,7 +68,7 @@ void tst_AxisVelocityCalculator::init()
68void tst_AxisVelocityCalculator::cleanup()
68void tst_AxisVelocityCalculator::cleanup()
69{
69{
70 delete velCalc;
70 delete velCalc;
71− delete fakeTimeSource;
71+ fakeTimeSource.reset();
72}
72}
73
73
74void tst_AxisVelocityCalculator::simpleSamples()
74void tst_AxisVelocityCalculator::simpleSamples()
tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp+285−96
@@ -19,23 +19,38 @@
19#include <qpa/qwindowsysteminterface.h>
19#include <qpa/qwindowsysteminterface.h>
20#include <QtQuick/QQuickView>
20#include <QtQuick/QQuickView>
21#include <QtQml/QQmlEngine>
21#include <QtQml/QQmlEngine>
22+#include <QPointer>
22
23
23#include <DirectionalDragArea.h>
24#include <DirectionalDragArea.h>
24
25
26+using namespace UbuntuGestures;
27+
25−class FakeTimer : public UbuntuGestures::AbstractTimer
28+class FakeTimer : public AbstractTimer
26{
29{
27 Q_OBJECT
30 Q_OBJECT
28public:
31public:
29− FakeTimer(QObject *parent = 0)
32+ FakeTimer(const SharedTimeSource &timeSource, QObject *parent = 0)
30− : UbuntuGestures::AbstractTimer(parent)
33+ : UbuntuGestures::AbstractTimer(parent),
34+ m_timeSource(timeSource)
31 {}
35 {}
32
36
33− virtual int interval() const { return m_duration; }
37+ int interval() const override { return m_interval; }
34− virtual void setInterval(int msecs) { m_duration = msecs; }
38+ void setInterval(int msecs) override { m_interval = msecs; }
39+ void start() override {
40+ AbstractTimer::start();
41+ m_nextTimeoutTime = m_timeSource->msecsSinceReference() + (qint64)m_interval;
42+ }
43+
44+ void emitTimeout() {
45+ m_nextTimeoutTime += m_interval;
46+ Q_EMIT timeout();
47+ }
35
48
36− void emitTimeout() {Q_EMIT timeout();}
49+ qint64 nextTimeoutTime() const { return m_nextTimeoutTime; }
37private:
50private:
38− int m_duration;
51+ int m_interval;
52+ SharedTimeSource m_timeSource;
53+ qint64 m_nextTimeoutTime;
39};
54};
40
55
41class FakeTimeSource : public UbuntuGestures::TimeSource
56class FakeTimeSource : public UbuntuGestures::TimeSource
@@ -67,14 +82,17 @@ private Q_SLOTS:
67 void maxSilenceTime();
82 void maxSilenceTime();
68 void sceneXAndX();
83 void sceneXAndX();
69 void sceneYAndY();
84 void sceneYAndY();
70− void emitDraggingChangedOnDirectRecognition();
85+ void twoFingerTap();
86+ void movingDDA();
87+ void ignoreOldFinger();
71
88
72private:
89private:
73 QQuickView *createView();
90 QQuickView *createView();
91+ void passTime(qint64 timeSpan);
74 QQuickView *view;
92 QQuickView *view;
75 QTouchDevice *device;
93 QTouchDevice *device;
76 FakeTimer *fakeTimer;
94 FakeTimer *fakeTimer;
77− FakeTimeSource *fakeTimeSource;
95+ QSharedPointer<FakeTimeSource> fakeTimeSource;
78};
96};
79
97
80void tst_DirectionalDragArea::initTestCase()
98void tst_DirectionalDragArea::initTestCase()
@@ -101,8 +119,8 @@ void tst_DirectionalDragArea::init()
101 QVERIFY(view->rootObject() != 0);
119 QVERIFY(view->rootObject() != 0);
102 qApp->processEvents();
120 qApp->processEvents();
103
121
122+ fakeTimeSource.reset(new FakeTimeSource);
104− fakeTimer = new FakeTimer;
123+ fakeTimer = new FakeTimer(fakeTimeSource);
105− fakeTimeSource = new FakeTimeSource;
106}
124}
107
125
108void tst_DirectionalDragArea::cleanup()
126void tst_DirectionalDragArea::cleanup()
@@ -113,8 +131,7 @@ void tst_DirectionalDragArea::cleanup()
113 delete fakeTimer;
131 delete fakeTimer;
114 fakeTimer = 0;
132 fakeTimer = 0;
115
133
116− delete fakeTimeSource;
134+ fakeTimeSource.reset();
117− fakeTimeSource = 0;
118}
135}
119
136
120QQuickView *tst_DirectionalDragArea::createView()
137QQuickView *tst_DirectionalDragArea::createView()
@@ -127,6 +144,23 @@ QQuickView *tst_DirectionalDragArea::createView()
127 return window;
144 return window;
128}
145}
129
146
147+void tst_DirectionalDragArea::passTime(qint64 timeSpan)
148+{
149+ qint64 finalTime = fakeTimeSource->m_msecsSinceReference + timeSpan;
150+
151+ if (fakeTimer->isRunning() && finalTime >= fakeTimer->nextTimeoutTime()) {
152+ fakeTimeSource->m_msecsSinceReference = fakeTimer->nextTimeoutTime();
153+ fakeTimer->emitTimeout();
154+
155+ qint64 timeSpanRemainder = finalTime - fakeTimeSource->m_msecsSinceReference;
156+ if (timeSpanRemainder > 0) {
157+ passTime(timeSpanRemainder);
158+ }
159+ } else {
160+ fakeTimeSource->m_msecsSinceReference = finalTime;
161+ }
162+}
163+
130namespace {
164namespace {
131QPointF calculateInitialTouchPos(DirectionalDragArea *edgeDragArea, QQuickView *view)
165QPointF calculateInitialTouchPos(DirectionalDragArea *edgeDragArea, QQuickView *view)
132{
166{
@@ -180,7 +214,7 @@ void tst_DirectionalDragArea::edgeDrag()
180 QFETCH(QString, dragAreaObjectName);
214 QFETCH(QString, dragAreaObjectName);
181 QFETCH(qreal, wideningAngleMultiplier);
215 QFETCH(qreal, wideningAngleMultiplier);
182 QFETCH(qreal, dragDistanceFactor);
216 QFETCH(qreal, dragDistanceFactor);
183− QFETCH(int, expectedGestureRecognition);
217+ QFETCH(bool, expectGestureRecognition);
184
218
185 DirectionalDragArea *edgeDragArea =
219 DirectionalDragArea *edgeDragArea =
186 view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
220 view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
@@ -196,7 +230,10 @@ void tst_DirectionalDragArea::edgeDrag()
196 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*dragDistanceFactor;
230 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*dragDistanceFactor;
197 QPointF dragDirectionVector = calculateDirectionVector(edgeDragArea,
231 QPointF dragDirectionVector = calculateDirectionVector(edgeDragArea,
198 wideningAngleMultiplier);
232 wideningAngleMultiplier);
199− QPointF touchMovement = dragDirectionVector * (edgeDragArea->distanceThreshold() * 0.1f);
233+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
234+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
235+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
236+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
200
237
201 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
238 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
202
239
@@ -211,15 +248,16 @@ void tst_DirectionalDragArea::edgeDrag()
211 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
248 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
212 }
249 }
213
250
214− do {
251+ for (int i = 0; i < totalMovementSteps; ++i) {
215 touchPoint += touchMovement;
252 touchPoint += touchMovement;
253+ passTime(movementTimeStepMs);
216 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
254 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
217− } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance);
255+ }
218
256
219− if (expectedGestureRecognition)
257+ if (expectGestureRecognition)
220 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
258 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
221
259
222− if (edgeDragArea->status() == DirectionalDragArea::Rejected) {
260+ if (edgeDragArea->status() == DirectionalDragArea::WaitingForTouch) {
223 QCOMPARE(edgeDragArea->dragging(), false);
261 QCOMPARE(edgeDragArea->dragging(), false);
224 QCOMPARE(draggingSpy.count(), 2);
262 QCOMPARE(draggingSpy.count(), 2);
225 }
263 }
@@ -235,49 +273,49 @@ void tst_DirectionalDragArea::edgeDrag_data()
235 QTest::addColumn<QString>("dragAreaObjectName");
273 QTest::addColumn<QString>("dragAreaObjectName");
236 QTest::addColumn<qreal>("wideningAngleMultiplier");
274 QTest::addColumn<qreal>("wideningAngleMultiplier");
237 QTest::addColumn<qreal>("dragDistanceFactor");
275 QTest::addColumn<qreal>("dragDistanceFactor");
238− QTest::addColumn<int>("expectedGestureRecognition");
276+ QTest::addColumn<bool>("expectGestureRecognition");
239
277
240 QTest::newRow("rightwards, tiny drag")
278 QTest::newRow("rightwards, tiny drag")
241− << "hpDragArea" << 0.0 << 0.2 << 0;
279+ << "hpDragArea" << 0.0 << 0.2 << false;
242
280
243 QTest::newRow("rightwards, straight drag")
281 QTest::newRow("rightwards, straight drag")
244− << "hpDragArea" << 0.0 << 3.0 << 1;
282+ << "hpDragArea" << 0.0 << 3.0 << true;
245
283
246 QTest::newRow("rightwards, diagonal drag")
284 QTest::newRow("rightwards, diagonal drag")
247− << "hpDragArea" << 0.9 << 3.0 << 1;
285+ << "hpDragArea" << 0.9 << 3.0 << true;
248
286
249 QTest::newRow("rightwards, overly diagonal drag")
287 QTest::newRow("rightwards, overly diagonal drag")
250− << "hpDragArea" << 2.0 << 3.0 << 0;
288+ << "hpDragArea" << 2.0 << 3.0 << false;
251
289
252 QTest::newRow("leftwards, tiny drag")
290 QTest::newRow("leftwards, tiny drag")
253− << "hnDragArea" << 0.0 << 0.2 << 0;
291+ << "hnDragArea" << 0.0 << 0.2 << false;
254
292
255 QTest::newRow("leftwards, straight drag")
293 QTest::newRow("leftwards, straight drag")
256− << "hnDragArea" << 0.0 << 3.0 << 1;
294+ << "hnDragArea" << 0.0 << 3.0 << true;
257
295
258 QTest::newRow("leftwards, diagonal drag")
296 QTest::newRow("leftwards, diagonal drag")
259− << "hnDragArea" << 0.9 << 3.0 << 1;
297+ << "hnDragArea" << 0.9 << 3.0 << true;
260
298
261 QTest::newRow("downwards, tiny drag")
299 QTest::newRow("downwards, tiny drag")
262− << "vpDragArea" << 0.0 << 0.2 << 0;
300+ << "vpDragArea" << 0.0 << 0.2 << false;
263
301
264 QTest::newRow("downwards, straight drag")
302 QTest::newRow("downwards, straight drag")
265− << "vpDragArea" << 0.0 << 3.0 << 1;
303+ << "vpDragArea" << 0.0 << 3.0 << true;
266
304
267 QTest::newRow("downwards, diagonal drag")
305 QTest::newRow("downwards, diagonal drag")
268− << "vpDragArea" << 0.9 << 3.0 << 1;
306+ << "vpDragArea" << 0.9 << 3.0 << true;
269
307
270 QTest::newRow("upwards, tiny drag")
308 QTest::newRow("upwards, tiny drag")
271− << "vnDragArea" << 0.0 << 0.2 << 0;
309+ << "vnDragArea" << 0.0 << 0.2 << false;
272
310
273 QTest::newRow("upwards, straight drag")
311 QTest::newRow("upwards, straight drag")
274− << "vnDragArea" << 0.0 << 3.0 << 1;
312+ << "vnDragArea" << 0.0 << 3.0 << true;
275
313
276 QTest::newRow("upwards, diagonal drag")
314 QTest::newRow("upwards, diagonal drag")
277− << "vnDragArea" << 0.9 << 3.0 << 1;
315+ << "vnDragArea" << 0.9 << 3.0 << true;
278
316
279 QTest::newRow("upwards, overly diagonal drag")
317 QTest::newRow("upwards, overly diagonal drag")
280− << "vnDragArea" << 2.0 << 3.0 << 0;
318+ << "vnDragArea" << 2.0 << 3.0 << false;
281}
319}
282
320
283/*
321/*
@@ -298,25 +336,33 @@ void tst_DirectionalDragArea::dragWithShortDirectionChange()
298
336
299 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0;
337 qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0;
300 QPointF dragDirectionVector(1.0, 0.0);
338 QPointF dragDirectionVector(1.0, 0.0);
301− QPointF touchMovement = dragDirectionVector * (edgeDragArea->distanceThreshold() * 0.1f);
339+ qreal touchStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
340+ // make sure we are above minimum speed
341+ int touchStepTimeMs = (touchStepDistance / (edgeDragArea->minSpeed() * 5.0f)) * 1000.0f;
342+ QPointF touchMovement = dragDirectionVector * touchStepDistance;
302
343
303 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
344 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
304
345
305 // Move a bit in the proper direction
346 // Move a bit in the proper direction
306 for (int i=0; i < 3; ++i) {
347 for (int i=0; i < 3; ++i) {
307 touchPoint += touchMovement;
348 touchPoint += touchMovement;
349+ passTime(touchStepTimeMs);
308 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
350 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
309 }
351 }
310
352
311 // Then a sudden and small movement to the opposite direction
353 // Then a sudden and small movement to the opposite direction
312− touchPoint -= dragDirectionVector * (edgeDragArea->maxDeviation() * 0.7);
354+ touchPoint -= touchMovement*0.2;
355+ passTime(touchStepTimeMs*0.2);
313 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
356 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
314
357
315− // And then resume movment in the correct direction until it crosses the distance threshold.
358+ // And then resume movment in the correct direction until it crosses the distance and time
359+ // thresholds.
316 do {
360 do {
317 touchPoint += touchMovement;
361 touchPoint += touchMovement;
362+ passTime(touchStepTimeMs);
318 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
363 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
319− } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance);
364+ } while ((touchPoint - initialTouchPos).manhattanLength() < desiredDragDistance
365+ || fakeTimeSource->m_msecsSinceReference < (edgeDragArea->compositionTime() * 1.5f));
320
366
321 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
367 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
322
368
@@ -329,7 +375,8 @@ void tst_DirectionalDragArea::dragWithShortDirectionChange()
329 */
375 */
330void tst_DirectionalDragArea::minSpeed()
376void tst_DirectionalDragArea::minSpeed()
331{
377{
332− QFETCH(int, minSpeedMsecsDeviation);
378+ QFETCH(qreal, minSpeed);
379+ QFETCH(qreal, speed);
333 QFETCH(int, expectedStatusAfterSpeedCheck);
380 QFETCH(int, expectedStatusAfterSpeedCheck);
334
381
335 DirectionalDragArea *edgeDragArea =
382 DirectionalDragArea *edgeDragArea =
@@ -338,44 +385,40 @@ void tst_DirectionalDragArea::minSpeed()
338 edgeDragArea->setRecognitionTimer(fakeTimer);
385 edgeDragArea->setRecognitionTimer(fakeTimer);
339 edgeDragArea->setTimeSource(fakeTimeSource);
386 edgeDragArea->setTimeSource(fakeTimeSource);
340
387
388+ // A really long, unattainable, number. We don't want it getting recognized before
389+ // the speed checks we want have been performed
390+ edgeDragArea->setDistanceThreshold(500000);
391+
392+ edgeDragArea->setMinSpeed(minSpeed);
393+
341 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
394 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
342 QPointF touchPoint = initialTouchPos;
395 QPointF touchPoint = initialTouchPos;
343
396
344 QPointF dragDirectionVector(1.0, 0.0);
397 QPointF dragDirectionVector(1.0, 0.0);
345− qreal distanceStep = edgeDragArea->distanceThreshold() * 0.1f;
398+ qint64 timeStepMsecs = 10;
399+ qreal distanceStep = (speed / 1000.0f) * timeStepMsecs;
346 QPointF touchMovement = dragDirectionVector * distanceStep;
400 QPointF touchMovement = dragDirectionVector * distanceStep;
347− qreal minSpeedMsecs = edgeDragArea->minSpeed() / 1000.0;
348− qint64 timeStepMsecs = qFloor(distanceStep / minSpeedMsecs) + minSpeedMsecsDeviation;
349
401
350− // if it fails it means the params set in the QML file are not in harmony with the values
351− // used in this test
352− Q_ASSERT(timeStepMsecs > 0);
353−
354− fakeTimeSource->m_msecsSinceReference = 0;
355 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
402 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
356
403
357− // Move a bit in the proper direction
404+ // Move for a while to ensure our speed check is performed a couple of times
358− for (int i=0; i < 4; ++i) {
405+ for (int i=0; i < 20; ++i) {
359 touchPoint += touchMovement;
406 touchPoint += touchMovement;
360− fakeTimeSource->m_msecsSinceReference += timeStepMsecs;
407+ passTime(timeStepMsecs);
361 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
408 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
362 }
409 }
363
410
364− QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
365−
366− // Force the periodic speed check.
367− fakeTimer->emitTimeout();
368−
369 QCOMPARE((int)edgeDragArea->status(), expectedStatusAfterSpeedCheck);
411 QCOMPARE((int)edgeDragArea->status(), expectedStatusAfterSpeedCheck);
370}
412}
371
413
372void tst_DirectionalDragArea::minSpeed_data()
414void tst_DirectionalDragArea::minSpeed_data()
373{
415{
374− QTest::addColumn<int>("minSpeedMsecsDeviation");
416+ QTest::addColumn<qreal>("minSpeed");
417+ QTest::addColumn<qreal>("speed");
375 QTest::addColumn<int>("expectedStatusAfterSpeedCheck");
418 QTest::addColumn<int>("expectedStatusAfterSpeedCheck");
376
419
377− QTest::newRow("slower than minSpeed") << 20 << (int)DirectionalDragArea::Rejected;
420+ QTest::newRow("slower than minSpeed") << 100.0 << 50.0 << (int)DirectionalDragArea::WaitingForTouch;
378− QTest::newRow("faster than minSpeed") << -20 << (int)DirectionalDragArea::Undecided;
421+ QTest::newRow("faster than minSpeed") << 100.0 << 150.0 << (int)DirectionalDragArea::Undecided;
379}
422}
380
423
381/*
424/*
@@ -391,32 +434,37 @@ void tst_DirectionalDragArea::recognitionTimerUsage()
391 edgeDragArea->setRecognitionTimer(fakeTimer);
434 edgeDragArea->setRecognitionTimer(fakeTimer);
392 edgeDragArea->setTimeSource(fakeTimeSource);
435 edgeDragArea->setTimeSource(fakeTimeSource);
393
436
437+ // don't let it interfere with our test
438+ edgeDragArea->setMinSpeed(0.0);
439+
440+ int timeStepMs = 5; // some arbitrary small value.
441+
394 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
442 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
395 QPointF touchPoint = initialTouchPos;
443 QPointF touchPoint = initialTouchPos;
396
444
397 QPointF dragDirectionVector(1.0, 0.0);
445 QPointF dragDirectionVector(1.0, 0.0);
398 QPointF touchMovement = dragDirectionVector * (edgeDragArea->distanceThreshold() * 0.2f);
446 QPointF touchMovement = dragDirectionVector * (edgeDragArea->distanceThreshold() * 0.2f);
399
447
448+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
400 QVERIFY(!fakeTimer->isRunning());
449 QVERIFY(!fakeTimer->isRunning());
401
450
402 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
451 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
403
452
453+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
404 QVERIFY(fakeTimer->isRunning());
454 QVERIFY(fakeTimer->isRunning());
405
455
406− // Move a bit in the proper direction
456+ // Move beyond distance threshold and composition time to ensure recognition
407− for (int i=0; i < 3; ++i) {
457+ while (fakeTimeSource->m_msecsSinceReference <= edgeDragArea->compositionTime() ||
458+ (touchPoint - initialTouchPos).manhattanLength() <= edgeDragArea->distanceThreshold()) {
459+
460+ QCOMPARE(edgeDragArea->status() == DirectionalDragArea::Undecided, fakeTimer->isRunning());
461+
408 touchPoint += touchMovement;
462 touchPoint += touchMovement;
463+ passTime(timeStepMs);
409 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
464 QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
410 }
465 }
411
466
412− QVERIFY(fakeTimer->isRunning());
413−
414− // Move beyond distance threshold
415− touchPoint += 3*touchMovement;
416− QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
417−
418 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
467 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
419−
420 QVERIFY(!fakeTimer->isRunning());
468 QVERIFY(!fakeTimer->isRunning());
421}
469}
422
470
@@ -432,29 +480,23 @@ void tst_DirectionalDragArea::maxSilenceTime()
432 edgeDragArea->setRecognitionTimer(fakeTimer);
480 edgeDragArea->setRecognitionTimer(fakeTimer);
433 edgeDragArea->setTimeSource(fakeTimeSource);
481 edgeDragArea->setTimeSource(fakeTimeSource);
434
482
483+ // Make sure this property is not disabled
484+ edgeDragArea->setMaxSilenceTime(100);
485+
435 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
486 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
436 QPointF touchPoint = initialTouchPos;
487 QPointF touchPoint = initialTouchPos;
437
488
438− fakeTimeSource->m_msecsSinceReference = 0;
439 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
489 QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
440
490
441 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
491 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
492+ QVERIFY(fakeTimer->isRunning());
442
493
443− int neededTimeouts = qCeil((qreal)edgeDragArea->maxSilenceTime() / (qreal)fakeTimer->interval());
494+ // Force timer to timeout until after maxSilenceTime has been reached
444− if ((edgeDragArea->maxSilenceTime() % fakeTimer->interval()) == 0) {
495+ while (fakeTimeSource->m_msecsSinceReference < edgeDragArea->maxSilenceTime()) {
445− ++neededTimeouts;
496+ passTime(fakeTimer->interval());
446− }
447−
448− // Force the periodic speed check.
449− for (int i = 0; i < neededTimeouts; ++i) {
450− fakeTimer->emitTimeout();
451−
452− if (i < neededTimeouts - 1) {
453− QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
454− }
455 }
497 }
456
498
457− QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Rejected);
499+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
458}
500}
459
501
460/*
502/*
@@ -471,7 +513,6 @@ void tst_DirectionalDragArea::sceneXAndX()
471
513
472 QPointF touchScenePos(view->width() - (edgeDragArea->width()/2.0f), view->height()/2.0f);
514 QPointF touchScenePos(view->width() - (edgeDragArea->width()/2.0f), view->height()/2.0f);
473
515
474− fakeTimeSource->m_msecsSinceReference = 0;
475 QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
516 QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
476
517
477 QSignalSpy touchXSpy(edgeDragArea, SIGNAL(touchXChanged(qreal)));
518 QSignalSpy touchXSpy(edgeDragArea, SIGNAL(touchXChanged(qreal)));
@@ -500,7 +541,6 @@ void tst_DirectionalDragArea::sceneYAndY()
500
541
501 QPointF touchScenePos(view->width()/2.0f, view->height() - (edgeDragArea->height()/2.0f));
542 QPointF touchScenePos(view->width()/2.0f, view->height() - (edgeDragArea->height()/2.0f));
502
543
503− fakeTimeSource->m_msecsSinceReference = 0;
504 QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
544 QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
505
545
506 QSignalSpy touchYSpy(edgeDragArea, SIGNAL(touchYChanged(qreal)));
546 QSignalSpy touchYSpy(edgeDragArea, SIGNAL(touchYChanged(qreal)));
@@ -516,11 +556,12 @@ void tst_DirectionalDragArea::sceneYAndY()
516}
556}
517
557
518/*
558/*
519− Emit draggingChanged() when status change from WaitingForTouch directly to Recognized.
559+ Regression test for https://bugs.launchpad.net/bugs/1228336
520− This happens when the gesture recognition is effectively disabled (e.g. by setting a
560+
521− distanceThreshold of zero)
561+ Perform a quick two-finger double-tap and check that DirectionalDragArea properly
562+ rejects those touch points. In the bug above it got confused and crashed.
522 */
563 */
523−void tst_DirectionalDragArea::emitDraggingChangedOnDirectRecognition()
564+void tst_DirectionalDragArea::twoFingerTap()
524{
565{
525 DirectionalDragArea *edgeDragArea =
566 DirectionalDragArea *edgeDragArea =
526 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
567 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
@@ -528,22 +569,170 @@ void tst_DirectionalDragArea::emitDraggingChangedOnDirectRecognition()
528 edgeDragArea->setRecognitionTimer(fakeTimer);
569 edgeDragArea->setRecognitionTimer(fakeTimer);
529 edgeDragArea->setTimeSource(fakeTimeSource);
570 edgeDragArea->setTimeSource(fakeTimeSource);
530
571
531− QPointF touchPos = calculateInitialTouchPos(edgeDragArea, view);
572+ // Make touches evenly spaced along the edgeDragArea
573+ QPoint touchAPos(edgeDragArea->width()/2.0f, view->height()*0.33f);
574+ QPoint touchBPos(edgeDragArea->width()/2.0f, view->height()*0.66f);
532
575
533− QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
576+ qint64 timeStepMsecs = 5; // some arbitrary, small value
534
577
535− // That will make it completetly skip the recognition phase ("Undecided" status).
578+ // Perform the first two-finger tap
536− edgeDragArea->setDistanceThreshold(0.0);
579+ // NB: using move() instead of stationary() becasue in the latter you cannot provide
580+ // the touch position and therefore it's left with some garbage numbers.
581+ QTest::touchEvent(view, device)
582+ .press(0, touchAPos);
537
583
584+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
585+
586+ passTime(timeStepMsecs);
587+ QTest::touchEvent(view, device)
588+ .move(0, touchAPos)
589+ .press(1, touchBPos);
590+
591+ // A second touch point appeared during recognition, reject immediately as this
592+ // can't be a single-touch gesture anymore.
538 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
593 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
539− QCOMPARE(edgeDragArea->dragging(), false);
540
594
541− fakeTimeSource->m_msecsSinceReference = 0;
595+ passTime(timeStepMsecs);
596+ QTest::touchEvent(view, device)
597+ .release(0, touchAPos)
598+ .move(1, touchBPos);
599+
600+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
601+
602+ passTime(timeStepMsecs);
603+ QTest::touchEvent(view, device)
604+ .release(1, touchBPos);
605+
606+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
607+
608+ // Perform the second two-finger tap
609+
610+ passTime(timeStepMsecs);
611+ QTest::touchEvent(view, device)
612+ .press(0, touchAPos);
613+
614+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
615+
616+ passTime(timeStepMsecs);
617+ QTest::touchEvent(view, device)
618+ .move(0, touchAPos)
619+ .press(1, touchBPos);
620+
621+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
622+
623+ passTime(timeStepMsecs);
624+ QTest::touchEvent(view, device)
625+ .release(0, touchAPos)
626+ .move(1, touchBPos);
627+
628+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
629+
630+ passTime(timeStepMsecs);
631+ QTest::touchEvent(view, device)
632+ .release(1, touchBPos);
633+
634+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
635+}
636+
637+/*
638+ Tests that gesture recognition works normally even if the DirectionalDragArea moves
639+ during recognition.
640+ This effectively means that we have to do gesture recognition with scene coordinates
641+ instead of local item coordinates.
642+ */
643+void tst_DirectionalDragArea::movingDDA()
644+{
645+ QQuickItem *rightwardsLauncher = view->rootObject()->findChild<QQuickItem*>("rightwardsLauncher");
646+ Q_ASSERT(rightwardsLauncher != 0);
647+
648+ DirectionalDragArea *edgeDragArea =
649+ rightwardsLauncher->findChild<DirectionalDragArea*>("hpDragArea");
650+ Q_ASSERT(edgeDragArea != 0);
651+ edgeDragArea->setRecognitionTimer(fakeTimer);
652+ edgeDragArea->setTimeSource(fakeTimeSource);
653+
654+ QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
655+ QPointF touchPoint = initialTouchPos;
656+
657+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
658+ QPointF dragDirectionVector(1.0f, 0.0f);
659+
660+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
661+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
662+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
663+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
664+
542− QTest::touchEvent(view, device).press(0, touchPos.toPoint());
665+ QTest::touchEvent(view, device).press(0, touchPoint.toPoint());
666+
667+ // Move it far ahead along the direction of the gesture
668+ // rightwardsLauncher is a parent of our DirectionalDragArea. So moving it will move our DDA
669+ rightwardsLauncher->setX(rightwardsLauncher->x() + edgeDragArea->distanceThreshold() * 5.0f);
670+
671+ for (int i = 0; i < totalMovementSteps; ++i) {
672+ touchPoint += touchMovement;
673+ passTime(movementTimeStepMs);
674+ QTest::touchEvent(view, device).move(0, touchPoint.toPoint());
675+ }
543
676
544 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
677 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
545− QCOMPARE(draggingSpy.count(), 1);
678+
679+ QTest::touchEvent(view, device).release(0, touchPoint.toPoint());
680+}
681+
682+/*
683+ The presence of and old, rejected, touch point lying on the DirectionalDragArea
684+ shouldn't impede the recognition of a gesture from a new touch point.
685+ */
686+void tst_DirectionalDragArea::ignoreOldFinger()
687+{
688+ DirectionalDragArea *edgeDragArea =
689+ view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
690+ Q_ASSERT(edgeDragArea != 0);
691+ edgeDragArea->setRecognitionTimer(fakeTimer);
692+ edgeDragArea->setTimeSource(fakeTimeSource);
693+
694+ // Make touches evenly spaced along the edgeDragArea
695+ QPoint touch0Pos(edgeDragArea->width()/2.0f, view->height()*0.33f);
696+ QPoint touch1Pos(edgeDragArea->width()/2.0f, view->height()*0.66f);
697+
698+ QTest::touchEvent(view, device).press(0, touch0Pos);
699+
700+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
701+
702+ // leave it lying around for some time
703+ passTime(qMax(edgeDragArea->maxSilenceTime(), edgeDragArea->compositionTime()) * 10);
704+
705+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
706+
707+ qreal desiredDragDistance = edgeDragArea->distanceThreshold()*2.0f;
708+ QPointF dragDirectionVector(1.0f, 0.0f);
709+
710+ qreal movementStepDistance = edgeDragArea->distanceThreshold() * 0.1f;
711+ QPointF touchMovement = dragDirectionVector * movementStepDistance;
712+ int totalMovementSteps = qCeil(desiredDragDistance / movementStepDistance);
713+ int movementTimeStepMs = (edgeDragArea->compositionTime() * 1.5f) / totalMovementSteps;
714+
715+ QTest::touchEvent(view, device)
716+ .move(0, touch0Pos)
717+ .press(1, touch1Pos);
718+
546− QCOMPARE(edgeDragArea->dragging(), true);
719+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Undecided);
720+
721+ for (int i = 0; i < totalMovementSteps; ++i) {
722+ touch1Pos += touchMovement.toPoint();
723+ passTime(movementTimeStepMs);
724+ QTest::touchEvent(view, device)
725+ .move(0, touch0Pos)
726+ .move(1, touch1Pos);
727+ }
728+
729+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
730+
731+ QTest::touchEvent(view, device)
732+ .move(0, touch0Pos)
733+ .release(1, touch1Pos);
734+
735+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
547}
736}
548
737
549QTEST_MAIN(tst_DirectionalDragArea)
738QTEST_MAIN(tst_DirectionalDragArea)
tests/plugins/Unity/Indicators/CMakeLists.txt+36−27
@@ -1,34 +1,43 @@
1+pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
2+pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
1pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
3pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
2
4
5+set(INDICATORS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../plugins/Unity/Indicators)
6+set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
7+
3include_directories(
8include_directories(
4 ${CMAKE_CURRENT_BINARY_DIR}
9 ${CMAKE_CURRENT_BINARY_DIR}
5− ${CMAKE_CURRENT_SOURCE_DIR}/../../../../plugins/Unity/Indicators
10+ ${INDICATORS_DIR}
6− ${QMENUMODEL_INCLUDE_DIRS}
11+ ${TEST_DIR}/mocks/QMenuModel
12+ ${GLIB_INCLUDE_DIRS}
13+ ${GIO_INCLUDE_DIRS}
7 )
14 )
8
15
9−macro(run_tests)
16+macro(indicator_test TEST)
10− set(_test_list "")
17+ set(multi_value_keywords ADDITIONAL_CPPS ADDITIONAL_LIBS)
11− foreach(_test ${ARGN})
18+ cmake_parse_arguments(test "" "" "${multi_value_keywords}" ${ARGN})
12− set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/${_test}Exec
13− -o ${CMAKE_BINARY_DIR}/${_test}.xml,xunitxml
14− -o -,txt)
15− add_test(NAME ${_test} COMMAND ${testCommand})
16− add_custom_target(${_test} ${testCommand})
17− add_executable(${_test}Exec ${_test}.cpp
18− )
19− qt5_use_modules(${_test}Exec Test Core Qml)
20− target_link_libraries(${_test}Exec
21− IndicatorsQml
22− ${QMENUMODEL_LDFLAGS}
23− )
24− set(_test_list "${_test_list};${_test}")
25− endforeach()
26−endmacro(run_tests)
27
19
28−run_tests(
20+ set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/${TEST}Exec
21+ -o ${CMAKE_BINARY_DIR}/${TEST}.xml,xunitxml
22+ -o -,txt)
23+ add_test(NAME ${TEST} COMMAND ${testCommand})
24+ add_custom_target(${TEST} ${testCommand})
25+ add_executable(${TEST}Exec
26+ ${TEST}.cpp
27+ ${test_ADDITIONAL_CPPS}
28+ )
29+ qt5_use_modules(${TEST}Exec Test Core Qml)
30+ target_link_libraries(${TEST}Exec
31+ ${test_ADDITIONAL_LIBS}
32+ ${GLIB_LIBRARIES}
33+ ${GIO_LIBRARIES}
34+ ${QMENUMODEL_LDFLAGS}
35+ )
36+endmacro(indicator_test)
37+
29− indicatorsmanagertest
38+indicator_test(indicatorsmanagertest ADDITIONAL_LIBS IndicatorsQml)
30− indicatorsmodeltest
39+indicator_test(indicatorsmodeltest ADDITIONAL_LIBS IndicatorsQml)
31− menucontentactivatortest
40+indicator_test(menucontentactivatortest ADDITIONAL_CPPS ${INDICATORS_DIR}/menucontentactivator.cpp)
41+indicator_test(unitymenumodelstacktest ADDITIONAL_CPPS ${TEST_DIR}/mocks/QMenuModel/unitymenumodel.cpp ${INDICATORS_DIR}/unitymenumodelstack.cpp)
32− rootactionstatetest
42+indicator_test(rootactionstatetest ADDITIONAL_LIBS IndicatorsQml)
33− timeformattertest
43+indicator_test(timeformattertest ADDITIONAL_LIBS IndicatorsQml)
34− )
tests/plugins/Unity/Indicators/unitymenumodelstacktest.cppnew file+206
@@ -0,0 +1,206 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+#include "indicatorsmanager.h"
21+#include "paths.h"
22+#include "unitymenumodelstack.h"
23+
24+#include <QtTest>
25+#include <QDebug>
26+#include <unitymenumodel.h>
27+
28+class UnityMenuModelStackTest : public QObject
29+{
30+ Q_OBJECT
31+private Q_SLOTS:
32+
33+ void init()
34+ {
35+ m_model = new UnityMenuModel();
36+ m_headChanged = false;
37+ m_tailChanged = false;
38+ }
39+
40+ void cleanup()
41+ {
42+ delete m_model;
43+ m_model = NULL;
44+ }
45+
46+ void testHeadOnSetHead()
47+ {
48+ UnityMenuModelStack stack;
49+ connect(&stack, SIGNAL(headChanged(UnityMenuModel*)), this, SLOT(onHeadChanged()));
50+ stack.setHead(m_model);
51+
52+ QCOMPARE(stack.head(), m_model);
53+ QCOMPARE(m_headChanged, true);
54+ }
55+
56+ void testTailOnSetHead()
57+ {
58+ UnityMenuModelStack stack;
59+ connect(&stack, SIGNAL(tailChanged(UnityMenuModel*)), this, SLOT(onTailChanged()));
60+ stack.setHead(m_model);
61+
62+ QCOMPARE(stack.tail(), m_model);
63+ QCOMPARE(m_tailChanged, true);
64+ }
65+
66+ void testPushPop_data() {
67+ QTest::addColumn<int>("menuDepth");
68+ QTest::addColumn<int>("subMenuCount");
69+ QTest::addColumn<int>("subMenuIndex");
70+
71+ QTest::newRow("depth=0") << 0 << 1 << 0;
72+ QTest::newRow("depth=1") << 1 << 1 << 0;
73+ QTest::newRow("depth=8") << 8 << 2 << 1;
74+ }
75+
76+ void testPushPop()
77+ {
78+ QFETCH(int, menuDepth);
79+ QFETCH(int, subMenuCount);
80+ QFETCH(int, subMenuIndex);
81+
82+ m_model->setModelData(recuseAddMenu(subMenuCount, menuDepth));
83+
84+ UnityMenuModelStack stack;
85+ connect(&stack, SIGNAL(tailChanged(UnityMenuModel*)), this, SLOT(onTailChanged()));
86+
87+ QList<UnityMenuModel*> models;
88+
89+ int count = 0;
90+ auto foreachChild = [&](UnityMenuModel* child, int childIndex) {
91+ stack.push(child, childIndex);
92+ QCOMPARE(stack.count(), count+1);
93+
94+ count++;
95+ models << child;
96+ };
97+ recuseSubmenus(m_model, subMenuIndex, foreachChild);
98+
99+ QCOMPARE(stack.count(), models.count());
100+ QCOMPARE(stack.count(), menuDepth+1);
101+ while(stack.count() > 0) {
102+ m_tailChanged = false;
103+
104+ QCOMPARE(stack.pop(), models.takeLast());
105+
106+ QCOMPARE(m_tailChanged, true);
107+ if (stack.count()) {
108+ QCOMPARE(stack.tail(), models.last());
109+ }
110+ }
111+ QCOMPARE(m_tailChanged, true);
112+ }
113+
114+ void testPopOnRemove_data() {
115+ QTest::addColumn<int>("menuDepth");
116+ QTest::addColumn<int>("subMenuCount");
117+ QTest::addColumn<int>("subMenuIndex");
118+ QTest::addColumn<int>("removeIndex");
119+ QTest::addColumn<int>("resultCount");
120+
121+ QTest::newRow("removeIndexBefore") << 4 << 2 << 1 << 0 << 5;
122+ QTest::newRow("removeCurrentIndex") << 4 << 2 << 0 << 0 << 1;
123+ QTest::newRow("removeIndexAfter") << 4 << 2 << 0 << 1 << 5;
124+ }
125+
126+ void testPopOnRemove()
127+ {
128+ QFETCH(int, menuDepth);
129+ QFETCH(int, subMenuCount);
130+ QFETCH(int, subMenuIndex);
131+ QFETCH(int, removeIndex);
132+ QFETCH(int, resultCount);
133+
134+ m_model->setModelData(recuseAddMenu(subMenuCount, menuDepth));
135+
136+ UnityMenuModelStack stack;
137+
138+ auto foreachChild = [&](UnityMenuModel* child, int childIndex) {
139+ stack.push(child, childIndex);
140+ };
141+ recuseSubmenus(m_model, subMenuIndex, foreachChild);
142+
143+ QCOMPARE(stack.count(), menuDepth+1);
144+
145+ m_model->removeRow(removeIndex);
146+
147+ waitFor([&stack, resultCount]() { return stack.count() == resultCount; }, 1000);
148+ QCOMPARE(stack.count(), resultCount);
149+ }
150+
151+private:
152+ bool waitFor(std::function<bool()> functor, int ms) {
153+
154+ QElapsedTimer timer;
155+ timer.start();
156+ while(!functor() && timer.elapsed() < ms) { QTest::qWait(10); }
157+ return functor();
158+ }
159+
160+ QVariant recuseAddMenu(int subMenuCount, int depth_remaining)
161+ {
162+ QVariantList rows;
163+
164+ for (int i = 0; i < subMenuCount; i ++) {
165+ QVariantMap row;
166+ QVariantMap rowData;
167+
168+ if (depth_remaining > 0) {
169+ row["submenu"] = recuseAddMenu(subMenuCount, depth_remaining-1);
170+ }
171+
172+ row["rowData"] = rowData;
173+
174+ rows << row;
175+ }
176+
177+ return rows;
178+ }
179+
180+ void recuseSubmenus(UnityMenuModel* model, int childIndex, std::function<void(UnityMenuModel*, int)> func) {
181+ UnityMenuModel* parent = model;
182+ UnityMenuModel* child = model;
183+
184+ while(child) {
185+ if (func) {
186+ func(child, childIndex);
187+ }
188+
189+ parent = child;
190+ child = qobject_cast<UnityMenuModel*>(parent->submenu(childIndex));
191+ }
192+
193+ }
194+
195+private Q_SLOTS:
196+ void onHeadChanged() { m_headChanged = true; }
197+ void onTailChanged() { m_tailChanged = true; }
198+
199+public:
200+ UnityMenuModel* m_model;
201+ bool m_headChanged;
202+ bool m_tailChanged;
203+};
204+
205+QTEST_GUILESS_MAIN(UnityMenuModelStackTest)
206+#include "unitymenumodelstacktest.moc"
tests/qmltests/CMakeLists.txt+5−3
@@ -13,11 +13,9 @@ set(qmltest_DEFAULT_NO_ADD_TEST FALSE)
13set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
13set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
14add_qml_test(Components AnimationControllerWithSignals)
14add_qml_test(Components AnimationControllerWithSignals)
15add_qml_test(Components Carousel)
15add_qml_test(Components Carousel)
16−add_qml_test(Components MathLocal)
17add_qml_test(Components OpenEffect)
16add_qml_test(Components OpenEffect)
18add_qml_test(Components RatingStars)
17add_qml_test(Components RatingStars)
19add_qml_test(Components TimeLocal)
18add_qml_test(Components TimeLocal)
20−add_qml_test(Greeter Clock IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
21add_qml_test(Panel IndicatorItem)
19add_qml_test(Panel IndicatorItem)
22add_qml_test(utils/Unity/Test UnityTest)
20add_qml_test(utils/Unity/Test UnityTest)
23
21
@@ -62,15 +60,19 @@ add_qml_test(Greeter Phone IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DE
62 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
60 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
63add_qml_test(Greeter Infographics IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
61add_qml_test(Greeter Infographics IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
64 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
62 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
63+add_qml_test(Greeter Clock IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
64+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
65add_qml_test(Hud Hud)
65add_qml_test(Hud Hud)
66add_qml_test(Hud Result)
66add_qml_test(Hud Result)
67add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
67add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
68−add_qml_test(Notifications Notifications IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_SOURCE_DIR}/tests/mocks)
68+add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
69add_qml_test(Panel IndicatorRow)
69add_qml_test(Panel IndicatorRow)
70add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
70add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
71add_qml_test(Panel MenuContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
71add_qml_test(Panel MenuContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
72add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
72add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
73add_qml_test(Panel SearchIndicator)
73add_qml_test(Panel SearchIndicator)
74+add_qml_test(Panel/Indicators DefaultIndicatorWidget IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
75+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
74add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
76add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
75 ${CMAKE_BINARY_DIR}/tests/mocks
77 ${CMAKE_BINARY_DIR}/tests/mocks
76 ${CMAKE_BINARY_DIR}/plugins)
78 ${CMAKE_BINARY_DIR}/plugins)
tests/qmltests/Components/tst_DragHandle.cpp+4−5
@@ -41,7 +41,7 @@ class FakeTimeSource : public UbuntuGestures::TimeSource
41{
41{
42public:
42public:
43 FakeTimeSource() { m_msecsSinceReference = 0; }
43 FakeTimeSource() { m_msecsSinceReference = 0; }
44− virtual qint64 msecsSinceReference() {return m_msecsSinceReference;}
44+ qint64 msecsSinceReference() override {return m_msecsSinceReference;}
45 qint64 m_msecsSinceReference;
45 qint64 m_msecsSinceReference;
46};
46};
47
47
@@ -73,7 +73,7 @@ private:
73 QQuickView *m_view;
73 QQuickView *m_view;
74 QTouchDevice *m_device;
74 QTouchDevice *m_device;
75 FakeTimer *m_fakeTimer;
75 FakeTimer *m_fakeTimer;
76− FakeTimeSource *m_fakeTimeSource;
76+ QSharedPointer<FakeTimeSource> m_fakeTimeSource;
77};
77};
78
78
79
79
@@ -102,7 +102,7 @@ void tst_DragHandle::init()
102 qApp->processEvents();
102 qApp->processEvents();
103
103
104 m_fakeTimer = new FakeTimer;
104 m_fakeTimer = new FakeTimer;
105− m_fakeTimeSource = new FakeTimeSource;
105+ m_fakeTimeSource.reset(new FakeTimeSource);
106}
106}
107
107
108void tst_DragHandle::cleanup()
108void tst_DragHandle::cleanup()
@@ -113,8 +113,7 @@ void tst_DragHandle::cleanup()
113 delete m_fakeTimer;
113 delete m_fakeTimer;
114 m_fakeTimer = 0;
114 m_fakeTimer = 0;
115
115
116− delete m_fakeTimeSource;
116+ m_fakeTimeSource.reset();
117− m_fakeTimeSource = 0;
118}
117}
119
118
120QQuickView *tst_DragHandle::createView()
119QQuickView *tst_DragHandle::createView()
tests/qmltests/Components/tst_EdgeDemoOverlay.qml+2−2
@@ -112,8 +112,8 @@ Item {
112 // Test that the 'none' edge skips anywhere
112 // Test that the 'none' edge skips anywhere
113 signalSpy.target = none
113 signalSpy.target = none
114 signalSpy.clear()
114 signalSpy.clear()
115− var backgroundShade = findChild(none, "backgroundShade")
115+ var backgroundShade = findChild(none, "backgroundShadeMouseArea")
116− tryCompare(none, "opacity", 1)
116+ tryCompare(backgroundShade, "enabled", true)
117 mousePress(backgroundShade, 1, 1)
117 mousePress(backgroundShade, 1, 1)
118 mouseRelease(backgroundShade, 1, 1)
118 mouseRelease(backgroundShade, 1, 1)
119 signalSpy.wait()
119 signalSpy.wait()
tests/qmltests/Components/tst_MathLocal.qmldeleted−91
@@ -1,91 +0,0 @@
1−/*
2− * Copyright 2013 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import "../../../Components/Math.js" as MathLocal
20−
21−TestCase {
22− name: "MathLocal"
23−
24− property int minValue
25− property int maxValue
26− property int clampValue
27− property int clamped
28−
29− function test_clamp_positive_lower() {
30− minValue = 9
31− maxValue = 42
32− clampValue = -7
33−
34− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
35− compare(clamped, minValue, "clamped value not within range")
36− }
37−
38− function test_clamp_positive_greater() {
39− minValue = 9
40− maxValue = 42
41− clampValue = 111
42−
43− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
44− compare(clamped, maxValue, "clamped value not within range")
45− }
46−
47− function test_clamp_positive_within() {
48− minValue = 9
49− maxValue = 53
50− clampValue = 42
51−
52− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
53− compare(clamped, clampValue, "clamped value changed even though it shouldn't have")
54− }
55−
56− function test_clamp_positive_on_border() {
57− minValue = 9
58− maxValue = 42
59− clampValue = 9
60−
61− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
62− compare(clamped, clampValue, "clamped value changed even though it shouldn't have")
63− }
64−
65− function test_clamp_negative_lower() {
66− minValue = -42
67− maxValue = -9
68− clampValue = -50
69−
70− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
71− compare(clamped, minValue, "clamped value not within range")
72− }
73−
74− function test_clamp_negative_greater() {
75− minValue = -42
76− maxValue = -9
77− clampValue = 50
78−
79− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
80− compare(clamped, maxValue, "clamped value not within range")
81− }
82−
83− function test_clamp_postive_and_negative_greater() {
84− minValue = -42
85− maxValue = 9
86− clampValue = 50
87−
88− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
89− compare(clamped, maxValue, "clamped value not within range")
90− }
91−}
tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml+1
@@ -226,6 +226,7 @@ Item {
226 verify(fakeRunningAppsModel.contains("calendar"))
226 verify(fakeRunningAppsModel.contains("calendar"))
227
227
228 mouseClick(calendarTileCloseButton, calendarTileCloseButton.width/2, calendarTileCloseButton.height/2)
228 mouseClick(calendarTileCloseButton, calendarTileCloseButton.width/2, calendarTileCloseButton.height/2)
229+ wait(0) // spin event loop to start any pending animation
229
230
230 verify(!fakeRunningAppsModel.contains("calendar"))
231 verify(!fakeRunningAppsModel.contains("calendar"))
231
232
tests/qmltests/Dash/qml/FakeScopeView.qml+1
@@ -23,6 +23,7 @@ ScopeView {
23 id: fakeScopeView
23 id: fakeScopeView
24
24
25 property alias backColor : back.color
25 property alias backColor : back.color
26+ moving: listView.moving
26
27
27 onEndReached: {
28 onEndReached: {
28 if (shell != undefined && shell.scopeStatus != undefined) {
29 if (shell != undefined && shell.scopeStatus != undefined) {
tests/qmltests/Dash/tst_Dash.qml+2
@@ -103,6 +103,8 @@ Item {
103 return;
103 return;
104 }
104 }
105 dash.showScopeOnLoaded = data.tag
105 dash.showScopeOnLoaded = data.tag
106+ scopes.clear();
107+ scopes.load();
106
108
107 var dashContentList = findChild(dash, "dashContentList");
109 var dashContentList = findChild(dash, "dashContentList");
108 verify(dashContentList != undefined);
110 verify(dashContentList != undefined);
tests/qmltests/Dash/tst_DashContent.qml+14
@@ -229,5 +229,19 @@ Item {
229 tryCompare(scopesModel.get(1), "isActive", data.active1);
229 tryCompare(scopesModel.get(1), "isActive", data.active1);
230 tryCompare(scopesModel.get(2), "isActive", data.active2);
230 tryCompare(scopesModel.get(2), "isActive", data.active2);
231 }
231 }
232+
233+ function test_hswipe_disabled_vswipe() {
234+ var dashContentList = findChild(dashContent, "dashContentList");
235+
236+ tryCompare(dashContentList, "interactive", true);
237+
238+ var startX = dashContentList.width/2;
239+ var startY = dashContentList.height/2;
240+ touchFlick(dashContentList, startX, startY, startX, startY - units.gu(800));
241+
242+ tryCompare(dashContentList.currentItem, "moving", true);
243+
244+ compare(dashContentList.interactive, false);
245+ }
232 }
246 }
233}
247}
tests/qmltests/Dash/tst_GenericScopeView.qml+7−2
@@ -74,6 +74,9 @@ Item {
74 }
74 }
75
75
76 function openPreview() {
76 function openPreview() {
77+ var categoryListView = findChild(genericScopeView, "categoryListView");
78+ categoryListView.positionAtBeginning();
79+
77 var tile = findChild(genericScopeView, "delegate0");
80 var tile = findChild(genericScopeView, "delegate0");
78 mouseClick(tile, tile.width / 2, tile.height / 2);
81 mouseClick(tile, tile.width / 2, tile.height / 2);
79 var openEffect = findChild(genericScopeView, "openEffect");
82 var openEffect = findChild(genericScopeView, "openEffect");
@@ -167,14 +170,16 @@ Item {
167 true);
170 true);
168 tryCompare(nextPreviewItem, "progress", 1);
171 tryCompare(nextPreviewItem, "progress", 1);
169 waitForRendering(nextPreviewItem);
172 waitForRendering(nextPreviewItem);
173+ tryCompareFunction(function() {return nextPreviewItem.item !== null}, true);
170
174
171 checkArrowPosition(i);
175 checkArrowPosition(i);
172
176
173 // Make sure only the new one has isCurrent set to true
177 // Make sure only the new one has isCurrent set to true
178+ compare(nextPreviewItem.item.isCurrent, true);
179+
174− if (currentPreviewItem.item) {
180+ if (currentPreviewItem.item !== undefined && currentPreviewItem.item !== null) {
175 compare(currentPreviewItem.item.isCurrent, false);
181 compare(currentPreviewItem.item.isCurrent, false);
176 }
182 }
177− compare(nextPreviewItem.item.isCurrent, true);
178
183
179 currentPreviewItem = nextPreviewItem;
184 currentPreviewItem = nextPreviewItem;
180 }
185 }
tests/qmltests/Greeter/tst_Clock.qml+16
@@ -19,6 +19,7 @@ import QtTest 1.0
19import ".."
19import ".."
20import "../../../Greeter"
20import "../../../Greeter"
21import Ubuntu.Components 0.1
21import Ubuntu.Components 0.1
22+import QMenuModel 0.1
22import Unity.Test 0.1 as UT
23import Unity.Test 0.1 as UT
23
24
24Rectangle {
25Rectangle {
@@ -35,9 +36,24 @@ Rectangle {
35 }
36 }
36 }
37 }
37
38
39+ UnityMenuModel {
40+ id: menuModel
41+ modelData: [{
42+ "rowData": {
43+ "actionState": { "label": Qt.formatTime(new Date("October 13, 1975 11:13:00")) }
44+ }
45+ }]
46+ }
47+
38 UT.UnityTestCase {
48 UT.UnityTestCase {
39 name: "Clock"
49 name: "Clock"
40
50
51+ function init() {
52+ var cachedModel = findChild(clock, "timeModel");
53+ verify(cachedModel !== undefined);
54+ cachedModel.model = menuModel;
55+ }
56+
41 function test_customDate() {
57 function test_customDate() {
42 var dateObj = new Date("October 13, 1975 11:13:00")
58 var dateObj = new Date("October 13, 1975 11:13:00")
43 var dateString = Qt.formatDate(dateObj, Qt.DefaultLocaleLongDate)
59 var dateString = Qt.formatDate(dateObj, Qt.DefaultLocaleLongDate)
tests/qmltests/Greeter/tst_Lockscreen.qml+42−4
@@ -176,15 +176,17 @@ Rectangle {
176
176
177 function test_unlock_data() {
177 function test_unlock_data() {
178 return [
178 return [
179− {tag: "numeric", alphanumeric: false, username: "has-pin", password: "1234", unlockedSignal: true},
179+ {tag: "numeric", alphanumeric: false, username: "has-pin", password: "1234", unlockedSignal: true, pinLength: 4},
180− {tag: "alphanumeric", alphanumeric: true, username: "has-password", password: "password", unlockedSignal: true},
180+ {tag: "alphanumeric", alphanumeric: true, username: "has-password", password: "password", unlockedSignal: true, pinLength: -1},
181− {tag: "numeric (wrong)", alphanumeric: false, username: "has-pin", password: "4321", unlockedSignal: false},
181+ {tag: "numeric (wrong)", alphanumeric: false, username: "has-pin", password: "4321", unlockedSignal: false, pinLength: 4},
182− {tag: "alphanumeric (wrong)", alphanumeric: true, username: "has-password", password: "drowssap", unlockedSignal: false},
182+ {tag: "alphanumeric (wrong)", alphanumeric: true, username: "has-password", password: "drowssap", unlockedSignal: false, pinLength: -1},
183+ {tag: "flexible length", alphanumeric: false, username: "has-pin", password: "1234", unlockedSignal: true, pinLength: -1},
183 ]
184 ]
184 }
185 }
185
186
186 function test_unlock(data) {
187 function test_unlock(data) {
187 unlockedCheckBox.checked = false
188 unlockedCheckBox.checked = false
189+ pinLengthTextField.text = data.pinLength
188 LightDM.Greeter.authenticate(data.username)
190 LightDM.Greeter.authenticate(data.username)
189 waitForRendering(lockscreen)
191 waitForRendering(lockscreen)
190
192
@@ -199,7 +201,12 @@ Rectangle {
199 var button = findChild(lockscreen, "pinPadButton" + character)
201 var button = findChild(lockscreen, "pinPadButton" + character)
200 mouseClick(button, units.gu(1), units.gu(1))
202 mouseClick(button, units.gu(1), units.gu(1))
201 }
203 }
204+ if (data.pinLength == -1) {
205+ var pinPadButtonErase = findChild(lockscreen, "pinPadButtonErase");
206+ mouseClick(pinPadButtonErase, units.gu(1), units.gu(1));
207+ }
202 }
208 }
209+
203 tryCompare(unlockedCheckBox, "checked", data.unlockedSignal)
210 tryCompare(unlockedCheckBox, "checked", data.unlockedSignal)
204 if (!data.unlockedSignal) {
211 if (!data.unlockedSignal) {
205 // make sure the input is cleared on wrong input
212 // make sure the input is cleared on wrong input
@@ -208,5 +215,36 @@ Rectangle {
208 tryCompareFunction(function() {return inputField.text.length > 0}, true)
215 tryCompareFunction(function() {return inputField.text.length > 0}, true)
209 }
216 }
210 }
217 }
218+
219+ function test_backspace_data() {
220+ return [
221+ {tag: "fixed length", pinLength: 4},
222+ {tag: "variable length", pinLength: -1}
223+ ];
224+ }
225+
226+ function test_backspace(data) {
227+ LightDM.Greeter.authenticate("has-pin");
228+ pinLengthTextField.text = data.pinLength
229+ waitForRendering(lockscreen);
230+
231+ var pinPadButtonErase = findChild(lockscreen, "pinPadButtonErase");
232+ var backspaceIcon = findChild(lockscreen, "backspaceIcon");
233+ var pinEntryField = findChild(lockscreen, "pinentryField");
234+
235+ compare(pinPadButtonErase.iconName, data.pinLength == -1 ? "" : "erase");
236+ compare(backspaceIcon.visible, data.pinLength == -1);
237+
238+ var pinPadButton5 = findChild(lockscreen, "pinPadButton5");
239+ mouseClick(pinPadButton5, units.gu(1), units.gu(1));
240+ compare(pinEntryField.text, "5");
241+
242+ if (data.pinLength == -1) {
243+ mouseClick(backspaceIcon, units.gu(1), units.gu(1));
244+ } else {
245+ mouseClick(pinPadButtonErase, units.gu(1), units.gu(1));
246+ }
247+ compare(pinEntryField.text, "");
248+ }
211 }
249 }
212}
250}
tests/qmltests/Greeter/tst_Phone.qml+23−10
@@ -83,8 +83,9 @@ Item {
83
83
84 function test_teaseLockedUnlocked_data() {
84 function test_teaseLockedUnlocked_data() {
85 return [
85 return [
86− {tag: "unlocked", locked: false},
86+ {tag: "unlocked", locked: false, moved: false},
87− {tag: "locked", locked: true}
87+ {tag: "locked", locked: true, moved: false},
88+ {tag: "moved", locked: false, moved: true}
88 ];
89 ];
89 }
90 }
90
91
@@ -93,10 +94,16 @@ Item {
93 tryCompare(greeter, "x", 0);
94 tryCompare(greeter, "x", 0);
94 greeter.locked = data.locked;
95 greeter.locked = data.locked;
95
96
97+ // simulate greeter being in the middle of a swipe
98+ if (data.moved) {
99+ greeter.x = -units.gu(4);
100+ tryCompare(greeter, "x", -units.gu(4));
101+ }
102+
96 mouseClick(greeter, greeter.width - units.gu(5), greeter.height - units.gu(1));
103 mouseClick(greeter, greeter.width - units.gu(5), greeter.height - units.gu(1));
97 greeter.minX = 0; // This is needed because the transition actually makes x jump once before animating
104 greeter.minX = 0; // This is needed because the transition actually makes x jump once before animating
98
105
99− if (!data.locked) {
106+ if (!data.locked && !data.moved) {
100 // Check if it has been moved over by 2 GUs. Give it a 2 pixel grace area
107 // Check if it has been moved over by 2 GUs. Give it a 2 pixel grace area
101 // because animation duration and teaseTimer are the same duration and
108 // because animation duration and teaseTimer are the same duration and
102 // might cause slight offsets
109 // might cause slight offsets
@@ -104,10 +111,16 @@ Item {
104 } else {
111 } else {
105 // waiting 100ms to make sure nothing moves
112 // waiting 100ms to make sure nothing moves
106 wait(100);
113 wait(100);
107− compare(greeter.minX, 0, "Greeter moved even tho its locked");
114+ compare(greeter.minX, 0, "Greeter teasing not disabled even though it's locked or moving.");
108 }
115 }
116+
117+ // Restore position in case we moved it for the test
118+ if (data.moved) {
119+ greeter.x = 0;
120+ }
121+
109 // Wait until we're back to 0
122 // Wait until we're back to 0
110− tryCompareFunction(function() { return greeter.x;}, 0);
123+ tryCompareFunction(function() { return greeter.x;}, 0);
111 }
124 }
112
125
113 function test_statsWelcomeScreen() {
126 function test_statsWelcomeScreen() {
@@ -120,7 +133,7 @@ Item {
120 tryCompare(LightDM.Infographic, "username", "single")
133 tryCompare(LightDM.Infographic, "username", "single")
121 }
134 }
122
135
123− function test_wallpaper_data() {
136+ function test_background_data() {
124 return [
137 return [
125 {tag: "set", accounts: "../tests/data/unity/backgrounds/blue.png", expected: "blue.png"},
138 {tag: "set", accounts: "../tests/data/unity/backgrounds/blue.png", expected: "blue.png"},
126 {tag: "unset", accounts: "", expected: "background.jpg"},
139 {tag: "unset", accounts: "", expected: "background.jpg"},
@@ -128,12 +141,12 @@ Item {
128 ]
141 ]
129 }
142 }
130
143
131− function test_wallpaper(data) {
144+ function test_background(data) {
132 var loader = findChild(greeter, "greeterContentLoader")
145 var loader = findChild(greeter, "greeterContentLoader")
133− var wallpaper = findChild(loader.item, "wallpaper")
146+ var background = findChild(loader.item, "greeterBackground")
134 AccountsService.backgroundFile = data.accounts
147 AccountsService.backgroundFile = data.accounts
135− tryCompareFunction(function() { return wallpaper.source.toString().indexOf(data.expected) !== -1; }, true)
148+ tryCompareFunction(function() { return background.source.toString().indexOf(data.expected) !== -1; }, true)
136− tryCompare(wallpaper, "status", Image.Ready)
149+ tryCompare(background, "status", Image.Ready)
137 }
150 }
138 }
151 }
139}
152}
tests/qmltests/Panel/Indicators/tst_DefaultIndicatorWidget.qmlnew file+97
@@ -0,0 +1,97 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtTest 1.0
19+import Unity.Test 0.1 as UT
20+import QMenuModel 0.1
21+import "../../../../Panel/Indicators"
22+
23+Item {
24+ id: testView
25+ width: units.gu(40)
26+ height: units.gu(70)
27+
28+ DefaultIndicatorWidget {
29+ id: widget
30+
31+ anchors {
32+ left: parent.left
33+ top: parent.top
34+ }
35+
36+ busName: "test"
37+ actionsObjectPath: "test"
38+ deviceMenuObjectPath: "test"
39+
40+ rootMenuType: ""
41+
42+ iconSize: units.gu(3.2)
43+ height: units.gu(3)
44+
45+ rootActionState {
46+ icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ]
47+ leftLabel: "left"
48+ rightLabel: "right"
49+ }
50+ }
51+
52+ UT.UnityTestCase {
53+ name: "DefaultIndicatorWidget"
54+ when: windowShown
55+
56+ function init() {
57+ widget.rootActionState.icons = [];
58+ widget.rootActionState.leftLabel = "";
59+ widget.rootActionState.rightLabel = "";
60+ wait(50);
61+ }
62+
63+ function test_guRoundedWidth_data() {
64+ return [
65+ { tag: "empty", icons: [], leftLabel: "", rightLabel: "" },
66+ { tag: "1-icon-no-label", icons: [ "image://theme/audio-volume-high" ], leftLabel: "", rightLabel: "" },
67+ { tag: "2-icon-no-label", icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ], leftLabel: "", rightLabel: "" },
68+ { tag: "no-icon-l-label", icons: [], leftLabel: "left", rightLabel: "" },
69+ { tag: "no-icon-lr-label", icons: [], leftLabel: "left", rightLabel: "right" },
70+ { tag: "1-icon-l-label", icons: [ "image://theme/audio-volume-high" ], leftLabel: "left", rightLabel: "" },
71+ { tag: "1-icon-lr-label", icons: [ "image://theme/audio-volume-high" ], leftLabel: "left", rightLabel: "right" },
72+ { tag: "2-icon-l-label", icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ], leftLabel: "left", rightLabel: "" },
73+ { tag: "2-icon-lr-label", icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ], leftLabel: "left", rightLabel: "right" }
74+ ];
75+ }
76+
77+ function test_guRoundedWidth(data) {
78+ widget.rootActionState.icons = data.icons
79+ widget.rootActionState.leftLabel = data.leftLabel;
80+ widget.rootActionState.rightLabel = data.rightLabel;
81+ wait(50);
82+
83+ compare(widget.width, guRoundUp(widget.width));
84+ }
85+ }
86+
87+ // TODO: Use toolkit function https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1242575
88+ function guRoundUp(width) {
89+ if (width == 0) {
90+ return 0;
91+ }
92+ var gu1 = units.gu(1.0);
93+ var mod = (width % gu1);
94+
95+ return mod == 0 ? width : width + (gu1 - mod);
96+ }
97+}
tests/qmltests/Panel/tst_Panel.qml−1
@@ -52,7 +52,6 @@ Item {
52 {tag: "fullscreen", fullscreenFlag: true }
52 {tag: "fullscreen", fullscreenFlag: true }
53 ]}
53 ]}
54
54
55−
56 function init() {
55 function init() {
57 searchClicked = false;
56 searchClicked = false;
58 panel.indicators.hide();
57 panel.indicators.hide();
tests/qmltests/tst_Shell.qml+85−22
@@ -55,19 +55,42 @@ Item {
55 when: windowShown
55 when: windowShown
56
56
57 function initTestCase() {
57 function initTestCase() {
58− swipeAwayGreeter();
58+ var ok = false;
59+ var attempts = 0;
60+ var maxAttempts = 1000;
61+
62+ // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
63+ // tests may fail because the desired child item wasn't loaded yet.
64+ // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
65+ // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
66+ // (all items instantiated, etc), I resort to checking the existence of some key items until
67+ // repeatedly until they're all there.
68+ do {
69+ var dashContentList = findChild(shell, "dashContentList");
70+ waitForRendering(dashContentList);
71+ var homeLoader = findChild(dashContentList, "home.scope loader");
72+ ok = homeLoader !== undefined
73+ && homeLoader.item !== undefined;
59
74
60− // Ensure DashHome is loaded before continuing
75+ var greeter = findChild(shell, "greeter");
61− var dashContentList = findChild(shell, "dashContentList");
76+ ok &= greeter !== undefined;
62− waitForRendering(dashContentList);
77+
63− var homeLoader = findChild(dashContentList, "home.scope loader");
78+ var launcherPanel = findChild(shell, "launcherPanel");
64− verify(homeLoader);
79+ ok &= launcherPanel !== undefined;
65− tryCompareFunction(function() {return homeLoader.item !== undefined;}, true);
80+
81+ attempts++;
82+ if (!ok) {
83+ console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
84+ // wait a bit before retrying
85+ wait(100);
86+ } else {
87+ console.log("All seem fine after " + attempts + " attempts.");
88+ }
89+ } while (!ok && attempts <= maxAttempts);
66
90
67− // FIXME: Desperate measure to ensure Jenkins has the scene graph fully loaded
91+ verify(ok);
68− // before it calls the test functions (otherwise findChild calls will fail).
92+
69− // The code above just didn't solve it.
93+ swipeAwayGreeter();
70− wait(2000);
71 }
94 }
72
95
73 function cleanup() {
96 function cleanup() {
@@ -111,14 +134,14 @@ Item {
111 waitUntilApplicationWindowIsFullyVisible();
134 waitUntilApplicationWindowIsFullyVisible();
112
135
113 // Minimize the application we just launched
136 // Minimize the application we just launched
114− swipeFromLeftEdge();
137+ swipeFromLeftEdge(units.gu(27));
115
138
116 waitForUIToSettle();
139 waitForUIToSettle();
117
140
118 checkRightEdgeDragWithMinimizedApp();
141 checkRightEdgeDragWithMinimizedApp();
119
142
120 // Minimize that application once again
143 // Minimize that application once again
121− swipeFromLeftEdge();
144+ swipeFromLeftEdge(units.gu(27));
122
145
123 // Right edge behavior should now be the same as before that app,
146 // Right edge behavior should now be the same as before that app,
124 // was launched. Manually cleanup beforehand to get to initial
147 // was launched. Manually cleanup beforehand to get to initial
@@ -130,8 +153,10 @@ Item {
130
153
131 function test_leftEdgeDrag_data() {
154 function test_leftEdgeDrag_data() {
132 return [
155 return [
133− {tag: "without launcher", revealLauncher: false},
156+ {tag: "without launcher", revealLauncher: false, swipeLength: units.gu(27), appHides: true},
134− {tag: "with launcher", revealLauncher: true},
157+ {tag: "with launcher", revealLauncher: true, swipeLength: units.gu(27), appHides: true},
158+ {tag: "small swipe", revealLauncher: false, swipeLength: units.gu(25), appHides: false},
159+ {tag: "long swipe", revealLauncher: false, swipeLength: units.gu(27), appHides: true}
135 ];
160 ];
136 }
161 }
137
162
@@ -144,8 +169,11 @@ Item {
144 dragLauncherIntoView();
169 dragLauncherIntoView();
145 }
170 }
146
171
147− swipeFromLeftEdge();
172+ swipeFromLeftEdge(data.swipeLength);
173+ if (data.appHides)
148− waitUntilApplicationWindowIsFullyHidden();
174+ waitUntilApplicationWindowIsFullyHidden();
175+ else
176+ waitUntilApplicationWindowIsFullyVisible();
149 }
177 }
150
178
151 function test_suspend() {
179 function test_suspend() {
@@ -292,8 +320,12 @@ Item {
292
320
293 waitUntilApplicationWindowIsFullyVisible();
321 waitUntilApplicationWindowIsFullyVisible();
294
322
323+ // Dragging launcher into view with a little bit of gap (units.gu(1)) should switch to Apps scope
324+ dragLauncherIntoView();
325+ verify(itemIsOnScreen(dashApps));
326+
295 // Minimize the application we just launched
327 // Minimize the application we just launched
296− swipeFromLeftEdge();
328+ swipeFromLeftEdge(units.gu(27));
297
329
298 // Wait for the whole UI to settle down
330 // Wait for the whole UI to settle down
299 waitUntilApplicationWindowIsFullyHidden();
331 waitUntilApplicationWindowIsFullyHidden();
@@ -376,10 +408,10 @@ Item {
376 }
408 }
377 }
409 }
378
410
379− function swipeFromLeftEdge() {
411+ function swipeFromLeftEdge(swipeLength) {
380 var touchStartX = 2;
412 var touchStartX = 2;
381 var touchStartY = shell.height / 2;
413 var touchStartY = shell.height / 2;
382− touchFlick(shell, touchStartX, touchStartY, shell.width * 0.75, touchStartY);
414+ touchFlick(shell, touchStartX, touchStartY, swipeLength, touchStartY);
383 }
415 }
384
416
385 function swipeLeftFromCenter() {
417 function swipeLeftFromCenter() {
@@ -432,7 +464,7 @@ Item {
432 } while (!isStill);
464 } while (!isStill);
433 }
465 }
434
466
435− function test_wallpaper_data() {
467+ function test_background_data() {
436 return [
468 return [
437 {tag: "red", url: "tests/data/unity/backgrounds/red.png", expectedUrl: "tests/data/unity/backgrounds/red.png"},
469 {tag: "red", url: "tests/data/unity/backgrounds/red.png", expectedUrl: "tests/data/unity/backgrounds/red.png"},
438 {tag: "blue", url: "tests/data/unity/backgrounds/blue.png", expectedUrl: "tests/data/unity/backgrounds/blue.png"},
470 {tag: "blue", url: "tests/data/unity/backgrounds/blue.png", expectedUrl: "tests/data/unity/backgrounds/blue.png"},
@@ -441,13 +473,21 @@ Item {
441 ]
473 ]
442 }
474 }
443
475
444− function test_wallpaper(data) {
476+ function test_background(data) {
445 var backgroundImage = findChild(shell, "backgroundImage")
477 var backgroundImage = findChild(shell, "backgroundImage")
446 GSettingsController.setPictureUri(data.url)
478 GSettingsController.setPictureUri(data.url)
447 tryCompareFunction(function() { return backgroundImage.source.toString().indexOf(data.expectedUrl) !== -1; }, true)
479 tryCompareFunction(function() { return backgroundImage.source.toString().indexOf(data.expectedUrl) !== -1; }, true)
448 tryCompare(backgroundImage, "status", Image.Ready)
480 tryCompare(backgroundImage, "status", Image.Ready)
449 }
481 }
450
482
483+ function test_lockscreen_background() {
484+ var backgroundImage = findChild(shell, "backgroundImage")
485+ var lockscreen = findChild(shell, "lockscreen")
486+ var lockscreenBackground = findChild(lockscreen, "lockscreenBackground")
487+ var lockscreenBackgroundMapped = lockscreenBackground.mapToItem(shell, 0, 0)
488+ compare(backgroundImage.y, lockscreenBackgroundMapped.y)
489+ }
490+
451 function test_DashShown_data() {
491 function test_DashShown_data() {
452 return [
492 return [
453 {tag: "in focus", greeter: false, app: false, launcher: false, indicators: false, expectedShown: true},
493 {tag: "in focus", greeter: false, app: false, launcher: false, indicators: false, expectedShown: true},
@@ -483,5 +523,28 @@ Item {
483 var dash = findChild(shell, "dash");
523 var dash = findChild(shell, "dash");
484 tryCompare(dash, "shown", data.expectedShown);
524 tryCompare(dash, "shown", data.expectedShown);
485 }
525 }
526+
527+ function test_searchIndicatorHidesOnAppFocus() {
528+ var searchIndicator = findChild(shell, "container")
529+ tryCompare(searchIndicator, "opacity", 1)
530+ dragLauncherIntoView();
531+
532+ // Launch an app from the launcher
533+ tapOnAppIconInLauncher();
534+ waitUntilApplicationWindowIsFullyVisible();
535+
536+ tryCompare(searchIndicator, "opacity", 0);
537+ }
538+
539+ function test_searchIndicatorHidesOnGreeterShown() {
540+ var searchIndicator = findChild(shell, "container")
541+ var greeter = findChild(shell, "greeter");
542+
543+ tryCompare(searchIndicator, "opacity", 1)
544+
545+ greeter.show()
546+ tryCompare(greeter, "shown", true)
547+ tryCompare(searchIndicator, "opacity", 0)
548+ }
486 }
549 }
487}
550}
tests/utils/modules/Unity/Test/UnityTestCase.qml+34
@@ -14,6 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17+import QtQuick 2.0
17import QtTest 1.0
18import QtTest 1.0
18import Ubuntu.Components 0.1
19import Ubuntu.Components 0.1
19import Unity.Test 0.1 as UT
20import Unity.Test 0.1 as UT
@@ -297,4 +298,37 @@ TestCase {
297 event.release(0 /* touchId */, x, y)
298 event.release(0 /* touchId */, x, y)
298 event.commit()
299 event.commit()
299 }
300 }
301+
302+ Component.onCompleted: {
303+ var rootItem = parent;
304+ while (rootItem.parent != undefined) {
305+ rootItem = rootItem.parent;
306+ }
307+ removeTimeConstraintsFromDirectionalDragAreas(rootItem);
308+ }
309+
310+ /*
311+ In qmltests, sequences of touch events are sent all at once, unlike in "real life".
312+ Also qmltests might run really slowly, e.g. when run from inside virtual machines.
313+ Thus to remove a variable that qmltests cannot really control, namely time, this
314+ function removes all constraints from DirectionalDragAreas that are sensible to
315+ elapsed time.
316+
317+ This effectively makes DirectionalDragAreas easier to fool.
318+ */
319+ function removeTimeConstraintsFromDirectionalDragAreas(item) {
320+
321+ // use duck-typing to identify a DirectionalDragArea
322+ if (item.minSpeed != undefined
323+ && item.maxSilenceTime != undefined
324+ && item.compositionTime != undefined) {
325+ item.minSpeed = 0;
326+ item.maxSilenceTime = 60 * 60 * 1000;
327+ item.compositionTime = 0;
328+ } else {
329+ for (var i in item.children) {
330+ removeTimeConstraintsFromDirectionalDragAreas(item.children[i]);
331+ }
332+ }
333+ }
300}
334}