on xenial help sign in
merged with trunk. bump
a1389c0Nick Dedekind
Bottombar/Bottombar.qml+4−4
@@ -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
19+import Utils 0.1
20−import 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+26−10
@@ -45,18 +45,22 @@ Item {
45 property int drawBuffer: width / pathItemCount // an "ok" value - but values used from the listView cause loops
45 property int drawBuffer: width / pathItemCount // an "ok" value - but values used from the listView cause loops
46 /// The selected item can be shown in a different size controlled by selectedItemScaleFactor
46 /// The selected item can be shown in a different size controlled by selectedItemScaleFactor
47 property real selectedItemScaleFactor: 1.1
47 property real selectedItemScaleFactor: 1.1
48+ /// The index of the item that should be highlighted
49+ property alias highlightIndex: listView.highlightIndex
50+ /// exposes the delegate of the currentItem
51+ readonly property alias currentItem: listView.currentItem
52+ /// exposes the distance to the next row (only one row in carousel, so it's the topMargins)
53+ readonly property alias verticalSpacing: listView.verticalMargin
48
54
49 /// Emitted when the user clicked on an item
55 /// Emitted when the user clicked on an item
50 /// @param index is the index of the clicked item
56 /// @param index is the index of the clicked item
51− /// @param delegateItem is the clicked component/delegate itself
52 /// @param itemY is y of the clicked delegate
57 /// @param itemY is y of the clicked delegate
53− signal clicked(int index, var delegateItem, real itemY)
58+ signal clicked(int index, real itemY)
54
59
55 /// Emitted when the user pressed and held on an item
60 /// Emitted when the user pressed and held on an item
56 /// @param index is the index of the held item
61 /// @param index is the index of the held item
57− /// @param delegateItem is the held component/delegate itself
58 /// @param itemY is y of the held delegate
62 /// @param itemY is y of the held delegate
59− signal pressAndHold(int index, var delegateItem, real itemY)
63+ signal pressAndHold(int index, real itemY)
60
64
61 implicitHeight: listView.tileHeight * selectedItemScaleFactor
65 implicitHeight: listView.tileHeight * selectedItemScaleFactor
62
66
@@ -75,6 +79,7 @@ Item {
75 property real newContentX: disabledNewContentX
79 property real newContentX: disabledNewContentX
76 property real pathItemCount: referenceWidth / referenceTileWidth
80 property real pathItemCount: referenceWidth / referenceTileWidth
77 property real tileAspectRatio: 1
81 property real tileAspectRatio: 1
82+ property int highlightIndex: -1
78
83
79 /* The positioning and scaling of the items in the carousel is based on the variable
84 /* The positioning and scaling of the items in the carousel is based on the variable
80 'continuousIndex', a continuous real variable between [0, 'carousel.model.count'],
85 'continuousIndex', a continuous real variable between [0, 'carousel.model.count'],
@@ -136,13 +141,14 @@ Item {
136 height: listView.tileHeight
141 height: listView.tileHeight
137 }
142 }
138
143
139− boundsBehavior: Flickable.StopAtBounds
144+ boundsBehavior: Flickable.DragOverBounds
140 cacheBuffer: carousel.cacheBuffer
145 cacheBuffer: carousel.cacheBuffer
141 flickDeceleration: Math.max(1500 * Math.pow(realWidth / referenceWidth, 1.5), 1500) // 1500 is platform default
146 flickDeceleration: Math.max(1500 * Math.pow(realWidth / referenceWidth, 1.5), 1500) // 1500 is platform default
142 maximumFlickVelocity: Math.max(2500 * Math.pow(realWidth / referenceWidth, 1.5), 2500) // 2500 is platform default
147 maximumFlickVelocity: Math.max(2500 * Math.pow(realWidth / referenceWidth, 1.5), 2500) // 2500 is platform default
143 orientation: ListView.Horizontal
148 orientation: ListView.Horizontal
144
149
145 function itemClicked(index, delegateItem) {
150 function itemClicked(index, delegateItem) {
151+ listView.currentIndex = index
146 var x = CarouselJS.getXFromContinuousIndex(index,
152 var x = CarouselJS.getXFromContinuousIndex(index,
147 realWidth,
153 realWidth,
148 realContentWidth,
154 realContentWidth,
@@ -151,11 +157,11 @@ Item {
151 gapToEndPhase,
157 gapToEndPhase,
152 carousel.drawBuffer)
158 carousel.drawBuffer)
153
159
154− if (Math.abs(x - contentX) < 1) {
160+ if (Math.abs(x - contentX) < 1 && delegateItem !== undefined) {
155 /* We're clicking the selected item and
161 /* We're clicking the selected item and
156 we're in the neighbourhood of radius 1 pixel from it.
162 we're in the neighbourhood of radius 1 pixel from it.
157 Let's emit the clicked signal. */
163 Let's emit the clicked signal. */
158− carousel.clicked(index, delegateItem, delegateItem.y)
164+ carousel.clicked(index, delegateItem.y)
159 return
165 return
160 }
166 }
161
167
@@ -175,11 +181,11 @@ Item {
175 gapToEndPhase,
181 gapToEndPhase,
176 carousel.drawBuffer);
182 carousel.drawBuffer);
177
183
178− if (Math.abs(x - contentX) < 1) {
184+ if (Math.abs(x - contentX) < 1 && delegateItem !== undefined) {
179 /* We're pressAndHold the selected item and
185 /* We're pressAndHold the selected item and
180 we're in the neighbourhood of radius 1 pixel from it.
186 we're in the neighbourhood of radius 1 pixel from it.
181 Let's emit the pressAndHold signal. */
187 Let's emit the pressAndHold signal. */
182− carousel.pressAndHold(index, delegateItem, delegateItem.y);
188+ carousel.pressAndHold(index, delegateItem.y);
183 return;
189 return;
184 }
190 }
185
191
@@ -190,6 +196,12 @@ Item {
190 newContentXAnimation.start();
196 newContentXAnimation.start();
191 }
197 }
192
198
199+ onHighlightIndexChanged: {
200+ if (highlightIndex != -1) {
201+ itemClicked(highlightIndex)
202+ }
203+ }
204+
193 onMovementStarted: {
205 onMovementStarted: {
194 stepAnimation.stop()
206 stepAnimation.stop()
195 newContentXAnimation.stop()
207 newContentXAnimation.stop()
@@ -273,14 +285,18 @@ Item {
273 itemTranslationScale,
285 itemTranslationScale,
274 listView.maximumItemTranslation)
286 listView.maximumItemTranslation)
275
287
288+ readonly property real xTransform: listView.viewTranslation + translationX * listView.scaleFactor
289+ readonly property real center: x - listView.contentX + xTransform - drawBuffer + (width/2)
290+
276 width: listView.tileWidth
291 width: listView.tileWidth
277 height: listView.tileHeight
292 height: listView.tileHeight
278 scale: itemScale * explicitScaleFactor
293 scale: itemScale * explicitScaleFactor
279 sourceComponent: itemComponent
294 sourceComponent: itemComponent
280 z: cachedTiles - Math.abs(index - listView.selectedIndex)
295 z: cachedTiles - Math.abs(index - listView.selectedIndex)
296+ opacity: highlightIndex == -1 ? 1 : (highlightIndex == index ? 0.6 : 0.2)
281
297
282 transform: Translate {
298 transform: Translate {
283− x: listView.viewTranslation + translationX * listView.scaleFactor
299+ x: xTransform
284 }
300 }
285
301
286 Behavior on explicitScaleFactor {
302 Behavior on explicitScaleFactor {
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/FilterGrid.qml+3
@@ -54,6 +54,7 @@ Item {
54 property alias delegateWidth: iconTileGrid.delegateWidth
54 property alias delegateWidth: iconTileGrid.delegateWidth
55 property alias delegateHeight: iconTileGrid.delegateHeight
55 property alias delegateHeight: iconTileGrid.delegateHeight
56 property alias verticalSpacing: iconTileGrid.verticalSpacing
56 property alias verticalSpacing: iconTileGrid.verticalSpacing
57+ readonly property alias margins: iconTileGrid.margins
57 property alias delegate: iconTileGrid.delegate
58 property alias delegate: iconTileGrid.delegate
58 property alias cellWidth: iconTileGrid.cellWidth
59 property alias cellWidth: iconTileGrid.cellWidth
59 property alias cellHeight: iconTileGrid.cellHeight
60 property alias cellHeight: iconTileGrid.cellHeight
@@ -62,6 +63,8 @@ Item {
62 readonly property alias flicking: iconTileGrid.flicking
63 readonly property alias flicking: iconTileGrid.flicking
63 readonly property alias moving: iconTileGrid.moving
64 readonly property alias moving: iconTileGrid.moving
64 readonly property alias pressDelay: iconTileGrid.pressDelay
65 readonly property alias pressDelay: iconTileGrid.pressDelay
66+ property alias highlightIndex: iconTileGrid.highlightIndex
67+ readonly property alias currentItem: iconTileGrid.currentItem
65
68
66 height: !filterAnimation.running ? childrenRect.height : height
69 height: !filterAnimation.running ? childrenRect.height : height
67 clip: filterAnimation.running
70 clip: filterAnimation.running
Components/LazyImage.qml+2−2
@@ -100,10 +100,10 @@ Item {
100 verticalAlignment: Image.AlignVCenter
100 verticalAlignment: Image.AlignVCenter
101 sourceSize.width: root.scaleTo == "width" ? root.width
101 sourceSize.width: root.scaleTo == "width" ? root.width
102 : root.scaleTo == "fit" && root.width < root.height ? root.width
102 : root.scaleTo == "fit" && root.width < root.height ? root.width
103− : undefined
103+ : 0
104 sourceSize.height: root.scaleTo == "height" ? root.height
104 sourceSize.height: root.scaleTo == "height" ? root.height
105 : root.scale == "fit" && root.height < root.width ? root.height
105 : root.scale == "fit" && root.height < root.width ? root.height
106− : undefined
106+ : 0
107 }
107 }
108 }
108 }
109
109
Components/PageHeader.qml+28−5
@@ -44,7 +44,11 @@ Item {
44 if (!searchHistory) return;
44 if (!searchHistory) return;
45
45
46 searchHistory.addQuery(searchField.text);
46 searchHistory.addQuery(searchField.text);
47+ unfocus();
47 searchField.text = "";
48 searchField.text = "";
49+ }
50+
51+ function unfocus() {
48 searchField.focus = false;
52 searchField.focus = false;
49 }
53 }
50
54
@@ -108,6 +112,8 @@ Item {
108 objectName: "searchContainer"
112 objectName: "searchContainer"
109
113
110 visible: searchEntryEnabled
114 visible: searchEntryEnabled
115+ property bool popoverShouldOpen: false
116+ property bool popoverShouldClose: false
111
117
112 property bool narrowMode: parent.width < label.contentWidth + units.gu(50)
118 property bool narrowMode: parent.width < label.contentWidth + units.gu(50)
113
119
@@ -123,6 +129,16 @@ Item {
123 else if (active && !narrowMode) "active"
129 else if (active && !narrowMode) "active"
124 else if (!active && !narrowMode) "inactive"
130 else if (!active && !narrowMode) "inactive"
125
131
132+ onStateChanged: {
133+ if (state == "active" || state == "narrowActive") {
134+ popoverShouldOpen = true;
135+ popoverShouldClose = false;
136+ } else {
137+ popoverShouldOpen = false;
138+ popoverShouldClose = true;
139+ }
140+ }
141+
126 function openPopover() {
142 function openPopover() {
127 if (searchHistory.count > 0) {
143 if (searchHistory.count > 0) {
128 searchContainer.popover = PopupUtils.open(popoverComponent, searchField,
144 searchContainer.popover = PopupUtils.open(popoverComponent, searchField,
@@ -133,10 +149,17 @@ Item {
133 }
149 }
134 )
150 )
135 }
151 }
152+ popoverShouldOpen = false;
153+ popoverShouldClose = false;
136 }
154 }
137
155
138 function closePopover() {
156 function closePopover() {
157+ if (searchContainer.popover) {
139− if (searchContainer.popover) PopupUtils.close(searchContainer.popover)
158+ PopupUtils.close(searchContainer.popover);
159+ searchContainer.popover = null;
160+ }
161+ popoverShouldOpen = false;
162+ popoverShouldClose = false;
140 }
163 }
141
164
142 onActiveFocusChanged: if (!activeFocus) { searchHistory.addQuery(searchField.text) }
165 onActiveFocusChanged: if (!activeFocus) { searchHistory.addQuery(searchField.text) }
@@ -279,12 +302,12 @@ Item {
279 PropertyAction { target: primaryImage; property: "source" }
302 PropertyAction { target: primaryImage; property: "source" }
280 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
303 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
281 }
304 }
282− ScriptAction { script: searchContainer.openPopover() }
305+ ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
283 }
306 }
284 },
307 },
285 Transition {
308 Transition {
286 to: "inactive"
309 to: "inactive"
287− ScriptAction { script: searchContainer.closePopover() }
310+ ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
288 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
311 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
289 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
312 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
290 },
313 },
@@ -295,12 +318,12 @@ Item {
295 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
318 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
296 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
319 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
297 }
320 }
298− ScriptAction { script: searchContainer.openPopover() }
321+ ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
299 }
322 }
300 },
323 },
301 Transition {
324 Transition {
302 to: "narrowInactive"
325 to: "narrowInactive"
303− ScriptAction { script: searchContainer.closePopover() }
326+ ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
304 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
327 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
305 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
328 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
306 }
329 }
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/ResponsiveGridView.qml+10
@@ -26,6 +26,7 @@ Item {
26 property int maximumNumberOfColumns: 6
26 property int maximumNumberOfColumns: 6
27 readonly property int columns: gridView.columns
27 readonly property int columns: gridView.columns
28 property alias verticalSpacing: gridView.verticalSpacing
28 property alias verticalSpacing: gridView.verticalSpacing
29+ readonly property alias margins: gridView.margin
29 property int delegateWidth
30 property int delegateWidth
30 property int delegateHeight
31 property int delegateHeight
31 property alias model: gridView.model
32 property alias model: gridView.model
@@ -41,6 +42,8 @@ Item {
41 readonly property alias pressDelay: gridView.pressDelay
42 readonly property alias pressDelay: gridView.pressDelay
42 property alias delegateCreationBegin: gridView.delegateCreationBegin
43 property alias delegateCreationBegin: gridView.delegateCreationBegin
43 property alias delegateCreationEnd: gridView.delegateCreationEnd
44 property alias delegateCreationEnd: gridView.delegateCreationEnd
45+ property alias highlightIndex: gridView.highlightIndex
46+ readonly property alias currentItem: gridView.currentItem
44
47
45 function contentHeightForRows(rows) {
48 function contentHeightForRows(rows) {
46 return rows * cellHeight + verticalSpacing
49 return rows * cellHeight + verticalSpacing
@@ -77,8 +80,15 @@ Item {
77 property real horizontalSpacing: spacingForColumns(columns)
80 property real horizontalSpacing: spacingForColumns(columns)
78 property real verticalSpacing: horizontalSpacing
81 property real verticalSpacing: horizontalSpacing
79 property int margin: allocatableHorizontalSpace - columns * horizontalSpacing
82 property int margin: allocatableHorizontalSpace - columns * horizontalSpacing
83+ property int highlightIndex: -1
80
84
81 cellWidth: delegateWidth + horizontalSpacing
85 cellWidth: delegateWidth + horizontalSpacing
82 cellHeight: delegateHeight + verticalSpacing
86 cellHeight: delegateHeight + verticalSpacing
87+
88+ onHighlightIndexChanged: {
89+ if (highlightIndex != -1) {
90+ currentIndex = highlightIndex
91+ }
92+ }
83 }
93 }
84}
94}
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/Tile.qml+9
@@ -26,5 +26,14 @@ AbstractButton {
26 property int imageHeight
26 property int imageHeight
27 property int maximumLineCount: 1
27 property int maximumLineCount: 1
28
28
29+ readonly property int center: (index % GridView.view.columns * width) + (width / 2)
30+
31+ opacity: GridView.view.highlightIndex === -1 ? 1 :
32+ GridView.view.highlightIndex === index ? 0.6 : 0.2
33+
34+ Behavior on opacity {
35+ UbuntuNumberAnimation {}
36+ }
37+
29 style: TileStyle {}
38 style: TileStyle {}
30}
39}
Components/Time.jsdeleted−49
@@ -1,49 +0,0 @@
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−.pragma library
18−
19−var factors = {
20− "second": [ 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" ],
22− "hour": [ 60, "an hour ago", "in an hour", "%1 hours ago", "in %1 hours" ],
23− "day": [ 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" ],
25− "month": [ 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" ]
27−}
28−
29−function readableFromNow(date, now) {
30− var then = new Date(date);
31− if (isNaN(then)) return "";
32− if (now === undefined) {
33− now = new Date();
34− } else if (isNaN(now)) throw "now is NaN";
35− var diff = Math.abs(now - then);
36− if (diff < 1000) return "just now";
37−
38− var future = now < then;
39− var humanDiff;
40− for (var k in factors) {
41− diff /= factors[k][0];
42− if (Math.floor(diff) == 1) {
43− humanDiff = factors[k][future ? 2 : 1];
44− } else if (Math.floor(diff) > 1) {
45− humanDiff = factors[k][future ? 4 : 3].arg(Math.round(diff));
46− } else break;
47− }
48− return humanDiff;
49−}
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/AppInfo.qmldeleted−89
@@ -1,89 +0,0 @@
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−import "../../Components"
20−
21−Row {
22− id: root
23− property alias icon: image.source
24− property alias appName: appNameLabel.text
25− property alias rating: ratingStars.rating
26− property int rated: 0
27− property int reviews: 0
28−
29− spacing: units.gu(2)
30−
31− UbuntuShape {
32− id: imageShape
33− width: units.gu(6)
34− height: units.gu(6)
35− image: Image {
36− id: image
37− sourceSize { width: imageShape.width; height: imageShape.height }
38− asynchronous: true
39− fillMode: Image.PreserveAspectFit
40− }
41− }
42−
43− Column {
44− spacing: units.gu(1)
45−
46− Label {
47− id: appNameLabel
48− fontSize: "large"
49− color: "white"
50− style: Text.Raised
51− styleColor: "black"
52− opacity: .9
53− }
54−
55− Row {
56− visible: root.rating >= 0
57− spacing: units.gu(1)
58−
59− RatingStars {
60− id: ratingStars
61− maximumRating: 10
62− }
63−
64− Label {
65− id: ratedLabel
66− objectName: "ratedLabel"
67− fontSize: "medium"
68− color: "white"
69− style: Text.Raised
70− styleColor: "black"
71− opacity: .6
72− //TRANSLATORS: Number of persons who rated this app
73− text: i18n.tr("(%1)").arg(root.rated)
74− }
75−
76− Label {
77− id: reviewsLabel
78− objectName: "reviewsLabel"
79− fontSize: "medium"
80− color: "white"
81− style: Text.Raised
82− styleColor: "black"
83− opacity: .6
84− //TRANSLATORS: Number of persons who wrote reviews for this app
85− text: i18n.tr("%1 review", "%1 reviews", root.reviews).arg(root.reviews)
86− }
87− }
88− }
89−}
Dash/Apps/AppPreview.qml+9
@@ -44,6 +44,15 @@ GenericPreview {
44 model: previewData.infoMap["more-screenshots"] != null ? previewData.infoMap["more-screenshots"].value : [previewData.image]
44 model: previewData.infoMap["more-screenshots"] != null ? previewData.infoMap["more-screenshots"].value : [previewData.image]
45 cacheBuffer: width * 3
45 cacheBuffer: width * 3
46
46
47+ // FIXME: Because of ListViews inside ListViews inside Flickables inside ListViews (and some more)
48+ // we finally reached the point where this ListView doesn't correctly get swipe input any more but
49+ // instead the parent ListView is the one that is swiped. This MouseArea sort of creates a blocking
50+ // layer to make sure this ListView can be swiped, regardless of what's behind it.
51+ MouseArea {
52+ anchors.fill: parent
53+ enabled: parent.contentWidth > parent.width
54+ }
55+
47 LazyImage {
56 LazyImage {
48 objectName: "placeholderScreenshot"
57 objectName: "placeholderScreenshot"
49 anchors {
58 anchors {
Dash/Apps/ApplicationsFilterGrid.qmldeleted−55
@@ -1,55 +0,0 @@
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 "../../Components"
19−import "../../Applications"
20−
21−FilterGrid {
22− id: filterGrid
23−
24− filter: false
25− minimumHorizontalSpacing: units.gu(0.5)
26− maximumNumberOfColumns: 6
27− delegateWidth: units.gu(11)
28− delegateHeight: units.gu(9.5)
29− verticalSpacing: units.gu(2)
30−
31− signal clicked(int index, variant data)
32−
33− delegate: Tile {
34− objectName: "delegate" + index
35− Application {
36− id: application
37− desktopFile: model.dndUri ? stripProtocol(model.dndUri) : model.desktopFile // FIXME: this is temporary
38−
39− function stripProtocol(uri) {
40− var chunks = uri.split('file://')
41− return chunks[chunks.length-1]
42− }
43− }
44−
45− property string icon: model.icon ? model.icon : "../../graphics/applicationIcons/" + application.icon + ".png" // FIXME: this is temporary
46−
47− width: filterGrid.cellWidth
48− height: filterGrid.cellHeight
49− text: model.title ? model.title : application.name // FIXME: this is temporary
50− imageWidth: units.gu(8)
51− imageHeight: units.gu(7.5)
52− source: icon
53− onClicked: filterGrid.clicked(index, application.desktopFile);
54− }
55−}
Dash/Apps/DashPluginFilterGrid.qml+2−4
@@ -37,13 +37,11 @@ GenericFilterGrid {
37 }
37 }
38
38
39 onClicked: {
39 onClicked: {
40− var data = { model: model }
41− filtergrid.clicked(index, data, tile.y)
40+ filtergrid.clicked(index, tile.y)
42 }
41 }
43
42
44 onPressAndHold: {
43 onPressAndHold: {
45− var data = { model: model }
46− filtergrid.pressAndHold(index, data, tile.y)
44+ filtergrid.pressAndHold(index, tile.y)
47 }
45 }
48 }
46 }
49}
47}
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/DashBar.qml+2−2
@@ -35,7 +35,7 @@ Item {
35
35
36 function startNavigation() {
36 function startNavigation() {
37 timeout.stop()
37 timeout.stop()
38− panel.opened = true
38+ panel.open()
39 }
39 }
40
40
41 function stopNavigation() {
41 function stopNavigation() {
@@ -43,7 +43,7 @@ Item {
43 }
43 }
44
44
45 function finishNavigation() {
45 function finishNavigation() {
46− panel.opened = false
46+ panel.close()
47 }
47 }
48
48
49 Timer {
49 Timer {
Dash/DashContent.qml+2−2
@@ -116,8 +116,8 @@ Item {
116 source: scopeMapper.map(scope.id)
116 source: scopeMapper.map(scope.id)
117 objectName: scope.id + " loader"
117 objectName: scope.id + " loader"
118
118
119− readonly property bool previewShown: item.previewShown
119+ readonly property bool previewShown: item ? item.previewShown : false
120− readonly property bool moving: item.moving
120+ readonly property bool moving: item ? item.moving : false
121
121
122 // these are needed for autopilot tests
122 // these are needed for autopilot tests
123 readonly property string scopeId: scope.id
123 readonly property string scopeId: scope.id
Dash/DashPreview.qml+1−3
@@ -17,7 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19
19
20−Rectangle {
20+Item {
21 id: root
21 id: root
22
22
23 property int keyboardSize: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
23 property int keyboardSize: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
@@ -36,7 +36,6 @@ Rectangle {
36 readonly property int columnWidth: narrowMode ? contentRow.width : (contentRow.width / 3) - contentRow.spacing
36 readonly property int columnWidth: narrowMode ? contentRow.width : (contentRow.width / 3) - contentRow.spacing
37 readonly property int contentSpacing: units.gu(3)
37 readonly property int contentSpacing: units.gu(3)
38
38
39− color: Qt.rgba(0, 0, 0, .3)
40 clip: true
39 clip: true
41
40
42 function ensureVisible(item) {
41 function ensureVisible(item) {
@@ -61,7 +60,6 @@ Rectangle {
61 anchors.fill: parent
60 anchors.fill: parent
62 }
61 }
63
62
64−
65 Row {
63 Row {
66 id: contentRow
64 id: contentRow
67 anchors {
65 anchors {
tests/mocks/QMenuModel/UnityMenuModel.qml → Dash/DashPreviewPlaceholder.qmlrenamed+6−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,11 @@
18 */
15 */
19
16
20import QtQuick 2.0
17import QtQuick 2.0
18+import Ubuntu.Components 0.1
21
19
22−QtObject {
20+DashPreview {
23− property variant busName
21+ ActivityIndicator {
24− property variant actions
22+ anchors.centerIn: parent
25− property variant menuObjectPath
23+ running: true
24+ }
26}
25}
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/Generic/GenericFilterGrid.qml+4−6
@@ -28,8 +28,8 @@ FilterGrid {
28 property int iconWidth: units.gu(8)
28 property int iconWidth: units.gu(8)
29 property int iconHeight: units.gu(7.5)
29 property int iconHeight: units.gu(7.5)
30
30
31− signal clicked(int index, var delegateItem, real itemY)
31+ signal clicked(int index, real itemY)
32− signal pressAndHold(int index, var delegateItem, real itemY)
32+ signal pressAndHold(int index, real itemY)
33
33
34 delegate: Tile {
34 delegate: Tile {
35 id: tile
35 id: tile
@@ -42,13 +42,11 @@ FilterGrid {
42 source: model.icon
42 source: model.icon
43
43
44 onClicked: {
44 onClicked: {
45− var data = { model: model }
46− filtergrid.clicked(index, data, tile.y)
45+ filtergrid.clicked(index, tile.y)
47 }
46 }
48
47
49 onPressAndHold: {
48 onPressAndHold: {
50− var data = { model: model }
51− filtergrid.pressAndHold(index, data, tile.y)
49+ filtergrid.pressAndHold(index, tile.y)
52 }
50 }
53 }
51 }
54}
52}
Dash/Generic/WeatherFilterGrid.qml+2−4
@@ -37,13 +37,11 @@ GenericFilterGrid {
37 style: FlatTileStyle {}
37 style: FlatTileStyle {}
38
38
39 onClicked: {
39 onClicked: {
40− var data = { model: model }
41− filtergrid.clicked(index, data, tile.y)
40+ filtergrid.clicked(index, tile.y)
42 }
41 }
43
42
44 onPressAndHold: {
43 onPressAndHold: {
45− var data = { model: model }
46− filtergrid.pressAndHold(index, data, tile.y)
44+ filtergrid.pressAndHold(index, tile.y)
47 }
45 }
48 }
46 }
49}
47}
Dash/GenericScopeView.qml+285−71
@@ -16,19 +16,64 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import Utils 0.1
20+import Unity 0.1
19import "../Components"
21import "../Components"
20import "../Components/ListItems" as ListItems
22import "../Components/ListItems" as ListItems
21
23
22−ScopeView {
24+FocusScope {
23 id: scopeView
25 id: scopeView
26+
27+ property Scope scope
28+ property SortFilterProxyModel categories: categoryFilter
29+ property bool isCurrent
30+ property ListModel searchHistory
31+ property alias moving: categoryView.moving
32+
33+ signal endReached
34+ signal movementStarted
35+ signal positionedAtBeginning
36+
24− readonly property alias previewShown: previewLoader.onScreen
37+ readonly property alias previewShown: previewListView.onScreen
25 property bool enableHeightBehaviorOnNextCreation: false
38 property bool enableHeightBehaviorOnNextCreation: false
26
39
27− moving: categoryView.moving
40+ // FIXME delay the search so that daemons have time to settle, note that
41+ // removing this will break ScopeView::test_changeScope
42+ onScopeChanged: {
43+ if (scope) {
44+ timer.restart();
45+ scope.activateApplication.connect(activateApp);
46+ }
47+ }
48+
49+ function activateApp(desktopFilePath) {
50+ shell.activateApplication(desktopFilePath);
51+ }
52+
53+ Binding {
54+ target: scope
55+ property: "isActive"
56+ value: isCurrent
57+ }
58+
59+ Timer {
60+ id: timer
61+ interval: 2000
62+ onTriggered: scope.searchQuery = ""
63+ }
64+
65+ SortFilterProxyModel {
66+ id: categoryFilter
67+ model: scope ? scope.categories : null
68+ dynamicSortFilter: true
69+ filterRole: Categories.RoleCount
70+ filterRegExp: /^0$/
71+ invertMatch: true
72+ }
28
73
29 onIsCurrentChanged: {
74 onIsCurrentChanged: {
30 pageHeader.resetSearch();
75 pageHeader.resetSearch();
31− previewLoader.open = false;
76+ previewListView.open = false;
32 }
77 }
33
78
34 onMovementStarted: categoryView.showHeader()
79 onMovementStarted: categoryView.showHeader()
@@ -57,9 +102,8 @@ ScopeView {
57
102
58 Connections {
103 Connections {
59 target: scopeView.scope
104 target: scopeView.scope
60− onShowDash: previewLoader.open = false;
105+ onShowDash: previewListView.open = false;
61− onHideDash: previewLoader.open = false;
106+ onHideDash: previewListView.open = false;
62− onActivated: previewLoader.closePreviewSpinner();
63 }
107 }
64
108
65 ScopeListView {
109 ScopeListView {
@@ -67,12 +111,18 @@ ScopeView {
67 objectName: "categoryListView"
111 objectName: "categoryListView"
68 anchors.fill: parent
112 anchors.fill: parent
69 model: scopeView.categories
113 model: scopeView.categories
70− forceNoClip: previewLoader.onScreen
114+ forceNoClip: previewListView.onScreen
71
115
72 onAtYEndChanged: if (atYEnd) endReached()
116 onAtYEndChanged: if (atYEnd) endReached()
73 onMovingChanged: if (moving && atYEnd) endReached()
117 onMovingChanged: if (moving && atYEnd) endReached()
74
118
75 property string expandedCategoryId: ""
119 property string expandedCategoryId: ""
120+ signal correctExpandedCategory();
121+
122+ Behavior on contentY {
123+ enabled: previewListView.open
124+ UbuntuNumberAnimation {}
125+ }
76
126
77 delegate: ListItems.Base {
127 delegate: ListItems.Base {
78 id: baseItem
128 id: baseItem
@@ -124,33 +174,50 @@ ScopeView {
124 Connections {
174 Connections {
125 target: rendererLoader.item
175 target: rendererLoader.item
126 onClicked: {
176 onClicked: {
177+ // Prepare the preview in case activate() triggers a preview only
127− effect.positionPx = mapToItem(categoryView, 0, itemY).y
178+ effect.positionPx = Math.max(mapToItem(categoryView, 0, itemY).y, pageHeader.height + categoryView.stickyHeaderHeight);
128− scopeView.scope.activate(delegateItem.model.uri,
179+ previewListView.categoryId = categoryId
129− delegateItem.model.icon,
180+ previewListView.categoryDelegate = rendererLoader.item
130− delegateItem.model.category,
181+ previewListView.model = target.model;
131− 0,
182+ previewListView.init = true;
132− delegateItem.model.mimetype,
183+ previewListView.currentIndex = index;
133− delegateItem.model.title,
184+
134− delegateItem.model.comment,
185+ var item = target.model.get(index);
135− delegateItem.model.dndUri,
186+
136− delegateItem.model.metadata)
187+ if ((scopeView.scope.id == "applications.scope" && categoryId == "installed")
188+ || (scopeView.scope.id == "home.scope" && categoryId == "applications.scope")) {
189+ scopeView.scope.activate(item.uri, item.icon, item.category, 0, item.mimetype, item.title,
190+ item.comment, item.dndUri, item.metadata)
191+ } else {
192+ previewListView.open = true
193+
194+ scopeView.scope.preview( item.uri, item.icon, item.category, 0, item.mimetype, item.title,
195+ item.comment, item.dndUri, item.metadata)
196+ }
137 }
197 }
138 onPressAndHold: {
198 onPressAndHold: {
139− effect.positionPx = mapToItem(categoryView, 0, itemY).y
199+ effect.positionPx = Math.max(mapToItem(categoryView, 0, itemY).y, pageHeader.height + categoryView.stickyHeaderHeight);
200+ previewListView.categoryId = categoryId
201+ previewListView.categoryDelegate = rendererLoader.item
202+ previewListView.model = target.model;
203+ previewListView.init = true;
204+ previewListView.currentIndex = index;
205+ previewListView.open = true
206+
207+ var item = target.model.get(index)
140− scopeView.scope.preview( delegateItem.model.uri,
208+ scopeView.scope.preview( item.uri, item.icon, item.category, 0, item.mimetype, item.title,
141− delegateItem.model.icon,
209+ item.comment, item.dndUri, item.metadata)
142− delegateItem.model.category,
143− 0,
144− delegateItem.model.mimetype,
145− delegateItem.model.title,
146− delegateItem.model.comment,
147− delegateItem.model.dndUri,
148− delegateItem.model.metadata)
149 }
210 }
150 }
211 }
151 Connections {
212 Connections {
152 target: categoryView
213 target: categoryView
153 onExpandedCategoryIdChanged: {
214 onExpandedCategoryIdChanged: {
215+ collapseAllButExpandedCategory();
216+ }
217+ onCorrectExpandedCategory: {
218+ collapseAllButExpandedCategory();
219+ }
220+ function collapseAllButExpandedCategory() {
154 var item = rendererLoader.item;
221 var item = rendererLoader.item;
155 if (item.expandable) {
222 if (item.expandable) {
156 var shouldFilter = categoryId != categoryView.expandedCategoryId;
223 var shouldFilter = categoryId != categoryView.expandedCategoryId;
@@ -158,13 +225,15 @@ ScopeView {
158 // If the filter animation will be seen start it, otherwise, just flip the switch
225 // If the filter animation will be seen start it, otherwise, just flip the switch
159 var shrinkingVisible = shouldFilter && y + item.collapsedHeight < categoryView.height;
226 var shrinkingVisible = shouldFilter && y + item.collapsedHeight < categoryView.height;
160 var growingVisible = !shouldFilter && y + height < categoryView.height;
227 var growingVisible = !shouldFilter && y + height < categoryView.height;
228+ if (!previewListView.open || !shouldFilter) {
161− if (shrinkingVisible || growingVisible) {
229+ if (shrinkingVisible || growingVisible) {
162− item.startFilterAnimation(shouldFilter)
230+ item.startFilterAnimation(shouldFilter)
163− } else {
231+ } else {
164− item.filter = shouldFilter;
232+ item.filter = shouldFilter;
165− }
233+ }
166− if (!shouldFilter) {
234+ if (!shouldFilter && !previewListView.open) {
167− categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
235+ categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
236+ }
168 }
237 }
169 }
238 }
170 }
239 }
@@ -238,26 +307,27 @@ ScopeView {
238 rendererId = getDefaultRendererId(contentType);
307 rendererId = getDefaultRendererId(contentType);
239 }
308 }
240 switch (rendererId) {
309 switch (rendererId) {
310+ case "carousel": {
311+ switch (contentType) {
312+ case "music": return "Music/MusicCarouselLoader.qml";
313+ case "video": return "Video/VideoCarouselLoader.qml";
314+ default: return "Generic/GenericCarouselLoader.qml";
315+ }
316+ }
241 case "grid": {
317 case "grid": {
242 switch (contentType) {
318 switch (contentType) {
243− case "video": return "Video/VideoFilterGrid.qml";
244− case "music": return "Music/MusicFilterGrid.qml";
245 case "apps": {
319 case "apps": {
246 if (rendererHint == "toggled")
320 if (rendererHint == "toggled")
247 return "Apps/DashPluginFilterGrid.qml";
321 return "Apps/DashPluginFilterGrid.qml";
248 else
322 else
249 return "Generic/GenericFilterGrid.qml";
323 return "Generic/GenericFilterGrid.qml";
250 }
324 }
325+ case "music": return "Music/MusicFilterGrid.qml";
326+ case "video": return "Video/VideoFilterGrid.qml";
251 case "weather": return "Generic/WeatherFilterGrid.qml";
327 case "weather": return "Generic/WeatherFilterGrid.qml";
252 default: return "Generic/GenericFilterGrid.qml";
328 default: return "Generic/GenericFilterGrid.qml";
253 }
329 }
254 }
330 }
255− case "carousel": {
256− switch (contentType) {
257− case "music": return "Music/MusicCarousel.qml";
258− default: return "Generic/GenericCarousel.qml";
259− }
260− }
261 case "special": {
331 case "special": {
262 switch (contentType) {
332 switch (contentType) {
263 case "apps": return "Apps/RunningApplicationsGrid.qml";
333 case "apps": return "Apps/RunningApplicationsGrid.qml";
@@ -270,6 +340,7 @@ ScopeView {
270
340
271 OpenEffect {
341 OpenEffect {
272 id: effect
342 id: effect
343+ objectName: "openEffect"
273 anchors {
344 anchors {
274 fill: parent
345 fill: parent
275 bottomMargin: -bottomOverflow
346 bottomMargin: -bottomOverflow
@@ -282,29 +353,44 @@ ScopeView {
282 topOpacity: (1 - gap * 1.2)
353 topOpacity: (1 - gap * 1.2)
283 bottomGapPx: positionPx + gap * (targetBottomGapPx - positionPx)
354 bottomGapPx: positionPx + gap * (targetBottomGapPx - positionPx)
284 bottomOverflow: units.gu(20)
355 bottomOverflow: units.gu(20)
285− bottomOpacity: 1 - (gap * 0.8)
356+ live: !expansionAnimation.running
286
357
287 property int targetBottomGapPx: height - units.gu(8) - bottomOverflow
358 property int targetBottomGapPx: height - units.gu(8) - bottomOverflow
288− property real gap: previewLoader.open ? 1.0 : 0.0
359+ property real gap: previewListView.open ? 1.0 : 0.0
289
360
290 Behavior on gap {
361 Behavior on gap {
291 NumberAnimation {
362 NumberAnimation {
363+ id: expansionAnimation
292 duration: 200
364 duration: 200
293 easing.type: Easing.InOutQuad
365 easing.type: Easing.InOutQuad
294 onRunningChanged: {
366 onRunningChanged: {
295− if (!previewLoader.open && !running) {
367+ if (!previewListView.open && !running) {
296− previewLoader.onScreen = false
368+ previewListView.onScreen = false
297 }
369 }
298 }
370 }
299 }
371 }
300 }
372 }
373+ Behavior on positionPx {
374+ enabled: previewListView.open
375+ UbuntuNumberAnimation {}
376+ }
301 }
377 }
302
378
303 Connections {
379 Connections {
304 target: scopeView.scope
380 target: scopeView.scope
305 onPreviewReady: {
381 onPreviewReady: {
382+ if (previewListView.init) {
383+ // Preview was triggered because of a click on the item. Need to expand now.
384+ if (!previewListView.open) {
385+ previewListView.open = true
386+ }
387+
388+ var index = previewListView.currentIndex
389+ previewListView.currentIndex = -1
390+ previewListView.currentIndex = index
391+ previewListView.init = false
392+ }
306− previewLoader.previewData = preview
393+ previewListView.currentItem.previewData = preview
307− previewLoader.open = true
308 }
394 }
309 }
395 }
310
396
@@ -312,18 +398,9 @@ ScopeView {
312 id: previewDelegateMapper
398 id: previewDelegateMapper
313 }
399 }
314
400
315− Connections {
401+ ListView {
316− ignoreUnknownSignals: true
402+ id: previewListView
317− target: previewLoader.valid ? previewLoader.item : null
403+ objectName: "previewListView"
318− onClose: {
319− previewLoader.open = false
320− }
321− }
322−
323− Loader {
324− objectName: "previewLoader"
325− id: previewLoader
326− property var previewData
327 height: effect.bottomGapPx - effect.topGapPx
404 height: effect.bottomGapPx - effect.topGapPx
328 anchors {
405 anchors {
329 top: parent.top
406 top: parent.top
@@ -331,38 +408,175 @@ ScopeView {
331 left: parent.left
408 left: parent.left
332 right: parent.right
409 right: parent.right
333 }
410 }
334− source: onScreen ? previewDelegateMapper.map(previewLoader.previewData.rendererName) : ""
411+ orientation: ListView.Horizontal
412+ highlightRangeMode: ListView.StrictlyEnforceRange
413+ snapMode: ListView.SnapOneItem
414+ boundsBehavior: Flickable.DragAndOvershootBounds
415+ highlightMoveDuration: 250
416+ flickDeceleration: units.gu(625)
417+ maximumFlickVelocity: width * 5
418+ cacheBuffer: 0
419+
420+ // To be set before opening the preview
421+ property string categoryId: ""
422+ property var categoryDelegate
423+
424+ // because the ListView is built asynchronous, setting the
425+ // currentIndex directly won't work. We need to refresh it
426+ // when the first preview is ready to be displayed.
427+ property bool init: true
428+
429+ onCurrentIndexChanged: {
430+ var row = Math.floor(currentIndex / categoryDelegate.columns);
431+ if (categoryDelegate.collapsedRowCount <= row) {
432+ categoryView.expandedCategoryId = categoryId
433+ }
434+
435+ if (open) {
436+ categoryDelegate.highlightIndex = currentIndex
437+ }
438+
439+ if (!init && model !== undefined) {
440+ var item = model.get(currentIndex)
441+ scopeView.scope.preview(item.uri, item.icon, item.category, 0, item.mimetype, item.title, item.comment, item.dndUri, item.metadata)
442+ }
443+
444+ var itemY = categoryView.contentItem.mapFromItem(categoryDelegate.currentItem).y;
445+
446+ // Find new contentY and effect.postionPx
447+ var newContentY = itemY - effect.positionPx - categoryDelegate.verticalSpacing;
448+
449+ // Make sure the item is not covered by a header. Move the effect split down if necessary
450+ var headerHeight = pageHeader.height + categoryView.stickyHeaderHeight;
451+ var effectAdjust = Math.max(effect.positionPx, headerHeight);
452+
453+ // Make sure we don't overscroll the listview. If yes, adjust effect position
454+ if (newContentY < 0) {
455+ effectAdjust += newContentY;
456+ newContentY = 0;
457+ }
458+ if (newContentY > Math.max(0, categoryView.contentHeight - categoryView.height)) {
459+ effectAdjust += -(categoryView.contentHeight - categoryView.height) + newContentY
460+ newContentY = categoryView.contentHeight - categoryView.height;
461+ }
462+
463+ effect.positionPx = effectAdjust;
464+ categoryView.contentY = newContentY;
465+ }
335
466
336 property bool open: false
467 property bool open: false
337 property bool onScreen: false
468 property bool onScreen: false
338− property bool valid: item !== null
339
469
340 onOpenChanged: {
470 onOpenChanged: {
341 if (open) {
471 if (open) {
342− onScreen = true
472+ onScreen = true;
473+ categoryDelegate.highlightIndex = currentIndex;
474+ pageHeader.unfocus();
475+ } else {
476+ // Cancel any pending preview requests or actions
477+ if (previewListView.currentItem.previewData !== undefined) {
478+ previewListView.currentItem.previewData.cancelAction();
479+ }
480+ scopeView.scope.cancelActivation();
481+ model = undefined;
482+ categoryView.correctExpandedCategory();
483+ categoryDelegate.highlightIndex = -1;
343 }
484 }
344 }
485 }
345
486
346− onLoaded: {
487+ Rectangle {
347− item.previewData = Qt.binding(function() { return previewLoader.previewData })
488+ anchors.fill: parent
489+ color: Qt.rgba(0, 0, 0, .3)
490+ z: -1
348 }
491 }
349
492
493+ delegate: Loader {
494+ id: previewLoader
495+ objectName: "previewLoader" + index
496+ height: previewListView.height
497+ width: previewListView.width
498+ asynchronous: true
499+ source: previewListView.onScreen ?
500+ (previewData !== undefined ? previewDelegateMapper.map(previewData.rendererName) : "DashPreviewPlaceholder.qml") : ""
501+
502+ onPreviewDataChanged: {
503+ if (previewData !== undefined && source.toString().indexOf("DashPreviewPlaceholder.qml") != -1) {
504+ previewLoader.opacity = 0;
505+ }
506+ }
507+
508+ onSourceChanged: {
509+ if (previewData !== undefined) {
510+ fadeIn.start()
511+ }
512+ }
513+
514+ PropertyAnimation {
515+ id: fadeIn
516+ target: previewLoader
517+ property: "opacity"
518+ from: 0.0
519+ to: 1.0
520+ duration: UbuntuAnimation.BriskDuration
521+ }
522+
523+ property var previewData
524+ property bool valid: item !== null
525+
526+ onLoaded: {
527+ if (previewListView.onScreen && previewData !== undefined) {
528+ item.previewData = Qt.binding(function() { return previewData })
529+ }
530+ }
531+
532+ Connections {
533+ ignoreUnknownSignals: true
534+ target: item
535+ onClose: {
536+ previewListView.open = false
537+ }
538+ }
539+
350− function closePreviewSpinner() {
540+ function closePreviewSpinner() {
351− if(item) {
541+ if(item) {
352− item.showProcessingAction = false;
542+ item.showProcessingAction = false;
543+ }
544+ }
545+ }
546+ }
547+
548+ Image {
549+ objectName: "pointerArrow"
550+ anchors {
551+ top: previewListView.bottom
552+ left: parent.left
553+ leftMargin: previewListView.categoryDelegate !== undefined && previewListView.categoryDelegate.currentItem ?
554+ previewListView.categoryDelegate.currentItem.center + (-width + margins) / 2 : 0
555+
556+ Behavior on leftMargin {
557+ SmoothedAnimation {
558+ duration: UbuntuAnimation.FastDuration
559+ }
353 }
560 }
354 }
561 }
562+ height: units.gu(1)
563+ width: units.gu(2)
564+ property int margins: previewListView.categoryDelegate ? previewListView.categoryDelegate.margins : 0
565+ opacity: previewListView.open ? .5 : 0
566+
567+ source: "graphics/tooltip_arrow.png"
355 }
568 }
356
569
357 // TODO: Move as InverseMouseArea to DashPreview
570 // TODO: Move as InverseMouseArea to DashPreview
358 MouseArea {
571 MouseArea {
572+ objectName: "closePreviewMouseArea"
359− enabled: previewLoader.onScreen
573+ enabled: previewListView.onScreen
360 anchors {
574 anchors {
361 fill: parent
575 fill: parent
362 topMargin: effect.bottomGapPx
576 topMargin: effect.bottomGapPx
363 }
577 }
364 onClicked: {
578 onClicked: {
365− previewLoader.open = false;
579+ previewListView.open = false;
366 }
580 }
367 }
581 }
368}
582}
Dash/Music/AlbumTile.qmldeleted−116
@@ -1,116 +0,0 @@
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−AbstractButton {
21− id: root
22− property url source
23− property alias album: albumLabel.text
24− property alias artist: artistLabel.text
25− property alias iconWidth: icon.width
26− property alias iconHeight: icon.height
27−
28− UbuntuShape {
29− id: icon
30− anchors {
31− top: parent.top
32− horizontalCenter: parent.horizontalCenter
33− }
34− radius: "medium"
35− image: Image {
36− source: root.source
37− sourceSize { width: icon.width; height: icon.height }
38− asynchronous: true
39− cache: false
40− }
41− }
42−
43− UbuntuShape {
44− id: borderPressed
45−
46− anchors.fill: icon
47− radius: "medium"
48− borderSource: "radius_pressed.sci"
49− opacity: root.pressed ? 1.0 : 0.0
50− Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
51− }
52−
53− Item {
54− id: artistContainer
55− anchors {
56− left: parent.left
57− right: parent.right
58− top: icon.bottom
59− }
60− height: units.gu(2)
61−
62− Label {
63− id: artistLabel
64− anchors {
65− baseline: parent.bottom
66− left: parent.left
67− right: parent.right
68− leftMargin: units.gu(1)
69− rightMargin: units.gu(1)
70− }
71−
72− color: Theme.palette.selected.backgroundText
73− opacity: 0.9
74− style: Text.Raised
75− styleColor: "black"
76− fontSize: "small"
77− elide: Text.ElideMiddle
78− horizontalAlignment: Text.AlignHCenter
79− }
80− }
81−
82− Item {
83− anchors {
84− left: parent.left
85− right: parent.right
86− top: artistContainer.bottom
87− }
88− height: units.gu(1.5)
89−
90− Label {
91− id: albumLabel
92− anchors {
93− baseline: parent.bottom
94− left: parent.left
95− right: parent.right
96− leftMargin: units.gu(1)
97− rightMargin: units.gu(1)
98− }
99−
100− color: Theme.palette.selected.backgroundText
101− opacity: 0.9
102− style: Text.Raised
103− styleColor: "black"
104− fontSize: "small"
105− font.weight: Font.Light
106− elide: Text.ElideMiddle
107− horizontalAlignment: Text.AlignHCenter
108− }
109− }
110−
111− GridView.onRemove: SequentialAnimation {
112− PropertyAction { target: root; property: "GridView.delayRemove"; value: true }
113− NumberAnimation { target: root; property: "opacity"; from: 1; to: 0; duration: 200; easing.type: Easing.InOutQuad }
114− PropertyAction { target: root; property: "GridView.delayRemove"; value: false }
115− }
116−}
Launcher/QuicklistForegroundStyle.qml → Dash/Music/MusicCarouselLoader.qmlrenamed+6−5
@@ -14,10 +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+import QtQuick 2.0
17−import Ubuntu.Components.Themes.Ambiance 0.1
18+import Ubuntu.Components 0.1
19+import "../Generic"
18
20
19−PopoverForegroundStyle {
21+GenericCarouselLoader {
20− bubbleColor: "#221e1c"
22+ carouselUrl: "MusicCarousel.qml"
21− bubbleOpacity: 0.9
23+ filtergridUrl: "MusicFilterGrid.qml"
22− arrowSource: "graphics/quicklist_tooltip.png"
23}
24}
Dash/Music/MusicFilterGrid.qml+2−4
@@ -44,13 +44,11 @@ GenericFilterGrid {
44 }
44 }
45
45
46 onClicked: {
46 onClicked: {
47− var data = { model: model }
48− filtergrid.clicked(index, data, tile.y)
47+ filtergrid.clicked(index, tile.y)
49 }
48 }
50
49
51 onPressAndHold: {
50 onPressAndHold: {
52− var data = { model: model }
53− filtergrid.pressAndHold(index, data, tile.y)
51+ filtergrid.pressAndHold(index, tile.y)
54 }
52 }
55 }
53 }
56}
54}
Dash/ScopeView.qmldeleted−65
@@ -1,65 +0,0 @@
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 Utils 0.1
19−import Unity 0.1
20−
21−FocusScope {
22− property Scope scope
23− property SortFilterProxyModel categories: categoryFilter
24− property bool isCurrent
25− property ListModel searchHistory
26− property bool moving: false
27−
28− signal endReached
29− signal movementStarted
30− signal positionedAtBeginning
31−
32− // FIXME delay the search so that daemons have time to settle, note that
33− // removing this will break ScopeView::test_changeScope
34− onScopeChanged: {
35− if (scope) {
36− timer.restart();
37− scope.activateApplication.connect(activateApp);
38− }
39− }
40−
41− function activateApp(desktopFilePath) {
42− shell.activateApplication(desktopFilePath);
43− }
44−
45− Binding {
46− target: scope
47− property: "isActive"
48− value: isCurrent
49− }
50−
51− Timer {
52− id: timer
53− interval: 2000
54− onTriggered: scope.searchQuery = ""
55− }
56−
57− SortFilterProxyModel {
58− id: categoryFilter
59− model: scope ? scope.categories : null
60− dynamicSortFilter: true
61− filterRole: Categories.RoleCount
62− filterRegExp: /^0$/
63− invertMatch: true
64− }
65−}
Dash/SearchableResultModel.qml+4
@@ -25,6 +25,10 @@ SortFilterProxyModel {
25
25
26 filterRole: CategoryResults.RoleTitle
26 filterRole: CategoryResults.RoleTitle
27
27
28+ function get(index) {
29+ return model.get(mapToSource(index))
30+ }
31+
28 onSearchQueryChanged: {
32 onSearchQueryChanged: {
29 if (searchQuery.length == 0) {
33 if (searchQuery.length == 0) {
30 filterRegExp = RegExp("");
34 filterRegExp = RegExp("");
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}
Dash/Video/VideoFilterGrid.qml+2−4
@@ -42,13 +42,11 @@ GenericFilterGrid {
42 style: VideoTileStyle {}
42 style: VideoTileStyle {}
43
43
44 onClicked: {
44 onClicked: {
45− var data = { model: model }
46− filtergrid.clicked(index, data, tile.y)
45+ filtergrid.clicked(index, tile.y)
47 }
46 }
48
47
49 onPressAndHold: {
48 onPressAndHold: {
50− var data = { model: model }
51− filtergrid.pressAndHold(index, data, tile.y)
49+ filtergrid.pressAndHold(index, tile.y)
52 }
50 }
53 }
51 }
54}
52}
Dash/Video/VideoInfo.qmldeleted−84
@@ -1,84 +0,0 @@
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 QtQuick.XmlListModel 2.0
19−
20−Item {
21− id: info
22− property string source
23−
24− property bool ready: nfo.status == XmlListModel.Ready || nfoTV.status == XmlListModel.Ready
25− property bool isMovie: true
26− property variant video: null
27− property variant tvShow: null
28−
29− function getActors() {
30− var c = []
31− if (video.actor1) c.push(video.actor1)
32− if (video.actor2) c.push(video.actor2)
33− if (video.actor3) c.push(video.actor3)
34− return c
35− }
36−
37− onSourceChanged: isMovie = true
38−
39− XmlListModel {
40− id: nfo
41− source: info.source
42− query: (isMovie) ? "/movie" : "/episodedetails"
43−
44− XmlRole { name: "title"; query: "title/string()" }
45− XmlRole { name: "year"; query: "year/number()" }
46− XmlRole { name: "runtime"; query: "runtime/number()" }
47− XmlRole { name: "rating"; query: "rating/number()" }
48− XmlRole { name: "plot"; query: "plot/string()" }
49− XmlRole { name: "director"; query: "director[1]/string()" }
50− XmlRole { name: "actor1"; query: "actor[1]/name/string()" }
51− XmlRole { name: "actor2"; query: "actor[2]/name/string()" }
52− XmlRole { name: "actor3"; query: "actor[3]/name/string()" }
53− XmlRole { name: "author"; query: "author[1]/string()" }
54− XmlRole { name: "season"; query: "season/number()" }
55− XmlRole { name: "episode"; query: "episode/number()" }
56−
57− XmlRole { name: "rentPrice"; query: "rent_price/string()" }
58− XmlRole { name: "buyPrice"; query: "buy_price/string()" }
59− XmlRole { name: "expires"; query: "expires/string()" }
60−
61− onStatusChanged: if (status == XmlListModel.Ready) {
62− if (count > 0) info.video = nfo.get(0)
63− else info.isMovie = false
64− } else if (status == XmlListModel.Error) info.isMovie = false
65− }
66−
67− XmlListModel {
68− id: nfoTV
69− source: (nfo.isMovie) ? "" : info.source.substring(0, info.source.lastIndexOf("/") + 1) + "tvshow.nfo"
70− query: "/tvshow"
71−
72− XmlRole { name: "title"; query: "title/string()" }
73−
74− onStatusChanged: if (status == XmlListModel.Ready) {
75− if (count > 0) info.tvShow = nfoTV.get(0)
76− } else if (status == XmlListModel.Error) {
77− // Search for tvshow.nfo in the directory above this one to cater
78− // for directory layout Show/Season
79− var path = info.source.split("/")
80− path.splice(-2, 2, "tvshow.nfo")
81− source = path.join("/")
82− }
83− }
84−}
Dash/graphics/tooltip_arrow@27.pngnew file

Binary file not shown.

Greeter/Greeter.qml+5−8
@@ -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
@@ -89,7 +89,7 @@ Showable {
89 when: teasingTimer.running
89 when: teasingTimer.running
90 PropertyChanges {
90 PropertyChanges {
91 target: greeter
91 target: greeter
92− x: -units.gu(2)
92+ x: -dragHandle.hintDisplacement
93 }
93 }
94 }
94 }
95 ]
95 ]
@@ -113,10 +113,7 @@ Showable {
113 anchors.bottom: parent.bottom
113 anchors.bottom: parent.bottom
114 anchors.right: parent.right
114 anchors.right: parent.right
115
115
116− // no need for requiring a directional drag since we are covering the screen
116+ hintDisplacement: units.gu(2)
117− // anyway (i.e., no change user could be trying to interact with some other
118− // UI element)
119− distanceThreshold: 0
120
117
121 enabled: greeter.narrowMode || !greeter.locked
118 enabled: greeter.narrowMode || !greeter.locked
122
119
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
Launcher/LauncherDelegate.qml+1
@@ -57,6 +57,7 @@ Item {
57 anchors.fill: parent
57 anchors.fill: parent
58 anchors.margins: units.gu(1)
58 anchors.margins: units.gu(1)
59 radius: "medium"
59 radius: "medium"
60+ borderSource: "none"
60
61
61 image: Image {
62 image: Image {
62 id: iconImage
63 id: iconImage
Launcher/LauncherPanel.qml+88−47
@@ -21,6 +21,7 @@ import Unity 0.1
21import Unity.Launcher 0.1
21import Unity.Launcher 0.1
22import Ubuntu.Components.Popups 0.1
22import Ubuntu.Components.Popups 0.1
23import "../Components/ListItems"
23import "../Components/ListItems"
24+import "../Components/"
24
25
25Item {
26Item {
26 id: root
27 id: root
@@ -31,7 +32,7 @@ Item {
31 property bool inverted: true
32 property bool inverted: true
32 property bool dragging: false
33 property bool dragging: false
33 property bool moving: launcherListView.moving || launcherListView.flicking
34 property bool moving: launcherListView.moving || launcherListView.flicking
34− property bool preventHiding: moving || dndArea.draggedIndex >= 0 || dndArea.quickListPopover !== null || dndArea.pressed
35+ property bool preventHiding: moving || dndArea.draggedIndex >= 0 || quickList.state === "open" || dndArea.pressed
35 property int highlightIndex: -1
36 property int highlightIndex: -1
36
37
37 signal applicationSelected(string appId)
38 signal applicationSelected(string appId)
@@ -278,7 +279,6 @@ Item {
278 property bool postDragging: false
279 property bool postDragging: false
279 property int startX
280 property int startX
280 property int startY
281 property int startY
281− property var quickListPopover: null
282
282
283 onPressed: {
283 onPressed: {
284 selectedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
284 selectedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
@@ -357,18 +357,17 @@ Item {
357 draggedIndex = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
357 draggedIndex = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
358
358
359 // Opening QuickList
359 // Opening QuickList
360− var quickListModel = launcherListView.model.get(draggedIndex).quickList
360+ quickList.item = selectedItem;
361− var quickListAppId = launcherListView.model.get(draggedIndex).appId
361+ quickList.model = launcherListView.model.get(draggedIndex).quickList;
362−
362+ quickList.appId = launcherListView.model.get(draggedIndex).appId;
363− quickListPopover = PopupUtils.open(popoverComponent, selectedItem,
363+ quickList.state = "open";
364− {model: quickListModel, appId: quickListAppId})
365
364
366 launcherListView.interactive = false
365 launcherListView.interactive = false
367
366
368 var yOffset = draggedIndex > 0 ? (mouseY + launcherListView.realContentY) % (draggedIndex * launcherListView.realItemHeight) : mouseY + launcherListView.realContentY
367 var yOffset = draggedIndex > 0 ? (mouseY + launcherListView.realContentY) % (draggedIndex * launcherListView.realItemHeight) : mouseY + launcherListView.realContentY
369
368
370 fakeDragItem.iconName = launcherListView.model.get(draggedIndex).icon
369 fakeDragItem.iconName = launcherListView.model.get(draggedIndex).icon
371− fakeDragItem.x = 0
370+ fakeDragItem.x = units.gu(0.5)
372 fakeDragItem.y = mouseY - yOffset + launcherListView.anchors.topMargin + launcherListView.topMargin
371 fakeDragItem.y = mouseY - yOffset + launcherListView.anchors.topMargin + launcherListView.topMargin
373 fakeDragItem.angle = selectedItem.angle * (root.inverted ? -1 : 1)
372 fakeDragItem.angle = selectedItem.angle * (root.inverted ? -1 : 1)
374 fakeDragItem.offset = selectedItem.offset * (root.inverted ? -1 : 1)
373 fakeDragItem.offset = selectedItem.offset * (root.inverted ? -1 : 1)
@@ -387,7 +386,7 @@ Item {
387 var distance = Math.max(Math.abs(mouseX - startX), Math.abs(mouseY - startY))
386 var distance = Math.max(Math.abs(mouseX - startX), Math.abs(mouseY - startY))
388 if (!preDragging && distance > units.gu(1.5)) {
387 if (!preDragging && distance > units.gu(1.5)) {
389 preDragging = true;
388 preDragging = true;
390− PopupUtils.close(quickListPopover)
389+ quickList.state = "";
391 }
390 }
392 if (distance > launcherListView.itemHeight) {
391 if (distance > launcherListView.itemHeight) {
393 selectedItem.dragging = true
392 selectedItem.dragging = true
@@ -482,53 +481,95 @@ Item {
482 }
481 }
483 }
482 }
484
483
485− Component {
484+ UbuntuShapeForItem {
486− id: popoverComponent
485+ id: quickListShape
486+ objectName: "quickListShape"
487+ anchors.fill: quickList
488+ opacity: quickList.state === "open" ? 0.8 : 0
489+ visible: opacity > 0
490+ rotation: root.rotation
491+
492+ Behavior on opacity {
493+ UbuntuNumberAnimation {}
494+ }
495+
496+ image: quickList
497+
498+ Image {
499+ anchors {
500+ right: parent.left
501+ rightMargin: -units.dp(4)
502+ verticalCenter: parent.verticalCenter
503+ verticalCenterOffset: -quickList.offset
504+ }
505+ height: units.gu(1)
506+ width: units.gu(2)
507+ source: "graphics/quicklist_tooltip.png"
508+ rotation: 90
509+ }
510+
511+ InverseMouseArea {
512+ anchors.fill: parent
513+ enabled: quickList.state == "open"
514+ onClicked: {
515+ quickList.state = ""
516+ }
517+ }
518+
519+ }
520+
521+ Rectangle {
522+ id: quickList
523+ objectName: "quickList"
524+ color: "#221e1c"
525+ width: units.gu(30)
526+ height: quickListColumn.height
527+ anchors {
528+ left: root.inverted ? undefined : parent.right
529+ right: root.inverted ? parent.left : undefined
530+ margins: units.gu(1)
487
531
488− Popover {
532+ }
489− id: popover
533+ y: itemCenter - (height / 2) + offset
490− property var model
534+ rotation: root.rotation
491− property string appId
492− contentWidth: quickListColumn.width
493− foregroundStyle: QuicklistForegroundStyle {}
494
535
495− // FIXME: There's a bug in the Popover positioning that it covers the item in case it is rotated.
536+ property var model
496− // https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1204470
537+ property string appId
497− // For now, let's move the Popover around with callerMargin.
538+ property var item
498− // Remove popupMargin once the bug is fixed.
499− property int popupMargin: root.inverted ? launcherListView.itemHeight : 0;
500
539
501− callerMargin: units.gu(1) + popupMargin
540+ // internal
541+ property int itemCenter: item ? root.mapFromItem(quickList.item).y + (item.height / 2) : units.gu(1)
542+ property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
543+ itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
502
544
503− Column {
545+ Column {
504− id: quickListColumn
546+ id: quickListColumn
505− width: units.gu(30)
547+ width: parent.width
506− height: childrenRect.height
548+ height: childrenRect.height
507
549
508− Repeater {
550+ Repeater {
509− id: popoverRepeater
551+ id: popoverRepeater
510− model: popover.model
552+ model: quickList.model
511
553
512− ListItems.Standard {
554+ ListItems.Standard {
513− objectName: "quickListEntry" + index
555+ objectName: "quickListEntry" + index
514− text: (model.clickable ? "" : "<b>") + model.label + (model.clickable ? "" : "</b>")
556+ text: (model.clickable ? "" : "<b>") + model.label + (model.clickable ? "" : "</b>")
515− highlightWhenPressed: model.clickable
557+ highlightWhenPressed: model.clickable
516
558
517− // FIXME: This is a workaround for the theme not being context sensitive. I.e. the
559+ // FIXME: This is a workaround for the theme not being context sensitive. I.e. the
518− // ListItems don't know that they are sitting in a themed Popover where the color
560+ // ListItems don't know that they are sitting in a themed Popover where the color
519− // needs to be inverted.
561+ // needs to be inverted.
520− __foregroundColor: Theme.palette.selected.backgroundText
562+ __foregroundColor: Theme.palette.selected.backgroundText
521
563
522− onClicked: {
564+ onClicked: {
523− if (!model.clickable) {
565+ if (!model.clickable) {
524− return;
566+ return;
525− }
526− PopupUtils.close(popover);
527− // Unsetting model to prevent showing changing entries during fading out
528− // that may happen because of triggering an action.
529− LauncherModel.quickListActionInvoked(appId, index);
530− popoverRepeater.model = undefined;
531 }
567 }
568+ quickList.state = "";
569+ // Unsetting model to prevent showing changing entries during fading out
570+ // that may happen because of triggering an action.
571+ LauncherModel.quickListActionInvoked(quickList.appId, index);
572+ quickList.model = undefined;
532 }
573 }
533 }
574 }
534 }
575 }
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+37−10
@@ -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
@@ -38,6 +37,7 @@ Showable {
38 property bool partiallyOpened: height > panelHeight && !fullyOpened
37 property bool partiallyOpened: height > panelHeight && !fullyOpened
39 property real visualBottom: Math.max(y+height, y+indicatorRow.y+indicatorRow.height)
38 property real visualBottom: Math.max(y+height, y+indicatorRow.y+indicatorRow.height)
40 property bool contentEnabled: true
39 property bool contentEnabled: true
40+ property bool initalizeItem: true
41 readonly property alias content: menuContent
41 readonly property alias content: menuContent
42
42
43 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
43 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
@@ -64,14 +64,13 @@ Showable {
64 }
64 }
65
65
66 height: panelHeight
66 height: panelHeight
67+ onHeightChanged: updateRevealProgressState(indicators.height - panelHeight, true)
67
68
68− onHeightChanged: {
69+ function updateRevealProgressState(revealProgress, enableRelease) {
69− // need to use handle.get_height(). As the handle height depends on indicators.height changes (but this is called first!)
70− var revealProgress = indicators.height - panelHeight
71 if (!showAnimation.running && !hideAnimation.running) {
70 if (!showAnimation.running && !hideAnimation.running) {
72− if (revealProgress == 0) {
71+ if (revealProgress === 0) {
73 indicators.state = "initial";
72 indicators.state = "initial";
74− } else if (revealProgress <= hintValue) {
73+ } else if (revealProgress > 0 && revealProgress <= hintValue) {
75 indicators.state = "hint";
74 indicators.state = "hint";
76 } else if (revealProgress > hintValue && revealProgress < lockThreshold) {
75 } else if (revealProgress > hintValue && revealProgress < lockThreshold) {
77 indicators.state = "reveal";
76 indicators.state = "reveal";
@@ -80,7 +79,7 @@ Showable {
80 }
79 }
81 }
80 }
82
81
83− if (revealProgress == 0) {
82+ if (enableRelease && revealProgress === 0) {
84 menuContent.releaseContent();
83 menuContent.releaseContent();
85 }
84 }
86 }
85 }
@@ -100,14 +99,14 @@ 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 /*
107 Vertical velocity check. Don't change the indicator if we're moving too quickly.
106 Vertical velocity check. Don't change the indicator if we're moving too quickly.
108 */
107 */
109 var verticalSpeed = Math.abs(yVelocityCalculator.calculate());
108 var verticalSpeed = Math.abs(yVelocityCalculator.calculate());
110− if (verticalSpeed >= 0.05 && indicatorRow.currentItem!=null) {
109+ if (verticalSpeed >= 0.05 && !initalizeItem) {
111 return;
110 return;
112 }
111 }
113
112
@@ -147,6 +146,7 @@ Showable {
147 } else if (!currentItem) {
146 } else if (!currentItem) {
148 indicatorRow.setDefaultItem();
147 indicatorRow.setDefaultItem();
149 }
148 }
149+ initalizeItem = indicatorRow.currentItem == null;
150 }
150 }
151
151
152 // eater
152 // eater
@@ -282,6 +282,33 @@ Showable {
282 enableIndexChangeSignal = oldActive;
282 enableIndexChangeSignal = oldActive;
283 }
283 }
284 }
284 }
285+
286+ EdgeDragArea {
287+ id: rowDragArea
288+ anchors.fill: indicatorRow
289+ direction: Direction.Downwards
290+ maxSilenceTime: 2000
291+ distanceThreshold: 0
292+
293+ enabled: fullyOpened
294+ onDraggingChanged: {
295+ if (dragging) {
296+ initalizeItem = true;
297+ updateRevealProgressState(Math.max(touchSceneY - panelHeight, hintValue), false);
298+ indicators.calculateCurrentItem(touchX, false);
299+ } else {
300+ indicators.state = "commit";
301+ }
302+ }
303+
304+ onTouchXChanged: {
305+ indicators.calculateCurrentItem(touchX, true);
306+ }
307+ onTouchSceneYChanged: {
308+ updateRevealProgressState(Math.max(touchSceneY - panelHeight, hintValue), false);
309+ yVelocityCalculator.trackedPosition = touchSceneY;
310+ }
311+ }
285 }
312 }
286
313
287 Connections {
314 Connections {
@@ -298,7 +325,7 @@ Showable {
298 onRunningChanged: {
325 onRunningChanged: {
299 if (hideAnimation.running) {
326 if (hideAnimation.running) {
300 indicators.state = "initial";
327 indicators.state = "initial";
301− indicatorRow.currentItem = null;
328+ initalizeItem = true;
302 }
329 }
303 }
330 }
304 }
331 }
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)
data/unity8.conf+20
@@ -6,4 +6,24 @@ stop on desktop-end
6
6
7respawn
7respawn
8
8
9+pre-start script
10+ if [ -n "$MIR_SOCKET" ]; then
11+ if [ -z "$UNITY_MIR_SOCKET" ]; then
12+ # Save original value of MIR_SOCKET in case we are restarted,
13+ # as we modify the variable for future jobs, including ourself.
14+ UNITY_MIR_SOCKET=$MIR_SOCKET
15+ initctl set-env --global UNITY_MIR_SOCKET=$UNITY_MIR_SOCKET
16+ fi
17+
18+ # Point unity8 at unity-system-compositor
19+ MIR_SERVER_FILE=$XDG_RUNTIME_DIR/mir_socket
20+ initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
21+ initctl set-env MIR_SERVER_HOST_SOCKET=$UNITY_MIR_SOCKET
22+
23+ # Point all future jobs in this session to our Mir socket instead of
24+ # unity-system-compositor's socket.
25+ initctl set-env --global MIR_SOCKET=$MIR_SERVER_FILE
26+ fi
27+end script
28+
9exec ${BINARY:-unity8} $ARGS
29exec ${BINARY:-unity8} $ARGS
debian/changelog+102
@@ -1,3 +1,105 @@
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+
67+unity8 (7.83+14.04.20131031-0ubuntu1) trusty; urgency=low
68+
69+ [ Michał Sawicz ]
70+ * Use setenv as early as possible to avoid setenv and getenv clashing
71+ in multi-threaded situations. (LP: #1240866)
72+
73+ [ Ubuntu daily release ]
74+ * Automatic snapshot from revision 482
75+
76+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 31 Oct 2013 20:10:56 +0000
77+
78+unity8 (7.83+14.04.20131028.1-0ubuntu1) trusty; urgency=low
79+
80+ * New rebuild forced
81+ * Automatic snapshot from revision 480
82+
83+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 28 Oct 2013 22:42:07 +0000
84+
85+unity8 (7.83+14.04.20131028-0ubuntu1) trusty; urgency=low
86+
87+ [ Andrea Cimitan ]
88+ * Fix 1195349 by counting drawbuffer on the newContentX logic of the
89+ carousel When we changed carousel from repeater to listview, we
90+ added drawbuffer. this breaks the logic of newContentX, which was
91+ considered disabled and set to -1. The correct disabled value now
92+ has to take into account the drawbuffer. (LP: #1195349)
93+
94+ [ Christopher Lee ]
95+ * Checks both then env and upstart env for the currently set
96+ XDG_DATA_DIRS so they can be set correctly for the test.
97+
98+ [ Ubuntu daily release ]
99+ * Automatic snapshot from revision 479
100+
101+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 28 Oct 2013 03:08:59 +0000
102+
1unity8 (7.83+13.10.20131016.2-0ubuntu1) saucy; urgency=low
103unity8 (7.83+13.10.20131016.2-0ubuntu1) saucy; urgency=low
2
104
3 [ Loïc Minier ]
105 [ Loïc Minier ]
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,
main.cpp+8−8
@@ -78,14 +78,6 @@ void resolveIconTheme() {
78
78
79int startShell(int argc, const char** argv, void* server)
79int startShell(int argc, const char** argv, void* server)
80{
80{
81− /* Workaround Qt platform integration plugin not advertising itself
82− as having the following capabilities:
83− - QPlatformIntegration::ThreadedOpenGL
84− - QPlatformIntegration::BufferQueueingOpenGL
85− */
86− setenv("QML_FORCE_THREADED_RENDERER", "1", 1);
87− setenv("QML_FIXED_ANIMATION_STEP", "1", 1);
88−
89 const bool isUbuntuMirServer = qgetenv("QT_QPA_PLATFORM") == "ubuntumirserver";
81 const bool isUbuntuMirServer = qgetenv("QT_QPA_PLATFORM") == "ubuntumirserver";
90
82
91 QGuiApplication::setApplicationName("Unity 8");
83 QGuiApplication::setApplicationName("Unity 8");
@@ -186,6 +178,14 @@ int startShell(int argc, const char** argv, void* server)
186
178
187int main(int argc, const char *argv[])
179int main(int argc, const char *argv[])
188{
180{
181+ /* Workaround Qt platform integration plugin not advertising itself
182+ as having the following capabilities:
183+ - QPlatformIntegration::ThreadedOpenGL
184+ - QPlatformIntegration::BufferQueueingOpenGL
185+ */
186+ setenv("QML_FORCE_THREADED_RENDERER", "1", 1);
187+ setenv("QML_FIXED_ANIMATION_STEP", "1", 1);
188+
189 // For ubuntumirserver/ubuntumirclient
189 // For ubuntumirserver/ubuntumirclient
190 if (qgetenv("QT_QPA_PLATFORM").startsWith("ubuntumir")) {
190 if (qgetenv("QT_QPA_PLATFORM").startsWith("ubuntumir")) {
191 setenv("QT_QPA_PLATFORM", "ubuntumirserver", 1);
191 setenv("QT_QPA_PLATFORM", "ubuntumirserver", 1);
plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+15−6
@@ -155,6 +155,7 @@ ListViewWithPageHeader::ListViewWithPageHeader()
155 , m_topSectionItem(nullptr)
155 , m_topSectionItem(nullptr)
156 , m_forceNoClip(false)
156 , m_forceNoClip(false)
157 , m_inLayout(false)
157 , m_inLayout(false)
158+ , m_inContentHeightKeepHeaderShown(false)
158{
159{
159 m_clipItem = new QQuickItem(contentItem());
160 m_clipItem = new QQuickItem(contentItem());
160// m_clipItem = new QQuickRectangle(contentItem());
161// m_clipItem = new QQuickRectangle(contentItem());
@@ -286,10 +287,12 @@ void ListViewWithPageHeader::setSectionDelegate(QQmlComponent *delegate)
286 m_topSectionItem = getSectionItem(QString());
287 m_topSectionItem = getSectionItem(QString());
287 m_topSectionItem->setZ(3);
288 m_topSectionItem->setZ(3);
288 QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
289 QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
290+ connect(m_topSectionItem, SIGNAL(heightChanged()), SIGNAL(stickyHeaderHeightChanged()));
289
291
290 // TODO create sections for existing items
292 // TODO create sections for existing items
291
293
292 Q_EMIT sectionDelegateChanged();
294 Q_EMIT sectionDelegateChanged();
295+ Q_EMIT stickyHeaderHeightChanged();
293 }
296 }
294}
297}
295
298
@@ -325,6 +328,11 @@ void ListViewWithPageHeader::setForceNoClip(bool noClip)
325 }
328 }
326}
329}
327
330
331+int ListViewWithPageHeader::stickyHeaderHeight() const
332+{
333+ return m_topSectionItem ? m_topSectionItem->height() : 0;
334+}
335+
328void ListViewWithPageHeader::positionAtBeginning()
336void ListViewWithPageHeader::positionAtBeginning()
329{
337{
330 if (m_delegateModel->count() <= 0)
338 if (m_delegateModel->count() <= 0)
@@ -476,7 +484,7 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
476 qreal diff = m_previousContentY - contentY();
484 qreal diff = m_previousContentY - contentY();
477 const bool showHeaderAnimationRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationShowHeader;
485 const bool showHeaderAnimationRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationShowHeader;
478 if (m_headerItem) {
486 if (m_headerItem) {
479− auto oldHeaderItemShownHeight = m_headerItemShownHeight;
487+ const auto oldHeaderItemShownHeight = m_headerItemShownHeight;
480 if (contentY() < -m_minYExtent) {
488 if (contentY() < -m_minYExtent) {
481 // Stick the header item to the top when dragging down
489 // Stick the header item to the top when dragging down
482 m_headerItem->setY(contentY());
490 m_headerItem->setY(contentY());
@@ -491,10 +499,10 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
491 const bool notShownByItsOwn = contentY() + diff >= m_headerItem->y() + m_headerItem->height();
499 const bool notShownByItsOwn = contentY() + diff >= m_headerItem->y() + m_headerItem->height();
492 const bool maximizeVisibleAreaRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationMaximizeVisibleArea;
500 const bool maximizeVisibleAreaRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationMaximizeVisibleArea;
493
501
494− if (!scrolledUp && contentY() == -m_minYExtent) {
502+ if (!scrolledUp && (contentY() == -m_minYExtent || (m_headerItemShownHeight == 0 && m_previousContentY == m_headerItem->y()))) {
495 m_headerItemShownHeight = 0;
503 m_headerItemShownHeight = 0;
496− m_headerItem->setY(contentY());
504+ m_headerItem->setY(-m_minYExtent);
497− } else if ((scrolledUp && notRebounding && notShownByItsOwn && !maximizeVisibleAreaRunning) || (m_headerItemShownHeight > 0)) {
505+ } else if ((scrolledUp && notRebounding && notShownByItsOwn && !maximizeVisibleAreaRunning) || (m_headerItemShownHeight > 0) || m_inContentHeightKeepHeaderShown) {
498 if (maximizeVisibleAreaRunning && diff > 0) // If we are maximizing and the header was shown, make sure we hide it
506 if (maximizeVisibleAreaRunning && diff > 0) // If we are maximizing and the header was shown, make sure we hide it
499 m_headerItemShownHeight -= diff;
507 m_headerItemShownHeight -= diff;
500 else
508 else
@@ -980,7 +988,6 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
980 if (growUp) {
988 if (growUp) {
981 ListItem *firstItem = m_visibleItems.first();
989 ListItem *firstItem = m_visibleItems.first();
982 firstItem->setY(firstItem->y() - item->height());
990 firstItem->setY(firstItem->y() - item->height());
983− adjustMinYExtent();
984 }
991 }
985 // Adding an item may break a "same section" chain, so check
992 // Adding an item may break a "same section" chain, so check
986 // if we need adding a new section item
993 // if we need adding a new section item
@@ -991,7 +998,6 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
991 if (growUp && nextItem->m_sectionItem) {
998 if (growUp && nextItem->m_sectionItem) {
992 ListItem *firstItem = m_visibleItems.first();
999 ListItem *firstItem = m_visibleItems.first();
993 firstItem->setY(firstItem->y() - nextItem->m_sectionItem->height());
1000 firstItem->setY(firstItem->y() - nextItem->m_sectionItem->height());
994− adjustMinYExtent();
995 }
1001 }
996 }
1002 }
997 }
1003 }
@@ -1000,6 +1006,7 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
1000 ListItem *firstItem = m_visibleItems.first();
1006 ListItem *firstItem = m_visibleItems.first();
1001 firstItem->setY(oldFirstValidIndexPos);
1007 firstItem->setY(oldFirstValidIndexPos);
1002 }
1008 }
1009+ adjustMinYExtent();
1003 } else if (insert.index <= m_firstVisibleIndex) {
1010 } else if (insert.index <= m_firstVisibleIndex) {
1004 m_firstVisibleIndex += insert.count;
1011 m_firstVisibleIndex += insert.count;
1005 }
1012 }
@@ -1267,7 +1274,9 @@ void ListViewWithPageHeader::updatePolish()
1267
1274
1268 m_contentHeightDirty = false;
1275 m_contentHeightDirty = false;
1269 adjustMinYExtent();
1276 adjustMinYExtent();
1277+ m_inContentHeightKeepHeaderShown = m_headerItem && m_headerItem->y() == contentY();
1270 setContentHeight(contentHeight);
1278 setContentHeight(contentHeight);
1279+ m_inContentHeightKeepHeaderShown = false;
1271 }
1280 }
1272}
1281}
1273
1282
plugins/ListViewWithPageHeader/listviewwithpageheader.h+5
@@ -60,6 +60,7 @@ class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeLi
60 Q_PROPERTY(QQmlComponent *sectionDelegate READ sectionDelegate WRITE setSectionDelegate NOTIFY sectionDelegateChanged)
60 Q_PROPERTY(QQmlComponent *sectionDelegate READ sectionDelegate WRITE setSectionDelegate NOTIFY sectionDelegateChanged)
61 Q_PROPERTY(QString sectionProperty READ sectionProperty WRITE setSectionProperty NOTIFY sectionPropertyChanged)
61 Q_PROPERTY(QString sectionProperty READ sectionProperty WRITE setSectionProperty NOTIFY sectionPropertyChanged)
62 Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
62 Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
63+ Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
63
64
64 friend class ListViewWithPageHeaderTest;
65 friend class ListViewWithPageHeaderTest;
65 friend class ListViewWithPageHeaderTestSection;
66 friend class ListViewWithPageHeaderTestSection;
@@ -87,6 +88,8 @@ public:
87 bool forceNoClip() const;
88 bool forceNoClip() const;
88 void setForceNoClip(bool noClip);
89 void setForceNoClip(bool noClip);
89
90
91+ int stickyHeaderHeight() const;
92+
90 Q_INVOKABLE void positionAtBeginning();
93 Q_INVOKABLE void positionAtBeginning();
91 Q_INVOKABLE void showHeader();
94 Q_INVOKABLE void showHeader();
92 Q_INVOKABLE QQuickItem *item(int modelIndex) const;
95 Q_INVOKABLE QQuickItem *item(int modelIndex) const;
@@ -104,6 +107,7 @@ Q_SIGNALS:
104 void sectionDelegateChanged();
107 void sectionDelegateChanged();
105 void sectionPropertyChanged();
108 void sectionPropertyChanged();
106 void forceNoClipChanged();
109 void forceNoClipChanged();
110+ void stickyHeaderHeightChanged();
107
111
108protected:
112protected:
109 void componentComplete();
113 void componentComplete();
@@ -202,6 +206,7 @@ private:
202
206
203 bool m_forceNoClip;
207 bool m_forceNoClip;
204 bool m_inLayout;
208 bool m_inLayout;
209+ bool m_inContentHeightKeepHeaderShown;
205
210
206 // Qt 5.0 doesn't like releasing the items just after itemCreated
211 // Qt 5.0 doesn't like releasing the items just after itemCreated
207 // so we delay the releasing until the next updatePolish
212 // so we delay the releasing until the next updatePolish
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/CMakeLists.txt−1
@@ -34,7 +34,6 @@ set(QMLPLUGIN_SRC
34 radiooptionfilter.cpp
34 radiooptionfilter.cpp
35 ratingsfilter.cpp
35 ratingsfilter.cpp
36 ratingfilteroption.cpp
36 ratingfilteroption.cpp
37− bottombarvisibilitycommunicatorshell.cpp
38 applicationpreview.cpp
37 applicationpreview.cpp
39 genericpreview.cpp
38 genericpreview.cpp
40 moviepreview.cpp
39 moviepreview.cpp
plugins/Unity/Indicators/CMakeLists.txt+1
@@ -36,6 +36,7 @@ set(IndicatorsQML_SOURCES
36 unitymenumodelcache.cpp
36 unitymenumodelcache.cpp
37 unitymenumodelstack.cpp
37 unitymenumodelstack.cpp
38 visibleindicatorsmodel.cpp
38 visibleindicatorsmodel.cpp
39+ timeformatter.cpp
39)
40)
40add_definitions(-DUNITYINDICATORS_LIBRARY)
41add_definitions(-DUNITYINDICATORS_LIBRARY)
41
42
plugins/Unity/Indicators/Messaging/qml/MessageMenuItemFactory.qml+3−4
@@ -22,7 +22,6 @@ import QtQuick 2.0
22import Ubuntu.Components 0.1
22import Ubuntu.Components 0.1
23import Unity.Indicators 0.1 as Indicators
23import Unity.Indicators 0.1 as Indicators
24import QMenuModel 0.1 as QMenuModel
24import QMenuModel 0.1 as QMenuModel
25−import "utils.js" as Utils
26
25
27Indicators.BaseMenuItem {
26Indicators.BaseMenuItem {
28 id: menuItem
27 id: menuItem
@@ -43,7 +42,7 @@ Indicators.BaseMenuItem {
43 SimpleTextMessage {
42 SimpleTextMessage {
44 // text
43 // text
45 title: menu && menu.label ? menu.label : ""
44 title: menu && menu.label ? menu.label : ""
46− time: menu ? Utils.formatDate(menu.ext.xCanonicalTime) : ""
45+ time: menu ? menu.ext.xCanonicalTime : 0
47 message: menu && menu.ext.xCanonicalText ? menu.ext.xCanonicalText : ""
46 message: menu && menu.ext.xCanonicalText ? menu.ext.xCanonicalText : ""
48 // icons
47 // icons
49 avatar: menu && menu.ext.icon !== undefined ? menu.ext.icon : "qrc:/indicators/artwork/messaging/default_contact.png"
48 avatar: menu && menu.ext.icon !== undefined ? menu.ext.icon : "qrc:/indicators/artwork/messaging/default_contact.png"
@@ -72,7 +71,7 @@ Indicators.BaseMenuItem {
72
71
73 // text
72 // text
74 title: menu && menu.label ? menu.label : ""
73 title: menu && menu.label ? menu.label : ""
75− time: menu ? Utils.formatDate(menu.ext.xCanonicalTime) : ""
74+ time: menu ? menu.ext.xCanonicalTime : 0
76 message: menu && menu.ext.xCanonicalText ? menu.ext.xCanonicalText : ""
75 message: menu && menu.ext.xCanonicalText ? menu.ext.xCanonicalText : ""
77 replyButtonText: actionsDescription && actionsDescription[0].label ? actionsDescription[0].label : "Send"
76 replyButtonText: actionsDescription && actionsDescription[0].label ? actionsDescription[0].label : "Send"
78 // icons
77 // icons
@@ -112,7 +111,7 @@ Indicators.BaseMenuItem {
112
111
113 // text
112 // text
114 title: menu && menu.label ? menu.label : ""
113 title: menu && menu.label ? menu.label : ""
115− time: menu ? Utils.formatDate(menu.ext.xCanonicalTime) : ""
114+ time: menu ? menu.ext.xCanonicalTime : ""
116 message: menu && menu.ext.xCanonicalText ? menu.ext.xCanonicalText : ""
115 message: menu && menu.ext.xCanonicalText ? menu.ext.xCanonicalText : ""
117 actionButtonText: actionsDescription && actionsDescription[0].label ? actionsDescription[0].label : "Call back"
116 actionButtonText: actionsDescription && actionsDescription[0].label ? actionsDescription[0].label : "Call back"
118 replyButtonText: actionsDescription && actionsDescription[1].label ? actionsDescription[1].label : "Send"
117 replyButtonText: actionsDescription && actionsDescription[1].label ? actionsDescription[1].label : "Send"
plugins/Unity/Indicators/Messaging/qml/SimpleTextMessage.qml+9−2
@@ -20,19 +20,20 @@
20
20
21import QtQuick 2.0
21import QtQuick 2.0
22import Ubuntu.Components 0.1
22import Ubuntu.Components 0.1
23+import Unity.Indicators 0.1
23
24
24HeroMessage {
25HeroMessage {
25 id: __heroMessage
26 id: __heroMessage
26
27
27 property string title: ""
28 property string title: ""
28− property string time: ""
29+ property var time
29 property string message: ""
30 property string message: ""
30
31
31 property alias footer: footerLoader.sourceComponent
32 property alias footer: footerLoader.sourceComponent
32
33
33 expandedHeight: fullMessage.y + fullMessage.height + units.gu(2)
34 expandedHeight: fullMessage.y + fullMessage.height + units.gu(2)
34 heroMessageHeader.titleText.text: title
35 heroMessageHeader.titleText.text: title
35− heroMessageHeader.subtitleText.text: time
36+ heroMessageHeader.subtitleText.text: timeFormatter.timeString
36 heroMessageHeader.bodyText.text: message
37 heroMessageHeader.bodyText.text: message
37
38
38 Item {
39 Item {
@@ -49,6 +50,12 @@ HeroMessage {
49 opacity: 0.0
50 opacity: 0.0
50 enabled: false
51 enabled: false
51
52
53+ TimeFormatter {
54+ id: timeFormatter
55+ time: __heroMessage.time
56+ format: "hh:mm - MMM dd"
57+ }
58+
52 Label {
59 Label {
53 id: bodyText
60 id: bodyText
54 anchors {
61 anchors {
plugins/Unity/Indicators/Messaging/qml/SnapDecision.qml+9−3
@@ -21,13 +21,13 @@
21import QtQuick 2.0
21import QtQuick 2.0
22import Ubuntu.Components 0.1
22import Ubuntu.Components 0.1
23import Unity.Indicators 0.1 as Indicators
23import Unity.Indicators 0.1 as Indicators
24−import "utils.js" as Utils
24+import Unity.Indicators 0.1
25
25
26HeroMessage {
26HeroMessage {
27 id: snapDecision
27 id: snapDecision
28
28
29 property string title: ""
29 property string title: ""
30− property string time: ""
30+ property var time
31 property string message: ""
31 property string message: ""
32
32
33 property bool activateEnabled: true
33 property bool activateEnabled: true
@@ -41,7 +41,7 @@ HeroMessage {
41 heroMessageHeader.titleText.text: title
41 heroMessageHeader.titleText.text: title
42 heroMessageHeader.subtitleText.text: message
42 heroMessageHeader.subtitleText.text: message
43 heroMessageHeader.subtitleText.color: "#e8e1d0"
43 heroMessageHeader.subtitleText.color: "#e8e1d0"
44− heroMessageHeader.bodyText.text: time
44+ heroMessageHeader.bodyText.text: timeFormatter.timeString
45 heroMessageHeader.bodyText.color: "#8f8f88"
45 heroMessageHeader.bodyText.color: "#8f8f88"
46
46
47 signal activate
47 signal activate
@@ -59,6 +59,12 @@ HeroMessage {
59 height: units.gu(4)
59 height: units.gu(4)
60 opacity: 0.0
60 opacity: 0.0
61
61
62+ TimeFormatter {
63+ id: timeFormatter
64+ time: snapDecision.time
65+ format: "hh:mm - MMM dd"
66+ }
67+
62 Button {
68 Button {
63 text: "Message"
69 text: "Message"
64 color: "#bababa"
70 color: "#bababa"
plugins/Unity/Indicators/plugin.cpp+2
@@ -33,6 +33,7 @@
33#include "unitymenumodelcache.h"
33#include "unitymenumodelcache.h"
34#include "unitymenumodelstack.h"
34#include "unitymenumodelstack.h"
35#include "visibleindicatorsmodel.h"
35#include "visibleindicatorsmodel.h"
36+#include "timeformatter.h"
36
37
37static QObject* menuModelCacheSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
38static QObject* menuModelCacheSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
38 Q_UNUSED(engine);
39 Q_UNUSED(engine);
@@ -51,6 +52,7 @@ void Indicators2Plugin::registerTypes(const char *uri)
51 qmlRegisterType<RootActionState>(uri, 0, 1, "RootActionState");
52 qmlRegisterType<RootActionState>(uri, 0, 1, "RootActionState");
52 qmlRegisterType<ModelPrinter>(uri, 0, 1, "ModelPrinter");
53 qmlRegisterType<ModelPrinter>(uri, 0, 1, "ModelPrinter");
53 qmlRegisterType<VisibleIndicatorsModel>(uri, 0, 1, "VisibleIndicatorsModel");
54 qmlRegisterType<VisibleIndicatorsModel>(uri, 0, 1, "VisibleIndicatorsModel");
55+ qmlRegisterType<TimeFormatter>(uri, 0, 1, "TimeFormatter");
54
56
55 qmlRegisterSingletonType<UnityMenuModelCache>(uri, 0, 1, "UnityMenuModelCache", menuModelCacheSingleton);
57 qmlRegisterSingletonType<UnityMenuModelCache>(uri, 0, 1, "UnityMenuModelCache", menuModelCacheSingleton);
56
58
plugins/Unity/Indicators/qml/IndicatorPage.qml+27−6
@@ -34,11 +34,36 @@ IndicatorBase {
34 Indicators.UnityMenuModelStack {
34 Indicators.UnityMenuModelStack {
35 id: menuStack
35 id: menuStack
36 head: contentActive ? main.menuModel : null
36 head: contentActive ? main.menuModel : null
37+
38+ property var rootMenu: null
39+
40+ onTailChanged: {
41+ if (!tail) {
42+ rootMenu = null;
43+ } else if (rootMenu != tail) {
44+ if (tail.get(0, "type") === rootMenuType) {
45+ rootMenu = menuStack.tail.submenu(0);
46+ push(rootMenu, 0);
47+ } else {
48+ rootMenu = null;
49+ }
50+ }
51+ }
52+ }
53+
54+ Connections {
55+ target: menuStack.tail
56+ onRowsInserted: {
57+ if (menuStack.rootMenu !== menuStack.tail && menuStack.tail.get(0, "type") === rootMenuType) {
58+ menuStack.rootMenu = menuStack.tail.submenu(0);
59+ menuStack.push(menuStack.rootMenu, 0);
60+ }
61+ }
37 }
62 }
38
63
39 ListView {
64 ListView {
40 id: mainMenu
65 id: mainMenu
41− model: menuStack.tail ? menuStack.tail : null
66+ model: menuStack.rootMenu
42
67
43 anchors {
68 anchors {
44 fill: parent
69 fill: parent
@@ -102,7 +127,7 @@ IndicatorBase {
102
127
103 Loader {
128 Loader {
104 id: loader
129 id: loader
105− asynchronous: true
130+ asynchronous: false
106
131
107 property int modelIndex: index
132 property int modelIndex: index
108
133
@@ -114,10 +139,6 @@ IndicatorBase {
114 sourceComponent: factory.load(model)
139 sourceComponent: factory.load(model)
115
140
116 onLoaded: {
141 onLoaded: {
117− if (model.type === rootMenuType) {
118− menuStack.push(mainMenu.model.submenu(index));
119− }
120−
121 if (item.hasOwnProperty("menuSelected")) {
142 if (item.hasOwnProperty("menuSelected")) {
122 item.menuSelected = mainMenu.selectedIndex == index;
143 item.menuSelected = mainMenu.selectedIndex == index;
123 item.selectMenu.connect(function() { mainMenu.selectedIndex = index; });
144 item.selectMenu.connect(function() { mainMenu.selectedIndex = index; });
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/timeformatter.cppnew file+172
@@ -0,0 +1,172 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Lars Uebernickel <lars.uebernickel@canonical.com>
17+ */
18+
19+#include "timeformatter.h"
20+
21+#include <gio/gio.h>
22+#include <QDateTime>
23+
24+struct TimeFormatterPrivate
25+{
26+ TimeFormatter *formatter;
27+
28+ QString format;
29+ QString timeString;
30+ qint64 time;
31+
32+ GDBusConnection *system_bus;
33+ guint subscription_id;
34+ GCancellable *cancellable;
35+};
36+
37+static void
38+timedate1_properties_changed (GDBusConnection *connection,
39+ const gchar *sender_name,
40+ const gchar *object_path,
41+ const gchar *interface_name,
42+ const gchar *signal_name,
43+ GVariant *parameters,
44+ gpointer user_data)
45+{
46+ Q_UNUSED(connection);
47+ Q_UNUSED(sender_name);
48+ Q_UNUSED(object_path);
49+ Q_UNUSED(interface_name);
50+ Q_UNUSED(signal_name);
51+
52+ TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
53+ GVariant *changed;
54+ GVariantIter *iter;
55+ const gchar *name;
56+
57+ if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa{sv}as)")))
58+ return;
59+
60+ g_variant_get (parameters, "(s@a{sv}as)", NULL, &changed, &iter);
61+
62+ if (g_variant_lookup (changed, "Timezone", "s", NULL)) {
63+ priv->formatter->update();
64+ }
65+ else {
66+ while (g_variant_iter_next (iter, "&s", &name)) {
67+ if (g_str_equal (name, "Timezone")) {
68+ priv->formatter->update();
69+ break;
70+ }
71+ }
72+ }
73+
74+ g_variant_unref (changed);
75+ g_variant_iter_free (iter);
76+}
77+
78+static void
79+got_bus(GObject *object, GAsyncResult *result, gpointer user_data)
80+{
81+ Q_UNUSED(object);
82+
83+ TimeFormatterPrivate *priv = (TimeFormatterPrivate *)user_data;
84+ GError *error = NULL;
85+
86+ priv->system_bus = g_bus_get_finish (result, &error);
87+ if (priv->system_bus == NULL) {
88+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
89+ qWarning("TimeFormatter: cannot connect to the system bus: %s", error->message);
90+ g_error_free (error);
91+ return;
92+ }
93+
94+ /* Listen to the PropertiesChanged on the org.freedesktop.timedate1
95+ * interface from any sender. In practice, this signal will only be sent
96+ * from timedated (we can trust other processes on the system bus to behave
97+ * nicely). That way, we don't have to watch timedated's well-known name
98+ * and keep the process alive.
99+ */
100+ priv->subscription_id = g_dbus_connection_signal_subscribe (priv->system_bus,
101+ NULL, /* sender */
102+ "org.freedesktop.DBus.Properties",
103+ "PropertiesChanged",
104+ NULL,
105+ "org.freedesktop.timedate1",
106+ G_DBUS_SIGNAL_FLAGS_NONE,
107+ timedate1_properties_changed,
108+ priv, NULL);
109+}
110+
111+TimeFormatter::TimeFormatter(QObject *parent): QObject(parent)
112+{
113+ priv = new TimeFormatterPrivate;
114+ priv->formatter = this;
115+ priv->time = 0;
116+ priv->format = "yyyy-MM-dd hh:mm";
117+ priv->system_bus = NULL;
118+ priv->subscription_id = 0;
119+ priv->cancellable = g_cancellable_new ();
120+
121+ g_bus_get (G_BUS_TYPE_SYSTEM, priv->cancellable, got_bus, priv);
122+}
123+
124+TimeFormatter::~TimeFormatter()
125+{
126+ if (priv->system_bus) {
127+ g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->subscription_id);
128+ g_object_unref (priv->system_bus);
129+ }
130+
131+ g_cancellable_cancel (priv->cancellable);
132+ g_object_unref (priv->cancellable);
133+}
134+
135+QString TimeFormatter::format() const
136+{
137+ return priv->format;
138+}
139+
140+QString TimeFormatter::timeString() const
141+{
142+ return priv->timeString;
143+}
144+
145+qint64 TimeFormatter::time() const
146+{
147+ return priv->time;
148+}
149+
150+void TimeFormatter::setFormat(const QString &format)
151+{
152+ if (priv->format != format) {
153+ priv->format = format;
154+ Q_EMIT formatChanged(priv->format);
155+ update();
156+ }
157+}
158+
159+void TimeFormatter::setTime(qint64 time)
160+{
161+ if (priv->time != time) {
162+ priv->time = time;
163+ Q_EMIT timeChanged(priv->time);
164+ update();
165+ }
166+}
167+
168+void TimeFormatter::update()
169+{
170+ priv->timeString = QDateTime::fromMSecsSinceEpoch(priv->time / 1000).toString(priv->format);
171+ Q_EMIT timeStringChanged(priv->timeString);
172+}
plugins/Unity/Indicators/timeformatter.hnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Lars Uebernickel <lars.uebernickel@canonical.com>
17+ */
18+
19+#ifndef TIME_FORMATTER_H
20+#define TIME_FORMATTER_H
21+
22+#include "unityindicatorsglobal.h"
23+#include <QObject>
24+
25+class UNITYINDICATORS_EXPORT TimeFormatter : public QObject
26+{
27+ Q_OBJECT
28+ Q_PROPERTY(QString format READ format WRITE setFormat NOTIFY formatChanged)
29+ Q_PROPERTY(QString timeString READ timeString NOTIFY timeStringChanged)
30+ Q_PROPERTY(qint64 time READ time WRITE setTime NOTIFY timeChanged)
31+
32+public:
33+ TimeFormatter(QObject *parent = 0);
34+ ~TimeFormatter();
35+
36+ QString format() const;
37+ QString timeString() const;
38+ qint64 time() const;
39+
40+ void setFormat(const QString &format);
41+ void setTime(qint64 time);
42+
43+ void update();
44+
45+Q_SIGNALS:
46+ void formatChanged(const QString &format);
47+ void timeStringChanged(const QString &timeString);
48+ void timeChanged(qint64 time);
49+
50+private:
51+ struct TimeFormatterPrivate *priv;
52+};
53+
54+#endif
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
plugins/Unity/Launcher/launcheritem.cpp+4−2
@@ -20,6 +20,8 @@
20#include "launcheritem.h"
20#include "launcheritem.h"
21#include "quicklistmodel.h"
21#include "quicklistmodel.h"
22
22
23+#include <libintl.h>
24+
23LauncherItem::LauncherItem(const QString &appId, const QString &name, const QString &icon, QObject *parent) :
25LauncherItem::LauncherItem(const QString &appId, const QString &name, const QString &icon, QObject *parent) :
24 LauncherItemInterface(parent),
26 LauncherItemInterface(parent),
25 m_appId(appId),
27 m_appId(appId),
@@ -38,7 +40,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
38 m_quickList->appendAction(nameAction);
40 m_quickList->appendAction(nameAction);
39 QuickListEntry pinningAction;
41 QuickListEntry pinningAction;
40 pinningAction.setActionId("pin_item");
42 pinningAction.setActionId("pin_item");
41− pinningAction.setText("Pin to Launcher");
43+ pinningAction.setText(gettext("Lock to Launcher"));
42 m_quickList->appendAction(pinningAction);
44 m_quickList->appendAction(pinningAction);
43}
45}
44
46
@@ -68,7 +70,7 @@ void LauncherItem::setPinned(bool pinned)
68 m_pinned = pinned;
70 m_pinned = pinned;
69 QuickListEntry entry;
71 QuickListEntry entry;
70 entry.setActionId("pin_item");
72 entry.setActionId("pin_item");
71− entry.setText(pinned ? "Remove from Launcher": "Pin to Launcher");
73+ entry.setText(pinned ? gettext("Unlock from Launcher") : gettext("Lock to Launcher"));
72 m_quickList->updateAction(entry);
74 m_quickList->updateAction(entry);
73 Q_EMIT pinnedChanged(pinned);
75 Q_EMIT pinnedChanged(pinned);
74 }
76 }
plugins/Unity/iconutils.cpp+10−10
@@ -17,11 +17,13 @@
17 * Michal Hruby <michal.hruby@canonical.com>
17 * Michal Hruby <michal.hruby@canonical.com>
18 */
18 */
19
19
20−#include <QStringList>
20+#include "iconutils.h"
21−#include <QUrl>
22
21
23#include <gio/gio.h>
22#include <gio/gio.h>
23+
24−#include "iconutils.h"
24+#include <QStringList>
25+#include <QUrl>
26+#include <QUrlQuery>
25
27
26#define BASE_THEME_ICON_URI "image://theme/"
28#define BASE_THEME_ICON_URI "image://theme/"
27#define BASE_THUMBNAILER_URI "image://thumbnailer/"
29#define BASE_THUMBNAILER_URI "image://thumbnailer/"
@@ -104,13 +106,11 @@ QString uriToThumbnailerProviderString(QString const &uri, QString const &mimety
104 if (contentHash.contains("content")) { // nested content in Home?
106 if (contentHash.contains("content")) { // nested content in Home?
105 contentHash = contentHash["content"].toHash();
107 contentHash = contentHash["content"].toHash();
106 }
108 }
107− if (contentHash.contains("album") &&
109+ if (contentHash.contains("album") && contentHash.contains("artist")) {
108− contentHash.contains("artist")) {
110+ QUrlQuery query;
109− const QString album = contentHash["album"].toString();
111+ query.addQueryItem(QStringLiteral("artist"), contentHash["artist"].toString());
110− const QString artist = contentHash["artist"].toString();
112+ query.addQueryItem(QStringLiteral("album"), contentHash["album"].toString());
111− thumbnailerUri.append(QUrl::toPercentEncoding(artist));
112− thumbnailerUri.append("/");
113+ thumbnailerUri.append(query.toString());
113− thumbnailerUri.append(QUrl::toPercentEncoding(album));
114 }
114 }
115 }
115 }
116 } else {
116 } else {
plugins/Unity/plugin.cpp−12
@@ -17,8 +17,6 @@
17 */
17 */
18
18
19// Qt
19// Qt
20−#include <QDBusConnection>
21−#include <QQmlContext>
22#include <qqml.h>
20#include <qqml.h>
23
21
24// self
22// self
@@ -33,16 +31,12 @@
33#include "scopes.h"
31#include "scopes.h"
34#include "categories.h"
32#include "categories.h"
35#include "categoryresults.h"
33#include "categoryresults.h"
36−#include "bottombarvisibilitycommunicatorshell.h"
37#include "genericoptionsmodel.h"
34#include "genericoptionsmodel.h"
38#include "result.h"
35#include "result.h"
39
36
40// libqtdee
37// libqtdee
41#include "deelistmodel.h"
38#include "deelistmodel.h"
42
39
43−static const char* BOTTOM_BAR_VISIBILITY_COMMUNICATOR_DBUS_PATH = "/BottomBarVisibilityCommunicator";
44−static const char* DBUS_SERVICE = "com.canonical.Shell.BottomBarVisibilityCommunicator";
45−
46void UnityPlugin::registerTypes(const char *uri)
40void UnityPlugin::registerTypes(const char *uri)
47{
41{
48 Q_ASSERT(uri == QLatin1String("Unity"));
42 Q_ASSERT(uri == QLatin1String("Unity"));
@@ -57,7 +51,6 @@ void UnityPlugin::registerTypes(const char *uri)
57 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
51 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
58 qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create new Category Results in QML. Get them from Categories instance.");
52 qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create new Category Results in QML. Get them from Categories instance.");
59 qmlRegisterType<DeeListModel>(uri, 0, 1, "DeeListModel");
53 qmlRegisterType<DeeListModel>(uri, 0, 1, "DeeListModel");
60− qmlRegisterUncreatableType<BottomBarVisibilityCommunicatorShell>(uri, 0, 1, "BottomBarVisibilityCommunicatorShell", "Can't create BottomBarVisibilityCommunicatorShell");
61}
54}
62
55
63void UnityPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
56void UnityPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
@@ -66,9 +59,4 @@ void UnityPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
66#ifndef GLIB_VERSION_2_36
59#ifndef GLIB_VERSION_2_36
67 g_type_init();
60 g_type_init();
68#endif
61#endif
69−
70− QDBusConnection::sessionBus().registerService(DBUS_SERVICE);
71− BottomBarVisibilityCommunicatorShell *bottomBarVisibilityCommunicator = &BottomBarVisibilityCommunicatorShell::instance();
72− QDBusConnection::sessionBus().registerObject(BOTTOM_BAR_VISIBILITY_COMMUNICATOR_DBUS_PATH, bottomBarVisibilityCommunicator, QDBusConnection::ExportAllContents);
73− engine->rootContext()->setContextProperty("bottomBarVisibilityCommunicatorShell", bottomBarVisibilityCommunicator);
74}
62}
plugins/Utils/CMakeLists.txt+1
@@ -13,6 +13,7 @@ include_directories(
13set(QMLPLUGIN_SRC
13set(QMLPLUGIN_SRC
14 albumartprovider.cpp
14 albumartprovider.cpp
15 applicationpaths.h
15 applicationpaths.h
16+ bottombarvisibilitycommunicatorshell.cpp
16 mediaartcache.cpp
17 mediaartcache.cpp
17 qlimitproxymodelqml.cpp
18 qlimitproxymodelqml.cpp
18 qsortfilterproxymodelqml.cpp
19 qsortfilterproxymodelqml.cpp
plugins/Utils/albumartprovider.cpp+10−7
@@ -32,6 +32,7 @@
32#include <QByteArray>
32#include <QByteArray>
33#include <QImage>
33#include <QImage>
34#include <QUrl>
34#include <QUrl>
35+#include <QUrlQuery>
35
36
36using namespace std;
37using namespace std;
37
38
@@ -65,6 +66,9 @@ AlbumArtProvider::~AlbumArtProvider()
65std::string AlbumArtProvider::get_lastfm_url(const albuminfo &ai) {
66std::string AlbumArtProvider::get_lastfm_url(const albuminfo &ai) {
66 QString artist = QString::fromStdString(ai.artist);
67 QString artist = QString::fromStdString(ai.artist);
67 QString album = QString::fromStdString(ai.album);
68 QString album = QString::fromStdString(ai.album);
69+ // audioscrobbler wants it without any / (as it would break the URL)
70+ artist.remove('/');
71+ album.remove('/');
68
72
69 /// @todo: this is the old API which will probably get axed at some point in the future
73 /// @todo: this is the old API which will probably get axed at some point in the future
70 /// The new 2.0 API requires an API key, but supports JSON output, etc, so switching
74 /// The new 2.0 API requires an API key, but supports JSON output, etc, so switching
@@ -200,21 +204,20 @@ std::string AlbumArtProvider::get_image(const std::string &artist, const std::st
200QImage AlbumArtProvider::requestImage(const QString &id, QSize *realSize, const QSize &requestedSize) {
204QImage AlbumArtProvider::requestImage(const QString &id, QSize *realSize, const QSize &requestedSize) {
201 Q_UNUSED(requestedSize)
205 Q_UNUSED(requestedSize)
202
206
203− const QStringList parts = id.split("/");
207+ QUrlQuery query(id);
204− if (parts.size() != 2) {
208+ if (!query.hasQueryItem(QStringLiteral("artist")) || !query.hasQueryItem(QStringLiteral("album"))) {
205 qWarning() << "Invalid albumart uri:" << id;
209 qWarning() << "Invalid albumart uri:" << id;
206 return QImage(QString::fromStdString(DEFAULT_ALBUM_ART));
210 return QImage(QString::fromStdString(DEFAULT_ALBUM_ART));
207 }
211 }
208− const std::string artist = QUrl::fromPercentEncoding(parts[0].toUtf8()).toStdString();
212+ const QString artist = query.queryItemValue(QStringLiteral("artist"), QUrl::FullyEncoded);
209− const std::string album = QUrl::fromPercentEncoding(parts[1].toUtf8()).toStdString();
213+ const QString album = query.queryItemValue(QStringLiteral("album"), QUrl::FullyEncoded);
210
214
211 std::string tgt_path;
215 std::string tgt_path;
212 try {
216 try {
213− tgt_path = get_image(artist, album);
217+ tgt_path = get_image(artist.toStdString(), album.toStdString());
214 if(!tgt_path.empty()) {
218 if(!tgt_path.empty()) {
215− QString tgt(tgt_path.c_str());
216 QImage image;
219 QImage image;
217− image.load(tgt);
220+ image.load(QString::fromStdString(tgt_path));
218 // FIXME: Rescale to requested size preserving aspect.
221 // FIXME: Rescale to requested size preserving aspect.
219 *realSize = image.size();
222 *realSize = image.size();
220 return image;
223 return image;
plugins/Unity/bottombarvisibilitycommunicatorshell.cpp → plugins/Utils/bottombarvisibilitycommunicatorshell.cpprenamed

The content is the same.

plugins/Unity/bottombarvisibilitycommunicatorshell.h → plugins/Utils/bottombarvisibilitycommunicatorshell.hrenamed

The content is the same.

plugins/Utils/plugin.cpp+12
@@ -18,6 +18,8 @@
18
18
19// Qt
19// Qt
20#include <QtQml/qqml.h>
20#include <QtQml/qqml.h>
21+#include <QDBusConnection>
22+#include <QQmlContext>
21#include <QtQuick/QQuickWindow>
23#include <QtQuick/QQuickWindow>
22#include <QDebug>
24#include <QDebug>
23// self
25// self
@@ -26,11 +28,15 @@
26// local
28// local
27#include "albumartprovider.h"
29#include "albumartprovider.h"
28#include "applicationpaths.h"
30#include "applicationpaths.h"
31+#include "bottombarvisibilitycommunicatorshell.h"
29#include "qlimitproxymodelqml.h"
32#include "qlimitproxymodelqml.h"
30#include "qsortfilterproxymodelqml.h"
33#include "qsortfilterproxymodelqml.h"
31#include "ubuntuwindow.h"
34#include "ubuntuwindow.h"
32#include "unitymenumodelpaths.h"
35#include "unitymenumodelpaths.h"
33
36
37+static const char* BOTTOM_BAR_VISIBILITY_COMMUNICATOR_DBUS_PATH = "/BottomBarVisibilityCommunicator";
38+static const char* DBUS_SERVICE = "com.canonical.Shell.BottomBarVisibilityCommunicator";
39+
34static QObject* applicationsPathsSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
40static QObject* applicationsPathsSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
35 Q_UNUSED(engine);
41 Q_UNUSED(engine);
36 Q_UNUSED(scriptEngine);
42 Q_UNUSED(scriptEngine);
@@ -46,6 +52,7 @@ void UtilsPlugin::registerTypes(const char *uri)
46 qmlRegisterType<UnityMenuModelPaths>(uri, 0, 1, "UnityMenuModelPaths");
52 qmlRegisterType<UnityMenuModelPaths>(uri, 0, 1, "UnityMenuModelPaths");
47 qmlRegisterExtendedType<QQuickWindow, UbuntuWindow>(uri, 0, 1, "Window");
53 qmlRegisterExtendedType<QQuickWindow, UbuntuWindow>(uri, 0, 1, "Window");
48 qmlRegisterSingletonType<ApplicationPaths>(uri, 0, 1, "ApplicationPaths", applicationsPathsSingleton);
54 qmlRegisterSingletonType<ApplicationPaths>(uri, 0, 1, "ApplicationPaths", applicationsPathsSingleton);
55+ qmlRegisterUncreatableType<BottomBarVisibilityCommunicatorShell>(uri, 0, 1, "BottomBarVisibilityCommunicatorShell", "Can't create BottomBarVisibilityCommunicatorShell");
49}
56}
50
57
51void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
58void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
@@ -64,4 +71,9 @@ void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
64 {
71 {
65 qWarning() << "Failed to register image provider for albumart (unknown error)";
72 qWarning() << "Failed to register image provider for albumart (unknown error)";
66 }
73 }
74+
75+ QDBusConnection::sessionBus().registerService(DBUS_SERVICE);
76+ BottomBarVisibilityCommunicatorShell *bottomBarVisibilityCommunicator = &BottomBarVisibilityCommunicatorShell::instance();
77+ QDBusConnection::sessionBus().registerObject(BOTTOM_BAR_VISIBILITY_COMMUNICATOR_DBUS_PATH, bottomBarVisibilityCommunicator, QDBusConnection::ExportAllContents);
78+ engine->rootContext()->setContextProperty("bottomBarVisibilityCommunicatorShell", bottomBarVisibilityCommunicator);
67}
79}
po/ar.po+23−10
@@ -7,8 +7,8 @@ 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-12 16:10+0100\n"
11−"PO-Revision-Date: 2013-10-20 19:41+0000\n"
11+"PO-Revision-Date: 2013-11-15 12:29+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"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16807)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "ويكيبيديا"
87msgid "YouTube"
87msgid "YouTube"
88msgstr "يوتيوب"
88msgstr "يوتيوب"
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr "تخطي المقدمة"
92msgstr "تخطي المقدمة"
93
93
@@ -136,7 +136,7 @@ msgstr ""
136"لقد أتقنت الآن إيماءات الحواف ويمكنك البدء باستخدام الهاتف<br><br>انقر في أي "
136"لقد أتقنت الآن إيماءات الحواف ويمكنك البدء باستخدام الهاتف<br><br>انقر في أي "
137"مكان للبدء"
137"مكان للبدء"
138
138
139−#: Components/PageHeader.qml:341
139+#: Components/PageHeader.qml:345
140msgid "Recent searches"
140msgid "Recent searches"
141msgstr "عمليات البحث الأخيرة"
141msgstr "عمليات البحث الأخيرة"
142
142
@@ -160,7 +160,7 @@ msgstr[3] "%1 تعليقات"
160msgstr[4] "%1 تعليقا"
160msgstr[4] "%1 تعليقا"
161msgstr[5] "%1 تعليق"
161msgstr[5] "%1 تعليق"
162
162
163−#: Dash/Apps/AppPreview.qml:126
163+#: Dash/Apps/AppPreview.qml:135
164msgid "Rate this"
164msgid "Rate this"
165msgstr "قيّم ذلك"
165msgstr "قيّم ذلك"
166
166
@@ -180,7 +180,7 @@ msgstr "أرسل"
180msgid "Comments:"
180msgid "Comments:"
181msgstr "التعليقات:"
181msgstr "التعليقات:"
182
182
183−#: Greeter/Lockscreen.qml:142
183+#: Greeter/Lockscreen.qml:146
184msgid "Emergency Call"
184msgid "Emergency Call"
185msgstr "مكالمة طوارئ"
185msgstr "مكالمة طوارئ"
186
186
@@ -213,11 +213,24 @@ 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/Launcher/launcheritem.cpp:43
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Lock to Launcher"
227+msgstr ""
228+
229+#: plugins/Unity/Launcher/launcheritem.cpp:73
230+msgid "Unlock from Launcher"
231+msgstr ""
232+
233+#: plugins/Unity/scope.cpp:408
221msgid "Sorry, there is nothing that matches your search."
234msgid "Sorry, there is nothing that matches your search."
222msgstr "عذراً، لا يوجد ما يطابق بحثك."
235msgstr "عذراً، لا يوجد ما يطابق بحثك."
223
236
@@ -225,7 +238,7 @@ msgstr "عذراً، لا يوجد ما يطابق بحثك."
225msgid "All"
238msgid "All"
226msgstr "الكل"
239msgstr "الكل"
227
240
228−#: Shell.qml:438
241+#: Shell.qml:441
229#, qt-format
242#, qt-format
230msgid "Please enter %1"
243msgid "Please enter %1"
231msgstr "من فضلك أدخِل %1"
244msgstr "من فضلك أدخِل %1"
po/ast.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Omitir la intro"
91msgstr "Omitir la intro"
92
92
@@ -136,7 +136,7 @@ msgstr ""
136"Agora domines los xestos de berbesos y pues usar el teléfonu<br><br>Toca la "
136"Agora domines los xestos de berbesos y pues usar el teléfonu<br><br>Toca la "
137"pantalla pa entamar"
137"pantalla pa entamar"
138
138
139−#: Components/PageHeader.qml:341
139+#: Components/PageHeader.qml:345
140msgid "Recent searches"
140msgid "Recent searches"
141msgstr "Busques recientes"
141msgstr "Busques recientes"
142
142
@@ -156,7 +156,7 @@ msgid_plural "%1 reviews"
156msgstr[0] "%1 reseña"
156msgstr[0] "%1 reseña"
157msgstr[1] "%1 reseñes"
157msgstr[1] "%1 reseñes"
158
158
159−#: Dash/Apps/AppPreview.qml:126
159+#: Dash/Apps/AppPreview.qml:135
160msgid "Rate this"
160msgid "Rate this"
161msgstr "Valorar esto"
161msgstr "Valorar esto"
162
162
@@ -176,7 +176,7 @@ msgstr "Unviar"
176msgid "Comments:"
176msgid "Comments:"
177msgstr "Comentarios:"
177msgstr "Comentarios:"
178
178
179−#: Greeter/Lockscreen.qml:142
179+#: Greeter/Lockscreen.qml:146
180msgid "Emergency Call"
180msgid "Emergency Call"
181msgstr "Llamada d'emerxencia"
181msgstr "Llamada d'emerxencia"
182
182
@@ -209,11 +209,24 @@ 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/Launcher/launcheritem.cpp:43
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Lock to Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Unlock from Launcher"
227+msgstr ""
228+
229+#: plugins/Unity/scope.cpp:408
217msgid "Sorry, there is nothing that matches your search."
230msgid "Sorry, there is nothing that matches your search."
218msgstr "Sentímoslo, nun hai res que concase cola gueta"
231msgstr "Sentímoslo, nun hai res que concase cola gueta"
219
232
@@ -221,28 +234,7 @@ msgstr "Sentímoslo, nun hai res que concase cola gueta"
221msgid "All"
234msgid "All"
222msgstr "Too"
235msgstr "Too"
223
236
224−#: Shell.qml:438
237+#: Shell.qml:441
225#, qt-format
238#, qt-format
226msgid "Please enter %1"
239msgid "Please enter %1"
227msgstr "Introduz %1"
240msgstr "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+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Son axtarışlar"
137msgstr "Son axtarışlar"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
227msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
215
228
@@ -217,13 +230,7 @@ msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Musiqi"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Videolar"
po/bg.po+22−21
@@ -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-12 16:10+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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Уикипедия"
87msgid "YouTube"
87msgid "YouTube"
88msgstr "YouTube"
88msgstr "YouTube"
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr ""
92msgstr ""
93
93
@@ -133,7 +133,7 @@ msgid ""
133"phone<br><br>Tap anywhere to start"
133"phone<br><br>Tap anywhere to start"
134msgstr ""
134msgstr ""
135
135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137msgid "Recent searches"
137msgid "Recent searches"
138msgstr "Скорошни търсения"
138msgstr "Скорошни търсения"
139
139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153msgstr[0] ""
153msgstr[0] ""
154msgstr[1] ""
154msgstr[1] ""
155
155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157msgid "Rate this"
157msgid "Rate this"
158msgstr ""
158msgstr ""
159
159
@@ -173,7 +173,7 @@ msgstr ""
173msgid "Comments:"
173msgid "Comments:"
174msgstr ""
174msgstr ""
175
175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177msgid "Emergency Call"
177msgid "Emergency Call"
178msgstr ""
178msgstr ""
179
179
@@ -206,11 +206,24 @@ 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/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
227msgid "Sorry, there is nothing that matches your search."
215msgstr "Съжаляваме, няма нищо, което да отговаря на вашето търсене."
228msgstr "Съжаляваме, няма нищо, което да отговаря на вашето търсене."
216
229
@@ -218,19 +231,7 @@ msgstr "Съжаляваме, няма нищо, което да отговар
218msgid "All"
231msgid "All"
219msgstr ""
232msgstr ""
220
233
221−#: Shell.qml:438
234+#: Shell.qml:441
222#, qt-format
235#, qt-format
223msgid "Please enter %1"
236msgid "Please enter %1"
224msgstr ""
237msgstr ""
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+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Viquipèdia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Omet la introducció"
91msgstr "Omet la introducció"
92
92
@@ -138,7 +138,7 @@ msgid ""
138"phone<br><br>Tap anywhere to start"
138"phone<br><br>Tap anywhere to start"
139msgstr ""
139msgstr ""
140
140
141−#: Components/PageHeader.qml:341
141+#: Components/PageHeader.qml:345
142msgid "Recent searches"
142msgid "Recent searches"
143msgstr "Cerques recents"
143msgstr "Cerques recents"
144
144
@@ -158,7 +158,7 @@ msgid_plural "%1 reviews"
158msgstr[0] "%1 ressenya"
158msgstr[0] "%1 ressenya"
159msgstr[1] "%1 ressenyes"
159msgstr[1] "%1 ressenyes"
160
160
161−#: Dash/Apps/AppPreview.qml:126
161+#: Dash/Apps/AppPreview.qml:135
162msgid "Rate this"
162msgid "Rate this"
163msgstr ""
163msgstr ""
164
164
@@ -178,7 +178,7 @@ msgstr "Envia"
178msgid "Comments:"
178msgid "Comments:"
179msgstr "Comentaris:"
179msgstr "Comentaris:"
180
180
181−#: Greeter/Lockscreen.qml:142
181+#: Greeter/Lockscreen.qml:146
182msgid "Emergency Call"
182msgid "Emergency Call"
183msgstr "Trucada d'emergència"
183msgstr "Trucada d'emergència"
184
184
@@ -211,11 +211,24 @@ 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/Launcher/launcheritem.cpp:43
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Lock to Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/Launcher/launcheritem.cpp:73
228+msgid "Unlock from Launcher"
229+msgstr ""
230+
231+#: plugins/Unity/scope.cpp:408
219msgid "Sorry, there is nothing that matches your search."
232msgid "Sorry, there is nothing that matches your search."
220msgstr "No hi ha res que coincideixi amb la cerca"
233msgstr "No hi ha res que coincideixi amb la cerca"
221
234
@@ -223,28 +236,7 @@ msgstr "No hi ha res que coincideixi amb la cerca"
223msgid "All"
236msgid "All"
224msgstr ""
237msgstr ""
225
238
226−#: Shell.qml:438
239+#: Shell.qml:441
227#, qt-format
240#, qt-format
228msgid "Please enter %1"
241msgid "Please enter %1"
229msgstr "Introduïu %1"
242msgstr "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+22−24
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedie"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Přeskočit intro"
91msgstr "Přeskočit intro"
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Poslední vyhledávání"
137msgstr "Poslední vyhledávání"
138
138
@@ -153,7 +153,7 @@ msgstr[0] "%1 recenze"
153msgstr[1] "%1 recenze"
153msgstr[1] "%1 recenze"
154msgstr[2] "%1 recenzí"
154msgstr[2] "%1 recenzí"
155
155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157msgid "Rate this"
157msgid "Rate this"
158msgstr "Ohodnoťte to"
158msgstr "Ohodnoťte to"
159
159
@@ -173,7 +173,7 @@ msgstr "Odeslat"
173msgid "Comments:"
173msgid "Comments:"
174msgstr "Komentáře:"
174msgstr "Komentáře:"
175
175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177msgid "Emergency Call"
177msgid "Emergency Call"
178msgstr "Tísňové volání"
178msgstr "Tísňové volání"
179
179
@@ -206,11 +206,24 @@ 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/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
227msgid "Sorry, there is nothing that matches your search."
215msgstr "Je nám líto, ale nic neodpovídá zadání"
228msgstr "Je nám líto, ale nic neodpovídá zadání"
216
229
@@ -218,22 +231,7 @@ msgstr "Je nám líto, ale nic neodpovídá zadání"
218msgid "All"
231msgid "All"
219msgstr "Vše"
232msgstr "Vše"
220
233
221−#: Shell.qml:438
234+#: Shell.qml:441
222#, qt-format
235#, qt-format
223msgid "Please enter %1"
236msgid "Please enter %1"
224msgstr "Zadejte prosím %1"
237msgstr "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+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16807)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Überspringe Einführung"
91msgstr "Überspringe Einführung"
92
92
@@ -136,7 +136,7 @@ msgstr ""
136"Sie haben nun die Einführung abgeschlossen und können Ihr Gerät nun "
136"Sie haben nun die Einführung abgeschlossen und können Ihr Gerät nun "
137"verwenden<br><br>Antippen um zu starten"
137"verwenden<br><br>Antippen um zu starten"
138
138
139−#: Components/PageHeader.qml:341
139+#: Components/PageHeader.qml:345
140msgid "Recent searches"
140msgid "Recent searches"
141msgstr "Letzte Suchbegriffe"
141msgstr "Letzte Suchbegriffe"
142
142
@@ -156,7 +156,7 @@ msgid_plural "%1 reviews"
156msgstr[0] "%1 Bewertung"
156msgstr[0] "%1 Bewertung"
157msgstr[1] "%1 Bewertungen"
157msgstr[1] "%1 Bewertungen"
158
158
159−#: Dash/Apps/AppPreview.qml:126
159+#: Dash/Apps/AppPreview.qml:135
160msgid "Rate this"
160msgid "Rate this"
161msgstr "Bewerten"
161msgstr "Bewerten"
162
162
@@ -176,7 +176,7 @@ msgstr "Senden"
176msgid "Comments:"
176msgid "Comments:"
177msgstr "Kommentare:"
177msgstr "Kommentare:"
178
178
179−#: Greeter/Lockscreen.qml:142
179+#: Greeter/Lockscreen.qml:146
180msgid "Emergency Call"
180msgid "Emergency Call"
181msgstr "Notruf"
181msgstr "Notruf"
182
182
@@ -209,11 +209,24 @@ 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/Launcher/launcheritem.cpp:43
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Lock to Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Unlock from Launcher"
227+msgstr ""
228+
229+#: plugins/Unity/scope.cpp:408
217msgid "Sorry, there is nothing that matches your search."
230msgid "Sorry, there is nothing that matches your search."
218msgstr "Entschuldigung, es wurden keine Treffer erzielt."
231msgstr "Entschuldigung, es wurden keine Treffer erzielt."
219
232
@@ -221,7 +234,7 @@ msgstr "Entschuldigung, es wurden keine Treffer erzielt."
221msgid "All"
234msgid "All"
222msgstr "Alle"
235msgstr "Alle"
223
236
224−#: Shell.qml:438
237+#: Shell.qml:441
225#, qt-format
238#, qt-format
226msgid "Please enter %1"
239msgid "Please enter %1"
227msgstr "Bitte geben Sie %1 ein"
240msgstr "Bitte geben Sie %1 ein"
po/el.po+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Πρόσφατες αναζητήσεις"
137msgstr "Πρόσφατες αναζητήσεις"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να ταιριάζει στην αναζήτησή σας."
227msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να ταιριάζει στην αναζήτησή σας."
215
228
@@ -217,13 +230,7 @@ msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να τ
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Μουσική"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Βίντεο"
po/en_AU.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Skip intro"
91msgstr "Skip intro"
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Recent searches"
137msgstr "Recent searches"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] "%1 review"
152msgstr[0] "%1 review"
153msgstr[1] "%1 reviews"
153msgstr[1] "%1 reviews"
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr "Rate this"
157msgstr "Rate this"
158
158
@@ -172,7 +172,7 @@ msgstr "Send"
172msgid "Comments:"
172msgid "Comments:"
173msgstr "Comments:"
173msgstr "Comments:"
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr "Emergency Call"
177msgstr "Emergency Call"
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Sorry, there is nothing that matches your search."
227msgstr "Sorry, there is nothing that matches your search."
215
228
@@ -217,28 +230,7 @@ msgstr "Sorry, there is nothing that matches your search."
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr "Please enter %1"
236msgstr "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+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Recent searches"
137msgstr "Recent searches"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Sorry, there is nothing that matches your search."
227msgstr "Sorry, there is nothing that matches your search."
215
228
@@ -217,28 +230,7 @@ msgstr "Sorry, there is nothing that matches your search."
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr "Please enter %1"
236msgstr "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+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,7 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
po/es.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Omitir la introducción"
91msgstr "Omitir la introducción"
92
92
@@ -136,7 +136,7 @@ msgstr ""
136"Ahora domina los gestos de bordes y puede usar el teléfono<br><br>Toque la "
136"Ahora domina los gestos de bordes y puede usar el teléfono<br><br>Toque la "
137"pantalla para comenzar"
137"pantalla para comenzar"
138
138
139−#: Components/PageHeader.qml:341
139+#: Components/PageHeader.qml:345
140msgid "Recent searches"
140msgid "Recent searches"
141msgstr "Búsquedas recientes"
141msgstr "Búsquedas recientes"
142
142
@@ -156,7 +156,7 @@ msgid_plural "%1 reviews"
156msgstr[0] "%1 reseña"
156msgstr[0] "%1 reseña"
157msgstr[1] "%1 reseñas"
157msgstr[1] "%1 reseñas"
158
158
159−#: Dash/Apps/AppPreview.qml:126
159+#: Dash/Apps/AppPreview.qml:135
160msgid "Rate this"
160msgid "Rate this"
161msgstr "Valorar esto"
161msgstr "Valorar esto"
162
162
@@ -176,7 +176,7 @@ msgstr "Enviar"
176msgid "Comments:"
176msgid "Comments:"
177msgstr "Comentarios:"
177msgstr "Comentarios:"
178
178
179−#: Greeter/Lockscreen.qml:142
179+#: Greeter/Lockscreen.qml:146
180msgid "Emergency Call"
180msgid "Emergency Call"
181msgstr "Llamada de emergencia"
181msgstr "Llamada de emergencia"
182
182
@@ -209,11 +209,24 @@ 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/Launcher/launcheritem.cpp:43
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Lock to Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Unlock from Launcher"
227+msgstr ""
228+
229+#: plugins/Unity/scope.cpp:408
217msgid "Sorry, there is nothing that matches your search."
230msgid "Sorry, there is nothing that matches your search."
218msgstr "No hay nada que coincida con su búsqueda."
231msgstr "No hay nada que coincida con su búsqueda."
219
232
@@ -221,28 +234,7 @@ msgstr "No hay nada que coincida con su búsqueda."
221msgid "All"
234msgid "All"
222msgstr "Todo"
235msgstr "Todo"
223
236
224−#: Shell.qml:438
237+#: Shell.qml:441
225#, qt-format
238#, qt-format
226msgid "Please enter %1"
239msgid "Please enter %1"
227msgstr "Introduzca %1"
240msgstr "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.ponew file+236
@@ -0,0 +1,236 @@
1+# Persian translation for unity8
2+# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
3+# This file is distributed under the same license as the unity8 package.
4+# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
5+#
6+msgid ""
7+msgstr ""
8+"Project-Id-Version: unity8\n"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
11+"PO-Revision-Date: 2013-10-31 19:02+0000\n"
12+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13+"Language-Team: Persian <fa@li.org>\n"
14+"MIME-Version: 1.0\n"
15+"Content-Type: text/plain; charset=UTF-8\n"
16+"Content-Transfer-Encoding: 8bit\n"
17+"Plural-Forms: nplurals=1; plural=0;\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
20+
21+#: Applications/applications.js:23
22+msgid "Phone"
23+msgstr ""
24+
25+#: Applications/applications.js:29
26+msgid "Camera"
27+msgstr ""
28+
29+#: Applications/applications.js:35
30+msgid "Gallery"
31+msgstr ""
32+
33+#: Applications/applications.js:40
34+msgid "Facebook"
35+msgstr ""
36+
37+#: Applications/applications.js:46
38+msgid "Browser"
39+msgstr ""
40+
41+#: Applications/applications.js:51
42+msgid "Twitter"
43+msgstr ""
44+
45+#: Applications/applications.js:57
46+msgid "GMail"
47+msgstr ""
48+
49+#: Applications/applications.js:62
50+msgid "Weather"
51+msgstr ""
52+
53+#: Applications/applications.js:68
54+msgid "Notepad"
55+msgstr ""
56+
57+#: Applications/applications.js:74
58+msgid "Calendar"
59+msgstr ""
60+
61+#: Applications/applications.js:80
62+msgid "Media Player"
63+msgstr ""
64+
65+#: Applications/applications.js:86
66+msgid "Evernote"
67+msgstr ""
68+
69+#: Applications/applications.js:91
70+msgid "Map"
71+msgstr ""
72+
73+#: Applications/applications.js:96
74+msgid "Pinterest"
75+msgstr ""
76+
77+#: Applications/applications.js:101
78+msgid "SoundCloud"
79+msgstr ""
80+
81+#: Applications/applications.js:106
82+msgid "Wikipedia"
83+msgstr ""
84+
85+#: Applications/applications.js:111
86+msgid "YouTube"
87+msgstr ""
88+
89+#: Components/EdgeDemoOverlay.qml:151
90+msgid "Skip intro"
91+msgstr ""
92+
93+#: Components/EdgeDemo.qml:112
94+msgid "Right edge"
95+msgstr ""
96+
97+#: Components/EdgeDemo.qml:113
98+msgid "Try swiping from the right edge to unlock the phone"
99+msgstr ""
100+
101+#: Components/EdgeDemo.qml:144
102+msgid "Top edge"
103+msgstr ""
104+
105+#: Components/EdgeDemo.qml:145
106+msgid "Try swiping from the top edge to access the indicators"
107+msgstr ""
108+
109+#: Components/EdgeDemo.qml:170
110+msgid "Close"
111+msgstr ""
112+
113+#: Components/EdgeDemo.qml:171
114+msgid "Swipe up again to close the settings screen"
115+msgstr ""
116+
117+#: Components/EdgeDemo.qml:198
118+msgid "Left edge"
119+msgstr ""
120+
121+#: Components/EdgeDemo.qml:199
122+msgid "Swipe from the left to reveal the launcher for quick access to apps"
123+msgstr ""
124+
125+#: Components/EdgeDemo.qml:226
126+msgid "Well done"
127+msgstr ""
128+
129+#: Components/EdgeDemo.qml:227
130+msgid ""
131+"You have now mastered the edge gestures and can start using the "
132+"phone<br><br>Tap anywhere to start"
133+msgstr ""
134+
135+#: Components/PageHeader.qml:345
136+msgid "Recent searches"
137+msgstr ""
138+
139+#. TRANSLATORS: Number of persons who rated this app
140+#. TRANSLATORS: Number of persons who rated this app/video/whatever
141+#: Dash/Apps/AppInfo.qml:73 Dash/Previews/Header.qml:93
142+#, qt-format
143+msgid "(%1)"
144+msgstr ""
145+
146+#. TRANSLATORS: Number of persons who wrote reviews for this app
147+#. TRANSLATORS: Number of persons who wrote reviews for this app/video/whatever
148+#: Dash/Apps/AppInfo.qml:85 Dash/Previews/Header.qml:105
149+#, qt-format
150+msgid "%1 review"
151+msgid_plural "%1 reviews"
152+msgstr[0] ""
153+msgstr[1] ""
154+
155+#: Dash/Apps/AppPreview.qml:135
156+msgid "Rate this"
157+msgstr ""
158+
159+#: Dash/Previews/Reviews.qml:74
160+msgid "Add a review"
161+msgstr ""
162+
163+#: Dash/Previews/Reviews.qml:86
164+msgid "Review"
165+msgstr ""
166+
167+#: Dash/Previews/Reviews.qml:121
168+msgid "Send"
169+msgstr ""
170+
171+#: Dash/Previews/Reviews.qml:139
172+msgid "Comments:"
173+msgstr ""
174+
175+#: Greeter/Lockscreen.qml:146
176+msgid "Emergency Call"
177+msgstr ""
178+
179+#: Greeter/PassphraseLockscreen.qml:59
180+#, qt-format
181+msgid "Hello %1"
182+msgstr ""
183+
184+#: Greeter/PassphraseLockscreen.qml:59
185+msgid "Hello"
186+msgstr ""
187+
188+#: Hud/HudParametrizedActionsPage.qml:132
189+msgid "Confirm"
190+msgstr ""
191+
192+#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
193+msgid "Type or say a command"
194+msgstr ""
195+
196+#: Hud/Hud.qml:84
197+msgid "Loading. Please Wait..."
198+msgstr ""
199+
200+#: Hud/Hud.qml:89
201+msgid "Speak Now..."
202+msgstr ""
203+
204+#: Hud/Hud.qml:94
205+msgid "Speaking..."
206+msgstr ""
207+
208+#: Notifications/NotificationMenuItemFactory.qml:89
209+msgid "Show password"
210+msgstr ""
211+
212+#: Panel/SearchIndicator.qml:27
213+msgid "Search"
214+msgstr ""
215+
216+#: plugins/Unity/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
226+msgid "Sorry, there is nothing that matches your search."
227+msgstr ""
228+
229+#: plugins/Unity/showallfilteroption.cpp:41
230+msgid "All"
231+msgstr ""
232+
233+#: Shell.qml:441
234+#, qt-format
235+msgid "Please enter %1"
236+msgstr ""
po/fi.po+23−31
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Ohita esittely"
91msgstr "Ohita esittely"
92
92
@@ -134,7 +134,7 @@ msgstr ""
134"Hallitset nyt reunaeleet, joten voit aloittaa puhelimen "
134"Hallitset nyt reunaeleet, joten voit aloittaa puhelimen "
135"käytön<br><br>Napauta missä tahansa aloittaaksesi"
135"käytön<br><br>Napauta missä tahansa aloittaaksesi"
136
136
137−#: Components/PageHeader.qml:341
137+#: Components/PageHeader.qml:345
138msgid "Recent searches"
138msgid "Recent searches"
139msgstr "Viimeisimmät haut"
139msgstr "Viimeisimmät haut"
140
140
@@ -154,7 +154,7 @@ msgid_plural "%1 reviews"
154msgstr[0] "%1 arvostelu"
154msgstr[0] "%1 arvostelu"
155msgstr[1] "%1 arvostelua"
155msgstr[1] "%1 arvostelua"
156
156
157−#: Dash/Apps/AppPreview.qml:126
157+#: Dash/Apps/AppPreview.qml:135
158msgid "Rate this"
158msgid "Rate this"
159msgstr "Arvioi tämä"
159msgstr "Arvioi tämä"
160
160
@@ -174,7 +174,7 @@ msgstr "Lähetä"
174msgid "Comments:"
174msgid "Comments:"
175msgstr "Kommentit:"
175msgstr "Kommentit:"
176
176
177−#: Greeter/Lockscreen.qml:142
177+#: Greeter/Lockscreen.qml:146
178msgid "Emergency Call"
178msgid "Emergency Call"
179msgstr "Hätäpuhelu"
179msgstr "Hätäpuhelu"
180
180
@@ -207,11 +207,24 @@ 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/Launcher/launcheritem.cpp:43
219+#: plugins/Unity/Launcher/launcheritem.cpp:73
220+msgid "Lock to Launcher"
221+msgstr ""
222+
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Unlock from Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/scope.cpp:408
215msgid "Sorry, there is nothing that matches your search."
228msgid "Sorry, there is nothing that matches your search."
216msgstr "Hakuun täsmääviä tuloksia ei löydy."
229msgstr "Hakuun täsmääviä tuloksia ei löydy."
217
230
@@ -219,28 +232,7 @@ msgstr "Hakuun täsmääviä tuloksia ei löydy."
219msgid "All"
232msgid "All"
220msgstr "Kaikki"
233msgstr "Kaikki"
221
234
222−#: Shell.qml:438
235+#: Shell.qml:441
223#, qt-format
236#, qt-format
224msgid "Please enter %1"
237msgid "Please enter %1"
225msgstr "Kirjoita %1"
238msgstr "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+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
227msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
215
228
@@ -217,13 +230,7 @@ msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Tónleikur"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Sjónbond"
po/fr.po+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,13 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Musique"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Vidéos"
po/gd.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "An Uicipeid"
87msgid "YouTube"
87msgid "YouTube"
88msgstr "YouTube"
88msgstr "YouTube"
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr "Gearr leum thairis air an ro-ràdh"
92msgstr "Gearr leum thairis air an ro-ràdh"
93
93
@@ -139,7 +139,7 @@ msgid ""
139"phone<br><br>Tap anywhere to start"
139"phone<br><br>Tap anywhere to start"
140msgstr ""
140msgstr ""
141
141
142−#: Components/PageHeader.qml:341
142+#: Components/PageHeader.qml:345
143msgid "Recent searches"
143msgid "Recent searches"
144msgstr "Na lorg thu o chionn goirid"
144msgstr "Na lorg thu o chionn goirid"
145
145
@@ -161,7 +161,7 @@ msgstr[1] "%1 lèirmheas"
161msgstr[2] "%1 lèirmheasan"
161msgstr[2] "%1 lèirmheasan"
162msgstr[3] "%1 lèirmheas"
162msgstr[3] "%1 lèirmheas"
163
163
164−#: Dash/Apps/AppPreview.qml:126
164+#: Dash/Apps/AppPreview.qml:135
165msgid "Rate this"
165msgid "Rate this"
166msgstr "Rangaich seo"
166msgstr "Rangaich seo"
167
167
@@ -181,7 +181,7 @@ msgstr "Cuir"
181msgid "Comments:"
181msgid "Comments:"
182msgstr "Beachdan"
182msgstr "Beachdan"
183
183
184−#: Greeter/Lockscreen.qml:142
184+#: Greeter/Lockscreen.qml:146
185msgid "Emergency Call"
185msgid "Emergency Call"
186msgstr "Gairm èiginn"
186msgstr "Gairm èiginn"
187
187
@@ -214,11 +214,24 @@ 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/Launcher/launcheritem.cpp:43
226+#: plugins/Unity/Launcher/launcheritem.cpp:73
227+msgid "Lock to Launcher"
228+msgstr ""
229+
230+#: plugins/Unity/Launcher/launcheritem.cpp:73
231+msgid "Unlock from Launcher"
232+msgstr ""
233+
234+#: plugins/Unity/scope.cpp:408
222msgid "Sorry, there is nothing that matches your search."
235msgid "Sorry, there is nothing that matches your search."
223msgstr "Tha sinn duilich ach chan eil dad a' freagairt ris na lorg thu."
236msgstr "Tha sinn duilich ach chan eil dad a' freagairt ris na lorg thu."
224
237
@@ -226,28 +239,7 @@ msgstr "Tha sinn duilich ach chan eil dad a' freagairt ris na lorg thu."
226msgid "All"
239msgid "All"
227msgstr ""
240msgstr ""
228
241
229−#: Shell.qml:438
242+#: Shell.qml:441
230#, qt-format
243#, qt-format
231msgid "Please enter %1"
244msgid "Please enter %1"
232msgstr "Cuir a-steach %1"
245msgstr "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+22−27
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Saltar introdución"
91msgstr "Saltar introdución"
92
92
@@ -134,7 +134,7 @@ msgstr ""
134"Xa domina os xestos desde os bordos e pode comezar a usar o "
134"Xa domina os xestos desde os bordos e pode comezar a usar o "
135"móbil<br><br>Toque en calquera sitio para comezar"
135"móbil<br><br>Toque en calquera sitio para comezar"
136
136
137−#: Components/PageHeader.qml:341
137+#: Components/PageHeader.qml:345
138msgid "Recent searches"
138msgid "Recent searches"
139msgstr "Buscas recentes"
139msgstr "Buscas recentes"
140
140
@@ -154,7 +154,7 @@ msgid_plural "%1 reviews"
154msgstr[0] "%1 opinión"
154msgstr[0] "%1 opinión"
155msgstr[1] "%1 opinións"
155msgstr[1] "%1 opinións"
156
156
157−#: Dash/Apps/AppPreview.qml:126
157+#: Dash/Apps/AppPreview.qml:135
158msgid "Rate this"
158msgid "Rate this"
159msgstr "Valore isto"
159msgstr "Valore isto"
160
160
@@ -174,7 +174,7 @@ msgstr "Enviar"
174msgid "Comments:"
174msgid "Comments:"
175msgstr "Comentarios:"
175msgstr "Comentarios:"
176
176
177−#: Greeter/Lockscreen.qml:142
177+#: Greeter/Lockscreen.qml:146
178msgid "Emergency Call"
178msgid "Emergency Call"
179msgstr "Chamada de emerxencia"
179msgstr "Chamada de emerxencia"
180
180
@@ -207,11 +207,24 @@ 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/Launcher/launcheritem.cpp:43
219+#: plugins/Unity/Launcher/launcheritem.cpp:73
220+msgid "Lock to Launcher"
221+msgstr ""
222+
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Unlock from Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/scope.cpp:408
215msgid "Sorry, there is nothing that matches your search."
228msgid "Sorry, there is nothing that matches your search."
216msgstr "Sentímolo, non hai nada que coincida con esta busca."
229msgstr "Sentímolo, non hai nada que coincida con esta busca."
217
230
@@ -219,25 +232,7 @@ msgstr "Sentímolo, non hai nada que coincida con esta busca."
219msgid "All"
232msgid "All"
220msgstr "Todo"
233msgstr "Todo"
221
234
222−#: Shell.qml:438
235+#: Shell.qml:441
223#, qt-format
236#, qt-format
224msgid "Please enter %1"
237msgid "Please enter %1"
225msgstr "Introduza %1"
238msgstr "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+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "ויקיפדיה"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "לדלג על הפתיחה"
91msgstr "לדלג על הפתיחה"
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "חיפושים אחרונים"
137msgstr "חיפושים אחרונים"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] "סקירה %1"
152msgstr[0] "סקירה %1"
153msgstr[1] "%1 סקירות"
153msgstr[1] "%1 סקירות"
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr "דירוג היישום"
157msgstr "דירוג היישום"
158
158
@@ -172,7 +172,7 @@ msgstr "שליחה"
172msgid "Comments:"
172msgid "Comments:"
173msgstr "הערות:"
173msgstr "הערות:"
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr "שיחת חירום"
177msgstr "שיחת חירום"
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה."
227msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה."
215
228
@@ -217,28 +230,7 @@ msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr "נא להזין %1"
236msgstr "נא להזין %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+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr ""
87msgid "YouTube"
87msgid "YouTube"
88msgstr ""
88msgstr ""
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr ""
92msgstr ""
93
93
@@ -133,7 +133,7 @@ msgid ""
133"phone<br><br>Tap anywhere to start"
133"phone<br><br>Tap anywhere to start"
134msgstr ""
134msgstr ""
135
135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137msgid "Recent searches"
137msgid "Recent searches"
138msgstr "Nedavne pretrage"
138msgstr "Nedavne pretrage"
139
139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153msgstr[0] ""
153msgstr[0] ""
154msgstr[1] ""
154msgstr[1] ""
155
155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157msgid "Rate this"
157msgid "Rate this"
158msgstr ""
158msgstr ""
159
159
@@ -173,7 +173,7 @@ msgstr ""
173msgid "Comments:"
173msgid "Comments:"
174msgstr ""
174msgstr ""
175
175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177msgid "Emergency Call"
177msgid "Emergency Call"
178msgstr ""
178msgstr ""
179
179
@@ -206,11 +206,24 @@ 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/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
227msgid "Sorry, there is nothing that matches your search."
215msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
228msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
216
229
@@ -218,13 +231,7 @@ msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
218msgid "All"
231msgid "All"
219msgstr ""
232msgstr ""
220
233
221−#: Shell.qml:438
234+#: Shell.qml:441
222#, qt-format
235#, qt-format
223msgid "Please enter %1"
236msgid "Please enter %1"
224msgstr ""
237msgstr ""
225−
226−#~ msgid "Music"
227−#~ msgstr "Glazba"
228−
229−#~ msgid "Videos"
230−#~ msgstr "Video"
po/hu.po+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Legutóbbi keresések"
137msgstr "Legutóbbi keresések"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Elnézést, nincs találat a keresésre."
227msgstr "Elnézést, nincs találat a keresésre."
215
228
@@ -217,13 +230,7 @@ msgstr "Elnézést, nincs találat a keresésre."
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Zene"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Videók"
po/hy.po+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Վերջին որոնումներ"
137msgstr "Վերջին որոնումներ"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
227msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
215
228
@@ -217,13 +230,7 @@ msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Երգեր"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Վիդեոներ"
po/id.po+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,7 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
po/is.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Hoppa yfir kynningu"
91msgstr "Hoppa yfir kynningu"
92
92
@@ -133,7 +133,7 @@ msgid ""
133"phone<br><br>Tap anywhere to start"
133"phone<br><br>Tap anywhere to start"
134msgstr ""
134msgstr ""
135
135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137msgid "Recent searches"
137msgid "Recent searches"
138msgstr "Nýlegar leitir"
138msgstr "Nýlegar leitir"
139
139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153msgstr[0] "%1 ummæli"
153msgstr[0] "%1 ummæli"
154msgstr[1] "%1 ummæli"
154msgstr[1] "%1 ummæli"
155
155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157msgid "Rate this"
157msgid "Rate this"
158msgstr "Gefa þessu einkunn"
158msgstr "Gefa þessu einkunn"
159
159
@@ -173,7 +173,7 @@ msgstr "Senda"
173msgid "Comments:"
173msgid "Comments:"
174msgstr "Athugasemdir:"
174msgstr "Athugasemdir:"
175
175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177msgid "Emergency Call"
177msgid "Emergency Call"
178msgstr "Neyðarsímtal"
178msgstr "Neyðarsímtal"
179
179
@@ -206,11 +206,24 @@ 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/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
227msgid "Sorry, there is nothing that matches your search."
215msgstr "Því miður, það var ekkert sem passaði við leitarorðið þitt."
228msgstr "Því miður, það var ekkert sem passaði við leitarorðið þitt."
216
229
@@ -218,28 +231,7 @@ msgstr "Því miður, það var ekkert sem passaði við leitarorðið þitt."
218msgid "All"
231msgid "All"
219msgstr ""
232msgstr ""
220
233
221−#: Shell.qml:438
234+#: Shell.qml:441
222#, qt-format
235#, qt-format
223msgid "Please enter %1"
236msgid "Please enter %1"
224msgstr ""
237msgstr ""
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+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipedia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Salta introduzione"
91msgstr "Salta introduzione"
92
92
@@ -139,7 +139,7 @@ msgstr ""
139"I gesti sui bordi sono stati configurati ed è possibile iniziare a usare il "
139"I gesti sui bordi sono stati configurati ed è possibile iniziare a usare il "
140"telefono<br><br>Toccare in un punto qualunque per iniziare"
140"telefono<br><br>Toccare in un punto qualunque per iniziare"
141
141
142−#: Components/PageHeader.qml:341
142+#: Components/PageHeader.qml:345
143msgid "Recent searches"
143msgid "Recent searches"
144msgstr "Ricerche recenti"
144msgstr "Ricerche recenti"
145
145
@@ -159,7 +159,7 @@ msgid_plural "%1 reviews"
159msgstr[0] "%1 recensione"
159msgstr[0] "%1 recensione"
160msgstr[1] "%1 recensioni"
160msgstr[1] "%1 recensioni"
161
161
162−#: Dash/Apps/AppPreview.qml:126
162+#: Dash/Apps/AppPreview.qml:135
163msgid "Rate this"
163msgid "Rate this"
164msgstr "Valuta"
164msgstr "Valuta"
165
165
@@ -179,7 +179,7 @@ msgstr "Invia"
179msgid "Comments:"
179msgid "Comments:"
180msgstr "Commenti:"
180msgstr "Commenti:"
181
181
182−#: Greeter/Lockscreen.qml:142
182+#: Greeter/Lockscreen.qml:146
183msgid "Emergency Call"
183msgid "Emergency Call"
184msgstr "Chiamata di emergenza"
184msgstr "Chiamata di emergenza"
185
185
@@ -212,11 +212,24 @@ 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/Launcher/launcheritem.cpp:43
224+#: plugins/Unity/Launcher/launcheritem.cpp:73
225+msgid "Lock to Launcher"
226+msgstr ""
227+
228+#: plugins/Unity/Launcher/launcheritem.cpp:73
229+msgid "Unlock from Launcher"
230+msgstr ""
231+
232+#: plugins/Unity/scope.cpp:408
220msgid "Sorry, there is nothing that matches your search."
233msgid "Sorry, there is nothing that matches your search."
221msgstr "Nessun risultato corrispondente alla ricerca."
234msgstr "Nessun risultato corrispondente alla ricerca."
222
235
@@ -224,28 +237,7 @@ msgstr "Nessun risultato corrispondente alla ricerca."
224msgid "All"
237msgid "All"
225msgstr "Tutto"
238msgstr "Tutto"
226
239
227−#: Shell.qml:438
240+#: Shell.qml:441
228#, qt-format
241#, qt-format
229msgid "Please enter %1"
242msgid "Please enter %1"
230msgstr "Inserire %1"
243msgstr "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+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,7 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
po/km.po+24−32
@@ -7,16 +7,16 @@ 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-12 16:10+0100\n"
11−"PO-Revision-Date: 2013-10-11 08:49+0000\n"
11+"PO-Revision-Date: 2013-11-14 03:02+0000\n"
12−"Last-Translator: Khoem Sokhem <khoemsokhem@khmeros.info>\n"
12+"Last-Translator: Seng Sutha <sutha@khmeros.info>\n"
13"Language-Team: Khmer <km@li.org>\n"
13"Language-Team: Khmer <km@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=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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "វីគីភីឌៀ"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "រំលង​ការ​ណែនាំ"
91msgstr "រំលង​ការ​ណែនាំ"
92
92
@@ -137,7 +137,7 @@ msgstr ""
137"និង​អាច​ចាប់ផ្ដើម​ប្រើ​ទូរស័ព្ទ​បាន<br><br>ប៉ះ​កន្លែង​ណា​មួយ​ "
137"និង​អាច​ចាប់ផ្ដើម​ប្រើ​ទូរស័ព្ទ​បាន<br><br>ប៉ះ​កន្លែង​ណា​មួយ​ "
138"ដើម្បី​ចាប់ផ្ដើម"
138"ដើម្បី​ចាប់ផ្ដើម"
139
139
140−#: Components/PageHeader.qml:341
140+#: Components/PageHeader.qml:345
141msgid "Recent searches"
141msgid "Recent searches"
142msgstr "ការ​ស្វែងរក​ថ្មី"
142msgstr "ការ​ស្វែងរក​ថ្មី"
143
143
@@ -156,7 +156,7 @@ msgid "%1 review"
156msgid_plural "%1 reviews"
156msgid_plural "%1 reviews"
157msgstr[0] "ពិនិត្យ​មើល %1"
157msgstr[0] "ពិនិត្យ​មើល %1"
158
158
159−#: Dash/Apps/AppPreview.qml:126
159+#: Dash/Apps/AppPreview.qml:135
160msgid "Rate this"
160msgid "Rate this"
161msgstr "វាយតម្លៃ​វា"
161msgstr "វាយតម្លៃ​វា"
162
162
@@ -176,7 +176,7 @@ msgstr "ផ្ញើ"
176msgid "Comments:"
176msgid "Comments:"
177msgstr "មតិយោបល់៖"
177msgstr "មតិយោបល់៖"
178
178
179−#: Greeter/Lockscreen.qml:142
179+#: Greeter/Lockscreen.qml:146
180msgid "Emergency Call"
180msgid "Emergency Call"
181msgstr "ការ​ហៅ​ពេល​អាសន្ន"
181msgstr "ការ​ហៅ​ពេល​អាសន្ន"
182
182
@@ -209,11 +209,24 @@ 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/Launcher/launcheritem.cpp:43
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Lock to Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/Launcher/launcheritem.cpp:73
226+msgid "Unlock from Launcher"
227+msgstr ""
228+
229+#: plugins/Unity/scope.cpp:408
217msgid "Sorry, there is nothing that matches your search."
230msgid "Sorry, there is nothing that matches your search."
218msgstr "សូម​ទោស មិនមាន​ពាក្យ​ដែល​អ្នក​ស្វែងរក​ទេ​។"
231msgstr "សូម​ទោស មិនមាន​ពាក្យ​ដែល​អ្នក​ស្វែងរក​ទេ​។"
219
232
@@ -221,28 +234,7 @@ msgstr "សូម​ទោស មិនមាន​ពាក្យ​ដែល
221msgid "All"
234msgid "All"
222msgstr "ទាំង​អស់"
235msgstr "ទាំង​អស់"
223
236
224−#: Shell.qml:438
237+#: Shell.qml:441
225#, qt-format
238#, qt-format
226msgid "Please enter %1"
239msgid "Please enter %1"
227msgstr "សូម​បញ្ចូល %1"
240msgstr "សូម​បញ្ចូល %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+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "ಇತ್ತೀಚಿನ ಹುಡುಕಾಟಗಳು"
137msgstr "ಇತ್ತೀಚಿನ ಹುಡುಕಾಟಗಳು"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯಾದ ಹೊಂದಾಣಿಕೆಗಳು ದೊರಕುತ್ತಿಲ್ಲ"
227msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯಾದ ಹೊಂದಾಣಿಕೆಗಳು ದೊರಕುತ್ತಿಲ್ಲ"
215
228
@@ -217,13 +230,7 @@ msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯ
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "ಸಂಗೀತ"
227−
228−#~ msgid "Videos"
229−#~ msgstr "ವೀಡಿಯೋಗಳು"
po/ko.po+22−12
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "위키백과"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "유튜브"
87msgstr "유튜브"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "도입부 건너뛰기"
91msgstr "도입부 건너뛰기"
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "최근 검색"
137msgstr "최근 검색"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,10 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "음악"
po/ky.po+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Соңку издөөлөр"
137msgstr "Соңку издөөлөр"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Тилекке каршы, сиздин издөөңүзгө эч нерсе дал келген жок."
227msgstr "Тилекке каршы, сиздин издөөңүзгө эч нерсе дал келген жок."
215
228
@@ -217,13 +230,7 @@ msgstr "Тилекке каршы, сиздин издөөңүзгө эч нер
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Музыка"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Видеолор"
po/lo.po+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr "ິYouTube"
87msgstr "ິYouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr "ສົ່ງ"
172msgid "Comments:"
172msgid "Comments:"
173msgstr "ຄໍ່ເຫັນ"
173msgstr "ຄໍ່ເຫັນ"
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,13 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr "ທັງໝົດ"
231msgstr "ທັງໝົດ"
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr "ກະລູນາປ້ອນ %1"
236msgstr "ກະລູນາປ້ອນ %1"
224−
225−#~ msgid "Videos"
226−#~ msgstr "ວິດີໂອ"
227−
228−#~ msgid "Music"
229−#~ msgstr "ດົນຕີ"
po/lv.po+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Vikipēdija"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Nesen veiktās meklēšanas"
137msgstr "Nesen veiktās meklēšanas"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
227msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
215
228
@@ -217,13 +230,7 @@ msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Mūzika"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Video"
po/my.po+22−24
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "ဝီကီပီဒီးယား"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "မိတ်ဆက်ကိုကျော်မည်"
91msgstr "မိတ်ဆက်ကိုကျော်မည်"
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "မကြာသေးခင်က ရှာဖွေခြင်း"
137msgstr "မကြာသေးခင်က ရှာဖွေခြင်း"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr "ဒီဟာကိုအမှတ်ပေးမည်"
157msgstr "ဒီဟာကိုအမှတ်ပေးမည်"
158
158
@@ -172,7 +172,7 @@ msgstr "ပို့မည်"
172msgid "Comments:"
172msgid "Comments:"
173msgstr "မှတ်ချက်များ-"
173msgstr "မှတ်ချက်များ-"
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့်တူညီတာဘာမှမရှိပါ။"
227msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့်တူညီတာဘာမှမရှိပါ။"
215
228
@@ -217,22 +230,7 @@ msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
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+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Siste søk"
137msgstr "Siste søk"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Søket ga ingen treff."
227msgstr "Søket ga ingen treff."
215
228
@@ -217,13 +230,7 @@ msgstr "Søket ga ingen treff."
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Musikk"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Videoer"
po/nl.po+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "Recente zoekopdrachten"
137msgstr "Recente zoekopdrachten"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
227msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
215
228
@@ -217,13 +230,7 @@ msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "Muziek"
227−
228−#~ msgid "Videos"
229−#~ msgstr "Video's"
po/pl.po+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Wikipedia"
87msgid "YouTube"
87msgid "YouTube"
88msgstr "YouTube"
88msgstr "YouTube"
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr "Pomiń intro"
92msgstr "Pomiń intro"
93
93
@@ -137,7 +137,7 @@ msgstr ""
137"Polecenia aktywatorów krawędzi ekranu zostały opanowane<br><br>Dotknij "
137"Polecenia aktywatorów krawędzi ekranu zostały opanowane<br><br>Dotknij "
138"gdziekolwiek aby kontynuować"
138"gdziekolwiek aby kontynuować"
139
139
140−#: Components/PageHeader.qml:341
140+#: Components/PageHeader.qml:345
141msgid "Recent searches"
141msgid "Recent searches"
142msgstr "Ostatnie wyszukiwania"
142msgstr "Ostatnie wyszukiwania"
143
143
@@ -158,7 +158,7 @@ msgstr[0] "%1 opinia"
158msgstr[1] "%1 opinie"
158msgstr[1] "%1 opinie"
159msgstr[2] "%1 opinii"
159msgstr[2] "%1 opinii"
160
160
161−#: Dash/Apps/AppPreview.qml:126
161+#: Dash/Apps/AppPreview.qml:135
162msgid "Rate this"
162msgid "Rate this"
163msgstr "Oceń to"
163msgstr "Oceń to"
164
164
@@ -178,7 +178,7 @@ msgstr "Wyślij"
178msgid "Comments:"
178msgid "Comments:"
179msgstr "Komentarze:"
179msgstr "Komentarze:"
180
180
181−#: Greeter/Lockscreen.qml:142
181+#: Greeter/Lockscreen.qml:146
182msgid "Emergency Call"
182msgid "Emergency Call"
183msgstr "Telefon ratunkowy"
183msgstr "Telefon ratunkowy"
184
184
@@ -211,11 +211,24 @@ 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/Launcher/launcheritem.cpp:43
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Lock to Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/Launcher/launcheritem.cpp:73
228+msgid "Unlock from Launcher"
229+msgstr ""
230+
231+#: plugins/Unity/scope.cpp:408
219msgid "Sorry, there is nothing that matches your search."
232msgid "Sorry, there is nothing that matches your search."
220msgstr "Nie znaleziono pasujących wyników."
233msgstr "Nie znaleziono pasujących wyników."
221
234
@@ -223,7 +236,7 @@ msgstr "Nie znaleziono pasujących wyników."
223msgid "All"
236msgid "All"
224msgstr "Wszystko"
237msgstr "Wszystko"
225
238
226−#: Shell.qml:438
239+#: Shell.qml:441
227#, qt-format
240#, qt-format
228msgid "Please enter %1"
241msgid "Please enter %1"
229msgstr "Wprowadź %1"
242msgstr "Wprowadź %1"
po/pt_BR.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Wikipédia"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "Pular introdução"
91msgstr "Pular introdução"
92
92
@@ -134,7 +134,7 @@ msgid ""
134"phone<br><br>Tap anywhere to start"
134"phone<br><br>Tap anywhere to start"
135msgstr ""
135msgstr ""
136
136
137−#: Components/PageHeader.qml:341
137+#: Components/PageHeader.qml:345
138msgid "Recent searches"
138msgid "Recent searches"
139msgstr "Pesquisas recentes"
139msgstr "Pesquisas recentes"
140
140
@@ -154,7 +154,7 @@ msgid_plural "%1 reviews"
154msgstr[0] "%1 análise"
154msgstr[0] "%1 análise"
155msgstr[1] "%1 análises"
155msgstr[1] "%1 análises"
156
156
157−#: Dash/Apps/AppPreview.qml:126
157+#: Dash/Apps/AppPreview.qml:135
158msgid "Rate this"
158msgid "Rate this"
159msgstr "Avaliar isto"
159msgstr "Avaliar isto"
160
160
@@ -174,7 +174,7 @@ msgstr "Enviar"
174msgid "Comments:"
174msgid "Comments:"
175msgstr "Comentários:"
175msgstr "Comentários:"
176
176
177−#: Greeter/Lockscreen.qml:142
177+#: Greeter/Lockscreen.qml:146
178msgid "Emergency Call"
178msgid "Emergency Call"
179msgstr "Chamada de emergência"
179msgstr "Chamada de emergência"
180
180
@@ -207,11 +207,24 @@ 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/Launcher/launcheritem.cpp:43
219+#: plugins/Unity/Launcher/launcheritem.cpp:73
220+msgid "Lock to Launcher"
221+msgstr ""
222+
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Unlock from Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/scope.cpp:408
215msgid "Sorry, there is nothing that matches your search."
228msgid "Sorry, there is nothing that matches your search."
216msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
229msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
217
230
@@ -219,28 +232,7 @@ msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
219msgid "All"
232msgid "All"
220msgstr ""
233msgstr ""
221
234
222−#: Shell.qml:438
235+#: Shell.qml:441
223#, qt-format
236#, qt-format
224msgid "Please enter %1"
237msgid "Please enter %1"
225msgstr "Por favor, digite %1"
238msgstr "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+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr ""
87msgid "YouTube"
87msgid "YouTube"
88msgstr ""
88msgstr ""
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr ""
92msgstr ""
93
93
@@ -133,7 +133,7 @@ msgid ""
133"phone<br><br>Tap anywhere to start"
133"phone<br><br>Tap anywhere to start"
134msgstr ""
134msgstr ""
135
135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137msgid "Recent searches"
137msgid "Recent searches"
138msgstr "Căutări recente"
138msgstr "Căutări recente"
139
139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153msgstr[0] ""
153msgstr[0] ""
154msgstr[1] ""
154msgstr[1] ""
155
155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157msgid "Rate this"
157msgid "Rate this"
158msgstr ""
158msgstr ""
159
159
@@ -173,7 +173,7 @@ msgstr ""
173msgid "Comments:"
173msgid "Comments:"
174msgstr ""
174msgstr ""
175
175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177msgid "Emergency Call"
177msgid "Emergency Call"
178msgstr ""
178msgstr ""
179
179
@@ -206,11 +206,24 @@ 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/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
227msgid "Sorry, there is nothing that matches your search."
215msgstr ""
228msgstr ""
216"Ne pare rău, nu este nimic care se potrivește căutării dumneavoastră."
229"Ne pare rău, nu este nimic care se potrivește căutării dumneavoastră."
@@ -219,13 +232,7 @@ msgstr ""
219msgid "All"
232msgid "All"
220msgstr ""
233msgstr ""
221
234
222−#: Shell.qml:438
235+#: Shell.qml:441
223#, qt-format
236#, qt-format
224msgid "Please enter %1"
237msgid "Please enter %1"
225msgstr ""
238msgstr ""
226−
227−#~ msgid "Music"
228−#~ msgstr "Muzică"
229−
230−#~ msgid "Videos"
231−#~ msgstr "Video"
po/ru.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Википедия"
87msgid "YouTube"
87msgid "YouTube"
88msgstr "YouTube"
88msgstr "YouTube"
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr "Пропустить обучение"
92msgstr "Пропустить обучение"
93
93
@@ -138,7 +138,7 @@ msgid ""
138"phone<br><br>Tap anywhere to start"
138"phone<br><br>Tap anywhere to start"
139msgstr ""
139msgstr ""
140
140
141−#: Components/PageHeader.qml:341
141+#: Components/PageHeader.qml:345
142msgid "Recent searches"
142msgid "Recent searches"
143msgstr "Последние поисковые запросы"
143msgstr "Последние поисковые запросы"
144
144
@@ -157,7 +157,7 @@ msgid "%1 review"
157msgid_plural "%1 reviews"
157msgid_plural "%1 reviews"
158msgstr[0] "%1 отзыв"
158msgstr[0] "%1 отзыв"
159
159
160−#: Dash/Apps/AppPreview.qml:126
160+#: Dash/Apps/AppPreview.qml:135
161msgid "Rate this"
161msgid "Rate this"
162msgstr "Оцените это"
162msgstr "Оцените это"
163
163
@@ -177,7 +177,7 @@ msgstr "Отправить"
177msgid "Comments:"
177msgid "Comments:"
178msgstr "Комментарии:"
178msgstr "Комментарии:"
179
179
180−#: Greeter/Lockscreen.qml:142
180+#: Greeter/Lockscreen.qml:146
181msgid "Emergency Call"
181msgid "Emergency Call"
182msgstr "Экстренный вызов"
182msgstr "Экстренный вызов"
183
183
@@ -210,11 +210,24 @@ 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/Launcher/launcheritem.cpp:43
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Lock to Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/Launcher/launcheritem.cpp:73
227+msgid "Unlock from Launcher"
228+msgstr ""
229+
230+#: plugins/Unity/scope.cpp:408
218msgid "Sorry, there is nothing that matches your search."
231msgid "Sorry, there is nothing that matches your search."
219msgstr "Извините, поиск не дал результатов."
232msgstr "Извините, поиск не дал результатов."
220
233
@@ -222,28 +235,7 @@ msgstr "Извините, поиск не дал результатов."
222msgid "All"
235msgid "All"
223msgstr ""
236msgstr ""
224
237
225−#: Shell.qml:438
238+#: Shell.qml:441
226#, qt-format
239#, qt-format
227msgid "Please enter %1"
240msgid "Please enter %1"
228msgstr "Пожалуйста, введите %1"
241msgstr "Пожалуйста, введите %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+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,7 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
po/si.po+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,7 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
po/sl.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Wikipedija"
87msgid "YouTube"
87msgid "YouTube"
88msgstr "YouTube"
88msgstr "YouTube"
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr "Preskoči uvod"
92msgstr "Preskoči uvod"
93
93
@@ -137,7 +137,7 @@ msgstr ""
137"Sedaj ste osvojili poteze robov ter lahko začnete uporabljati "
137"Sedaj ste osvojili poteze robov ter lahko začnete uporabljati "
138"telefon<br><br>Tapnite kjerkoli na začetek"
138"telefon<br><br>Tapnite kjerkoli na začetek"
139
139
140−#: Components/PageHeader.qml:341
140+#: Components/PageHeader.qml:345
141msgid "Recent searches"
141msgid "Recent searches"
142msgstr "Nedavna iskanja"
142msgstr "Nedavna iskanja"
143
143
@@ -159,7 +159,7 @@ msgstr[1] "%1 ocena"
159msgstr[2] "%1 oceni"
159msgstr[2] "%1 oceni"
160msgstr[3] "%1 ocene"
160msgstr[3] "%1 ocene"
161
161
162−#: Dash/Apps/AppPreview.qml:126
162+#: Dash/Apps/AppPreview.qml:135
163msgid "Rate this"
163msgid "Rate this"
164msgstr "Ocenite"
164msgstr "Ocenite"
165
165
@@ -179,7 +179,7 @@ msgstr "Pošlji"
179msgid "Comments:"
179msgid "Comments:"
180msgstr "Opombe:"
180msgstr "Opombe:"
181
181
182−#: Greeter/Lockscreen.qml:142
182+#: Greeter/Lockscreen.qml:146
183msgid "Emergency Call"
183msgid "Emergency Call"
184msgstr "Klic v sili"
184msgstr "Klic v sili"
185
185
@@ -212,11 +212,24 @@ 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/Launcher/launcheritem.cpp:43
224+#: plugins/Unity/Launcher/launcheritem.cpp:73
225+msgid "Lock to Launcher"
226+msgstr ""
227+
228+#: plugins/Unity/Launcher/launcheritem.cpp:73
229+msgid "Unlock from Launcher"
230+msgstr ""
231+
232+#: plugins/Unity/scope.cpp:408
220msgid "Sorry, there is nothing that matches your search."
233msgid "Sorry, there is nothing that matches your search."
221msgstr "Nič se ne ujema z vašim iskalnim nizom."
234msgstr "Nič se ne ujema z vašim iskalnim nizom."
222
235
@@ -224,28 +237,7 @@ msgstr "Nič se ne ujema z vašim iskalnim nizom."
224msgid "All"
237msgid "All"
225msgstr "Vse"
238msgstr "Vse"
226
239
227−#: Shell.qml:438
240+#: Shell.qml:441
228#, qt-format
241#, qt-format
229msgid "Please enter %1"
242msgid "Please enter %1"
230msgstr "Vnesite %1"
243msgstr "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+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16799)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr ""
87msgid "YouTube"
87msgid "YouTube"
88msgstr ""
88msgstr ""
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr ""
92msgstr ""
93
93
@@ -133,7 +133,7 @@ msgid ""
133"phone<br><br>Tap anywhere to start"
133"phone<br><br>Tap anywhere to start"
134msgstr ""
134msgstr ""
135
135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137msgid "Recent searches"
137msgid "Recent searches"
138msgstr "Скорашње претраге"
138msgstr "Скорашње претраге"
139
139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153msgstr[0] ""
153msgstr[0] ""
154msgstr[1] ""
154msgstr[1] ""
155
155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157msgid "Rate this"
157msgid "Rate this"
158msgstr ""
158msgstr ""
159
159
@@ -173,7 +173,7 @@ msgstr ""
173msgid "Comments:"
173msgid "Comments:"
174msgstr ""
174msgstr ""
175
175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177msgid "Emergency Call"
177msgid "Emergency Call"
178msgstr ""
178msgstr ""
179
179
@@ -206,11 +206,24 @@ 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/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
227msgid "Sorry, there is nothing that matches your search."
215msgstr "Нажалост, претрага није наишла на икакво подударање."
228msgstr "Нажалост, претрага није наишла на икакво подударање."
216
229
@@ -218,13 +231,7 @@ msgstr "Нажалост, претрага није наишла на икакв
218msgid "All"
231msgid "All"
219msgstr ""
232msgstr ""
220
233
221−#: Shell.qml:438
234+#: Shell.qml:441
222#, qt-format
235#, qt-format
223msgid "Please enter %1"
236msgid "Please enter %1"
224msgstr ""
237msgstr ""
225−
226−#~ msgid "Music"
227−#~ msgstr "Музика"
228−
229−#~ msgid "Videos"
230−#~ msgstr "Видео"
po/sv.po+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,7 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
po/ta.ponew file+242
@@ -0,0 +1,242 @@
1+# Tamil translation for unity8
2+# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
3+# This file is distributed under the same license as the unity8 package.
4+# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
5+# துளசி <Thangamani Arun<thangam.arunx@gmail.com>>, 2013.
6+msgid ""
7+msgstr ""
8+"Project-Id-Version: unity8\n"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2013-11-12 16:10+0100\n"
11+"PO-Revision-Date: 2013-10-24 11:36+0000\n"
12+"Last-Translator: Thangamani Arun - தங்கமணி அருண் <thangam.arunx@gmail.com>\n"
13+"Language-Team: Ubuntu Tamil Team/Free Tamil Computing/Thamizha\n"
14+"MIME-Version: 1.0\n"
15+"Content-Type: text/plain; charset=UTF-8\n"
16+"Content-Transfer-Encoding: 8bit\n"
17+"Plural-Forms: nplurals=2; plural=n != 1;\n"
18+"X-Launchpad-Export-Date: 2013-11-19 05:59+0000\n"
19+"X-Generator: Launchpad (build 16831)\n"
20+"Language: ta\n"
21+
22+#: Applications/applications.js:23
23+msgid "Phone"
24+msgstr "தொலைபேசி"
25+
26+#: Applications/applications.js:29
27+msgid "Camera"
28+msgstr "புகைப்பட கருவி"
29+
30+#: Applications/applications.js:35
31+msgid "Gallery"
32+msgstr "படத்தொகுப்பு"
33+
34+#: Applications/applications.js:40
35+msgid "Facebook"
36+msgstr "முகநுல்"
37+
38+#: Applications/applications.js:46
39+msgid "Browser"
40+msgstr "உலாவி"
41+
42+#: Applications/applications.js:51
43+msgid "Twitter"
44+msgstr "ட்விட்டர்"
45+
46+#: Applications/applications.js:57
47+msgid "GMail"
48+msgstr "ஜிமெயில்"
49+
50+#: Applications/applications.js:62
51+msgid "Weather"
52+msgstr "வானிலை"
53+
54+#: Applications/applications.js:68
55+msgid "Notepad"
56+msgstr "குறிப்புபலகை"
57+
58+#: Applications/applications.js:74
59+msgid "Calendar"
60+msgstr "நாள்காட்டி"
61+
62+#: Applications/applications.js:80
63+msgid "Media Player"
64+msgstr "ஊடக இயக்கி"
65+
66+#: Applications/applications.js:86
67+msgid "Evernote"
68+msgstr "எப்போதும்குறிப்பெடு"
69+
70+#: Applications/applications.js:91
71+msgid "Map"
72+msgstr "வரைபடம்"
73+
74+#: Applications/applications.js:96
75+msgid "Pinterest"
76+msgstr "விசைத்தட்டு"
77+
78+#: Applications/applications.js:101
79+msgid "SoundCloud"
80+msgstr "ஒலி கிளவுட்"
81+
82+#: Applications/applications.js:106
83+msgid "Wikipedia"
84+msgstr "விக்கிப்பீடியா"
85+
86+#: Applications/applications.js:111
87+msgid "YouTube"
88+msgstr "யூட்யுப்"
89+
90+#: Components/EdgeDemoOverlay.qml:151
91+msgid "Skip intro"
92+msgstr "அறிமுகத்தை தவிர்"
93+
94+#: Components/EdgeDemo.qml:112
95+msgid "Right edge"
96+msgstr "வலது விளிம்பு"
97+
98+#: Components/EdgeDemo.qml:113
99+msgid "Try swiping from the right edge to unlock the phone"
100+msgstr "தொலைபேசியை திறக்க வலது முனையிலிருந்து தேய்த்து முயற்சி செய்"
101+
102+#: Components/EdgeDemo.qml:144
103+msgid "Top edge"
104+msgstr "மேல் விளிம்பு"
105+
106+#: Components/EdgeDemo.qml:145
107+msgid "Try swiping from the top edge to access the indicators"
108+msgstr "காட்டிகளை அனுக மேல் விளிம்பிலிருந்து தேய்த்து முயற்சி செய்"
109+
110+#: Components/EdgeDemo.qml:170
111+msgid "Close"
112+msgstr "மூடு"
113+
114+#: Components/EdgeDemo.qml:171
115+msgid "Swipe up again to close the settings screen"
116+msgstr "அமைவுகளின் திரையை மூட மறுபடியும் மேலே தேய்க்கவும்"
117+
118+#: Components/EdgeDemo.qml:198
119+msgid "Left edge"
120+msgstr "இடது விளிம்பு"
121+
122+#: Components/EdgeDemo.qml:199
123+msgid "Swipe from the left to reveal the launcher for quick access to apps"
124+msgstr ""
125+"பயன்பாடுகளின் விரைவான அணுகலை பெறத்தேவையான தொடக்கியை இடமிருந்து தேய்த்தால் "
126+"வெளிப்படும்"
127+
128+#: Components/EdgeDemo.qml:226
129+msgid "Well done"
130+msgstr "நன்றாக செய்தீர்கள்"
131+
132+#: Components/EdgeDemo.qml:227
133+msgid ""
134+"You have now mastered the edge gestures and can start using the "
135+"phone<br><br>Tap anywhere to start"
136+msgstr ""
137+"நீங்கள் இப்போது விளிம்பு சைகைகளில் கைதேர்ந்தவர் மற்றும் தொலைபேசி "
138+"பயன்படுத்த தொடங்கவும் <br> <br>தட்டுவதன் மூலம் எங்க வேண்டுமானாலும் "
139+"தொடங்கலாம்."
140+
141+#: Components/PageHeader.qml:345
142+msgid "Recent searches"
143+msgstr "கடையாக தேடப்பட்டவைகள்"
144+
145+#. TRANSLATORS: Number of persons who rated this app
146+#. TRANSLATORS: Number of persons who rated this app/video/whatever
147+#: Dash/Apps/AppInfo.qml:73 Dash/Previews/Header.qml:93
148+#, qt-format
149+msgid "(%1)"
150+msgstr "(%1)"
151+
152+#. TRANSLATORS: Number of persons who wrote reviews for this app
153+#. TRANSLATORS: Number of persons who wrote reviews for this app/video/whatever
154+#: Dash/Apps/AppInfo.qml:85 Dash/Previews/Header.qml:105
155+#, qt-format
156+msgid "%1 review"
157+msgid_plural "%1 reviews"
158+msgstr[0] "%1 பரிசீலனை"
159+msgstr[1] "%1 பரிசீலனைகள்"
160+
161+#: Dash/Apps/AppPreview.qml:135
162+msgid "Rate this"
163+msgstr "இதை மதிப்பிடு"
164+
165+#: Dash/Previews/Reviews.qml:74
166+msgid "Add a review"
167+msgstr "ஒரு பரிசீலனையை சேர்"
168+
169+#: Dash/Previews/Reviews.qml:86
170+msgid "Review"
171+msgstr "மறுஆய்வு"
172+
173+#: Dash/Previews/Reviews.qml:121
174+msgid "Send"
175+msgstr "அனுப்பு"
176+
177+#: Dash/Previews/Reviews.qml:139
178+msgid "Comments:"
179+msgstr "கருத்துகள்:"
180+
181+#: Greeter/Lockscreen.qml:146
182+msgid "Emergency Call"
183+msgstr "அவசர அழைப்பு"
184+
185+#: Greeter/PassphraseLockscreen.qml:59
186+#, qt-format
187+msgid "Hello %1"
188+msgstr "வணக்கம் %1"
189+
190+#: Greeter/PassphraseLockscreen.qml:59
191+msgid "Hello"
192+msgstr "வணக்கம்"
193+
194+#: Hud/HudParametrizedActionsPage.qml:132
195+msgid "Confirm"
196+msgstr "உறுதிப்படுத்து"
197+
198+#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
199+msgid "Type or say a command"
200+msgstr "ஒரு கட்டளையை உச்சரி அல்லது தட்டச்சுசெய்"
201+
202+#: Hud/Hud.qml:84
203+msgid "Loading. Please Wait..."
204+msgstr "ஏற்றுகிறது. தயைசெய்து காத்திருக்கவும்..."
205+
206+#: Hud/Hud.qml:89
207+msgid "Speak Now..."
208+msgstr "இப்பொது பேசு..."
209+
210+#: Hud/Hud.qml:94
211+msgid "Speaking..."
212+msgstr "பேசுகிறது..."
213+
214+#: Notifications/NotificationMenuItemFactory.qml:89
215+msgid "Show password"
216+msgstr ""
217+
218+#: Panel/SearchIndicator.qml:27
219+msgid "Search"
220+msgstr "தெடு"
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:43
223+#: plugins/Unity/Launcher/launcheritem.cpp:73
224+msgid "Lock to Launcher"
225+msgstr ""
226+
227+#: plugins/Unity/Launcher/launcheritem.cpp:73
228+msgid "Unlock from Launcher"
229+msgstr ""
230+
231+#: plugins/Unity/scope.cpp:408
232+msgid "Sorry, there is nothing that matches your search."
233+msgstr "மன்னிக்கவும், உங்களுடைய தேடலுக்கு தகுந்த பொருத்தம் கிடைக்கவில்லை."
234+
235+#: plugins/Unity/showallfilteroption.cpp:41
236+msgid "All"
237+msgstr "அனைத்தும்"
238+
239+#: Shell.qml:441
240+#, qt-format
241+msgid "Please enter %1"
242+msgstr "தயவுச்செய்து %1 உள்ளிடு"
po/te.po+22−12
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,10 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "సంగీతం"
po/tr.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "Vikipedi"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr "İntro'yu geç"
91msgstr "İntro'yu geç"
92
92
@@ -133,7 +133,7 @@ msgid ""
133"phone<br><br>Tap anywhere to start"
133"phone<br><br>Tap anywhere to start"
134msgstr ""
134msgstr ""
135
135
136−#: Components/PageHeader.qml:341
136+#: Components/PageHeader.qml:345
137msgid "Recent searches"
137msgid "Recent searches"
138msgstr "Son Arananlar"
138msgstr "Son Arananlar"
139
139
@@ -153,7 +153,7 @@ msgid_plural "%1 reviews"
153msgstr[0] "%1 inceleme"
153msgstr[0] "%1 inceleme"
154msgstr[1] "%1 inceleme"
154msgstr[1] "%1 inceleme"
155
155
156−#: Dash/Apps/AppPreview.qml:126
156+#: Dash/Apps/AppPreview.qml:135
157msgid "Rate this"
157msgid "Rate this"
158msgstr "Oyla"
158msgstr "Oyla"
159
159
@@ -173,7 +173,7 @@ msgstr "Gönder"
173msgid "Comments:"
173msgid "Comments:"
174msgstr "Yorumlar:"
174msgstr "Yorumlar:"
175
175
176−#: Greeter/Lockscreen.qml:142
176+#: Greeter/Lockscreen.qml:146
177msgid "Emergency Call"
177msgid "Emergency Call"
178msgstr "Acil Arama"
178msgstr "Acil Arama"
179
179
@@ -206,11 +206,24 @@ 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/Launcher/launcheritem.cpp:43
218+#: plugins/Unity/Launcher/launcheritem.cpp:73
219+msgid "Lock to Launcher"
220+msgstr ""
221+
222+#: plugins/Unity/Launcher/launcheritem.cpp:73
223+msgid "Unlock from Launcher"
224+msgstr ""
225+
226+#: plugins/Unity/scope.cpp:408
214msgid "Sorry, there is nothing that matches your search."
227msgid "Sorry, there is nothing that matches your search."
215msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
228msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
216
229
@@ -218,28 +231,7 @@ msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
218msgid "All"
231msgid "All"
219msgstr ""
232msgstr ""
220
233
221−#: Shell.qml:438
234+#: Shell.qml:441
222#, qt-format
235#, qt-format
223msgid "Please enter %1"
236msgid "Please enter %1"
224msgstr "Lütfen %1 girin"
237msgstr "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+22−24
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "ۋىكىپېدىيە"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "يېقىنقى ئىزدەشلەر"
137msgstr "يېقىنقى ئىزدەشلەر"
138
138
@@ -151,7 +151,7 @@ msgid "%1 review"
151msgid_plural "%1 reviews"
151msgid_plural "%1 reviews"
152msgstr[0] "%1 باھا"
152msgstr[0] "%1 باھا"
153
153
154−#: Dash/Apps/AppPreview.qml:126
154+#: Dash/Apps/AppPreview.qml:135
155msgid "Rate this"
155msgid "Rate this"
156msgstr ""
156msgstr ""
157
157
@@ -171,7 +171,7 @@ msgstr "ئەۋەت"
171msgid "Comments:"
171msgid "Comments:"
172msgstr "ئىنكاس:"
172msgstr "ئىنكاس:"
173
173
174−#: Greeter/Lockscreen.qml:142
174+#: Greeter/Lockscreen.qml:146
175msgid "Emergency Call"
175msgid "Emergency Call"
176msgstr ""
176msgstr ""
177
177
@@ -204,11 +204,24 @@ 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/Launcher/launcheritem.cpp:43
216+#: plugins/Unity/Launcher/launcheritem.cpp:73
217+msgid "Lock to Launcher"
218+msgstr ""
219+
220+#: plugins/Unity/Launcher/launcheritem.cpp:73
221+msgid "Unlock from Launcher"
222+msgstr ""
223+
224+#: plugins/Unity/scope.cpp:408
212msgid "Sorry, there is nothing that matches your search."
225msgid "Sorry, there is nothing that matches your search."
213msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپىلمىدى."
226msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپىلمىدى."
214
227
@@ -216,22 +229,7 @@ msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپ
216msgid "All"
229msgid "All"
217msgstr "ھەممىسى"
230msgstr "ھەممىسى"
218
231
219−#: Shell.qml:438
232+#: Shell.qml:441
220#, qt-format
233#, qt-format
221msgid "Please enter %1"
234msgid "Please enter %1"
222msgstr "%1 نى كىرگۈزۈڭ"
235msgstr "%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+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
20−"X-Generator: Launchpad (build 16807)\n"
20+"X-Generator: Launchpad (build 16831)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -87,7 +87,7 @@ msgstr "Вікіпедія"
87msgid "YouTube"
87msgid "YouTube"
88msgstr "YouTube"
88msgstr "YouTube"
89
89
90−#: Components/EdgeDemoOverlay.qml:149
90+#: Components/EdgeDemoOverlay.qml:151
91msgid "Skip intro"
91msgid "Skip intro"
92msgstr "Пропустити вступ"
92msgstr "Пропустити вступ"
93
93
@@ -138,7 +138,7 @@ msgstr ""
138"Тепер жести налаштовано, ви можете почати користуватися "
138"Тепер жести налаштовано, ви можете почати користуватися "
139"телефоном.<br><br>Натисніть у довільному місці екрана."
139"телефоном.<br><br>Натисніть у довільному місці екрана."
140
140
141−#: Components/PageHeader.qml:341
141+#: Components/PageHeader.qml:345
142msgid "Recent searches"
142msgid "Recent searches"
143msgstr "Нещодавні пошуки"
143msgstr "Нещодавні пошуки"
144
144
@@ -159,7 +159,7 @@ msgstr[0] "%1 рецензія"
159msgstr[1] "%1 рецензії"
159msgstr[1] "%1 рецензії"
160msgstr[2] "%1 рецензій"
160msgstr[2] "%1 рецензій"
161
161
162−#: Dash/Apps/AppPreview.qml:126
162+#: Dash/Apps/AppPreview.qml:135
163msgid "Rate this"
163msgid "Rate this"
164msgstr "Оцінити"
164msgstr "Оцінити"
165
165
@@ -179,7 +179,7 @@ msgstr "Надіслати"
179msgid "Comments:"
179msgid "Comments:"
180msgstr "Коментарі:"
180msgstr "Коментарі:"
181
181
182−#: Greeter/Lockscreen.qml:142
182+#: Greeter/Lockscreen.qml:146
183msgid "Emergency Call"
183msgid "Emergency Call"
184msgstr "Терміновий виклик"
184msgstr "Терміновий виклик"
185
185
@@ -212,11 +212,24 @@ 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/Launcher/launcheritem.cpp:43
224+#: plugins/Unity/Launcher/launcheritem.cpp:73
225+msgid "Lock to Launcher"
226+msgstr ""
227+
228+#: plugins/Unity/Launcher/launcheritem.cpp:73
229+msgid "Unlock from Launcher"
230+msgstr ""
231+
232+#: plugins/Unity/scope.cpp:408
220msgid "Sorry, there is nothing that matches your search."
233msgid "Sorry, there is nothing that matches your search."
221msgstr "Вибачте, для вказаних вами ключових слів нічого не знайдено."
234msgstr "Вибачте, для вказаних вами ключових слів нічого не знайдено."
222
235
@@ -224,7 +237,7 @@ msgstr "Вибачте, для вказаних вами ключових слі
224msgid "All"
237msgid "All"
225msgstr "Усе"
238msgstr "Усе"
226
239
227−#: Shell.qml:438
240+#: Shell.qml:441
228#, qt-format
241#, qt-format
229msgid "Please enter %1"
242msgid "Please enter %1"
230msgstr "Будь ласка, введіть %1"
243msgstr "Будь ласка, введіть %1"
po/unity8.pot+20−7
@@ -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-12 16:10+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"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,7 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
po/xh.po+22−9
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr ""
137msgstr ""
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr ""
227msgstr ""
215
228
@@ -217,7 +230,7 @@ msgstr ""
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
po/zh_CN.po+22−30
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr "维基百科"
86msgid "YouTube"
86msgid "YouTube"
87msgstr "YouTube"
87msgstr "YouTube"
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "近期搜索"
137msgstr "近期搜索"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "对不起,没有找到您想要的结果。"
227msgstr "对不起,没有找到您想要的结果。"
215
228
@@ -217,28 +230,7 @@ msgstr "对不起,没有找到您想要的结果。"
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
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+22−15
@@ -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-12 16:10+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-19 05:59+0000\n"
19−"X-Generator: Launchpad (build 16799)\n"
19+"X-Generator: Launchpad (build 16831)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -86,7 +86,7 @@ msgstr ""
86msgid "YouTube"
86msgid "YouTube"
87msgstr ""
87msgstr ""
88
88
89−#: Components/EdgeDemoOverlay.qml:149
89+#: Components/EdgeDemoOverlay.qml:151
90msgid "Skip intro"
90msgid "Skip intro"
91msgstr ""
91msgstr ""
92
92
@@ -132,7 +132,7 @@ msgid ""
132"phone<br><br>Tap anywhere to start"
132"phone<br><br>Tap anywhere to start"
133msgstr ""
133msgstr ""
134
134
135−#: Components/PageHeader.qml:341
135+#: Components/PageHeader.qml:345
136msgid "Recent searches"
136msgid "Recent searches"
137msgstr "最近搜尋"
137msgstr "最近搜尋"
138
138
@@ -152,7 +152,7 @@ msgid_plural "%1 reviews"
152msgstr[0] ""
152msgstr[0] ""
153msgstr[1] ""
153msgstr[1] ""
154
154
155−#: Dash/Apps/AppPreview.qml:126
155+#: Dash/Apps/AppPreview.qml:135
156msgid "Rate this"
156msgid "Rate this"
157msgstr ""
157msgstr ""
158
158
@@ -172,7 +172,7 @@ msgstr ""
172msgid "Comments:"
172msgid "Comments:"
173msgstr ""
173msgstr ""
174
174
175−#: Greeter/Lockscreen.qml:142
175+#: Greeter/Lockscreen.qml:146
176msgid "Emergency Call"
176msgid "Emergency Call"
177msgstr ""
177msgstr ""
178
178
@@ -205,11 +205,24 @@ 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/Launcher/launcheritem.cpp:43
217+#: plugins/Unity/Launcher/launcheritem.cpp:73
218+msgid "Lock to Launcher"
219+msgstr ""
220+
221+#: plugins/Unity/Launcher/launcheritem.cpp:73
222+msgid "Unlock from Launcher"
223+msgstr ""
224+
225+#: plugins/Unity/scope.cpp:408
213msgid "Sorry, there is nothing that matches your search."
226msgid "Sorry, there is nothing that matches your search."
214msgstr "很抱歉,找不到符合您想搜尋的結果。"
227msgstr "很抱歉,找不到符合您想搜尋的結果。"
215
228
@@ -217,13 +230,7 @@ msgstr "很抱歉,找不到符合您想搜尋的結果。"
217msgid "All"
230msgid "All"
218msgstr ""
231msgstr ""
219
232
220−#: Shell.qml:438
233+#: Shell.qml:441
221#, qt-format
234#, qt-format
222msgid "Please enter %1"
235msgid "Please enter %1"
223msgstr ""
236msgstr ""
224−
225−#~ msgid "Music"
226−#~ msgstr "音樂"
227−
228−#~ msgid "Videos"
229−#~ msgstr "影片"
run_on_device+24−4
@@ -1,4 +1,4 @@
1−#!/bin/sh
1+#!/bin/bash
2CODE_DIR=shell
2CODE_DIR=shell
3USER=phablet
3USER=phablet
4USER_ID=32011
4USER_ID=32011
@@ -17,6 +17,8 @@ SUDO="echo $PASSWORD | sudo -S"
17NUM_JOBS='$(( `grep -c ^processor /proc/cpuinfo` + 1 ))'
17NUM_JOBS='$(( `grep -c ^processor /proc/cpuinfo` + 1 ))'
18FLIPPED=false
18FLIPPED=false
19CHROOT_PREFIX="/data/ubuntu"
19CHROOT_PREFIX="/data/ubuntu"
20+SSH_WAS_STARTED=0
21+SSH_STARTED=0
20
22
21usage() {
23usage() {
22 echo "usage: run_on_device [OPTIONS]\n"
24 echo "usage: run_on_device [OPTIONS]\n"
@@ -32,7 +34,15 @@ usage() {
32 exit 1
34 exit 1
33}
35}
34
36
37+start_ssh() {
38+ if [ $SSH_STARTED -eq 0 ]; then
39+ exec_with_adb initctl start ssh
40+ SSH_STARTED=1
41+ fi
42+}
43+
35exec_with_ssh() {
44exec_with_ssh() {
45+ start_ssh
36 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -t $USER@$TARGET_IP -p $TARGET_SSH_PORT sudo -u $USER -i bash -ic \"$@\"
46 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -t $USER@$TARGET_IP -p $TARGET_SSH_PORT sudo -u $USER -i bash -ic \"$@\"
37}
47}
38
48
@@ -52,7 +62,7 @@ adb_root() {
52install_ssh_key() {
62install_ssh_key() {
53 ssh-keygen -R $TARGET_IP
63 ssh-keygen -R $TARGET_IP
54 HOME_DIR="${CHROOT_PREFIX}/home/phablet"
64 HOME_DIR="${CHROOT_PREFIX}/home/phablet"
55− adb push ~/.ssh/phone_rsa.pub $HOME_DIR/.ssh/authorized_keys
65+ adb push ~/.ssh/id_rsa.pub $HOME_DIR/.ssh/authorized_keys
56 adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh
66 adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh
57 adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh/authorized_keys
67 adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh/authorized_keys
58 adb shell chmod 700 $HOME_DIR/.ssh
68 adb shell chmod 700 $HOME_DIR/.ssh
@@ -65,8 +75,6 @@ setup_adb_forwarding() {
65}
75}
66
76
67install_dependencies() {
77install_dependencies() {
68− exec_with_adb rm /etc/init/ssh.override
69− exec_with_adb service ssh start
70 exec_with_adb apt-get update
78 exec_with_adb apt-get update
71 exec_with_ssh $SUDO apt-get -y install build-essential rsync bzr ccache gdb ninja-build devscripts equivs
79 exec_with_ssh $SUDO apt-get -y install build-essential rsync bzr ccache gdb ninja-build devscripts equivs
72}
80}
@@ -74,6 +82,7 @@ install_dependencies() {
74sync_code() {
82sync_code() {
75 [ -e .bzr ] && bzr export --uncommitted --format=dir /tmp/$CODE_DIR
83 [ -e .bzr ] && bzr export --uncommitted --format=dir /tmp/$CODE_DIR
76 [ -e .git ] && git checkout-index -a -f --prefix=/tmp/$CODE_DIR/
84 [ -e .git ] && git checkout-index -a -f --prefix=/tmp/$CODE_DIR/
85+ start_ssh
77 rsync -crlOzv --delete --exclude builddir -e "ssh -p $TARGET_SSH_PORT -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" /tmp/$CODE_DIR/ $USER@$TARGET_IP:$CODE_DIR/
86 rsync -crlOzv --delete --exclude builddir -e "ssh -p $TARGET_SSH_PORT -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" /tmp/$CODE_DIR/ $USER@$TARGET_IP:$CODE_DIR/
78 rm -rf /tmp/$CODE_DIR
87 rm -rf /tmp/$CODE_DIR
79}
88}
@@ -96,7 +105,9 @@ run() {
96 fi
105 fi
97
106
98 exec_with_ssh "stop unity8"
107 exec_with_ssh "stop unity8"
108+ exec_with_ssh "start maliit-server"
99 exec_with_ssh "cd $CODE_DIR/ && ./run $ARGS -- $RUN_OPTIONS"
109 exec_with_ssh "cd $CODE_DIR/ && ./run $ARGS -- $RUN_OPTIONS"
110+ exec_with_ssh "stop maliit-server"
100 exec_with_ssh "start unity8"
111 exec_with_ssh "start unity8"
101}
112}
102
113
@@ -130,6 +141,12 @@ if [ "`adb shell 'grep -q Ubuntu /etc/lsb-release 2> /dev/null && echo -n FLIPPE
130 fi
141 fi
131fi
142fi
132
143
144+status_output=$(exec_with_adb initctl status ssh)
145+if [[ $status_output == "ssh start/running, process "* ]]; then
146+ SSH_WAS_STARTED=1
147+fi
148+SSH_STARTED=$SSH_WAS_STARTED
149+
133if $SETUP; then
150if $SETUP; then
134 echo "Setting up environment for building shell.."
151 echo "Setting up environment for building shell.."
135 install_ssh_key
152 install_ssh_key
@@ -144,3 +161,6 @@ else
144 run
161 run
145fi
162fi
146
163
164+if [ $SSH_WAS_STARTED -eq 0 ]; then
165+ exec_with_adb initctl stop ssh
166+fi
tests/autopilot/unity8/process_helpers.pynew file+143
@@ -0,0 +1,143 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Utilities
4+# Copyright (C) 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 autopilot.introspection import (
21+ get_proxy_object_for_existing_process,
22+ ProcessSearchError,
23+)
24+import logging
25+import subprocess
26+from unity8.shell.emulators import UnityEmulatorBase
27+from unity8.shell.emulators.main_window import MainWindow
28+
29+logger = logging.getLogger(__name__)
30+
31+
32+class CannotAccessUnity(Exception):
33+ pass
34+
35+
36+def unlock_unity(unity_proxy_obj=None):
37+ """Helper function that attempts to unlock the unity greeter.
38+
39+ If unity_proxy_object is None create a proxy object by querying for the
40+ running unity process.
41+ Otherwise re-use the passed proxy object.
42+
43+ :raises RuntimeError: if the greeter attempts and fails to be unlocked.
44+
45+ :raises RuntimeWarning: when the greeter cannot be found because it is
46+ already unlocked.
47+ :raises CannotAccessUnity: if unity is not introspectable or cannot be
48+ found on dbus.
49+ :raises CannotAccessUnity: if unity's upstart status is not "start" or the
50+ upstart job cannot be found at all.
51+
52+ """
53+ if unity_proxy_obj is None:
54+ try:
55+ pid = _get_unity_pid()
56+ unity = _get_unity_proxy_object(pid)
57+ main_window = MainWindow(unity)
58+ except ProcessSearchError as e:
59+ raise CannotAccessUnity(
60+ "Cannot introspect unity, make sure that it has been started "
61+ "with testability. Perhaps use the function "
62+ "'restart_unity_with_testability' this module provides."
63+ "(%s)"
64+ % str(e)
65+ )
66+ else:
67+ main_window = MainWindow(unity_proxy_obj)
68+
69+ greeter = main_window.get_greeter()
70+ if greeter is None:
71+ raise RuntimeWarning("Greeter appears to be already unlocked.")
72+ greeter.swipe()
73+
74+
75+def restart_unity_with_testability(*args):
76+ """Restarts (or starts) unity with testability enabled.
77+
78+ Passes *args arguments to the launched process.
79+
80+ """
81+ args += ("QT_LOAD_TESTABILITY=1",)
82+ return restart_unity(*args)
83+
84+
85+def restart_unity(*args):
86+ """Restarts (or starts) unity8 using the provided arguments.
87+
88+ Passes *args arguments to the launched process.
89+
90+ :raises subprocess.CalledProcessError: if unable to stop or start the
91+ unity8 upstart job.
92+
93+ """
94+ status = _get_unity_status()
95+ if "start/" in status:
96+ try:
97+ output = subprocess.check_output(['initctl', 'stop', 'unity8'])
98+ logger.info(output)
99+ except subprocess.CalledProcessError as e:
100+ e.args += (
101+ "Failed to stop running instance of unity8: %s" % e.output,
102+ )
103+ raise
104+
105+ try:
106+ command = ['initctl', 'start', 'unity8'] + list(args)
107+ output = subprocess.check_output(
108+ command,
109+ stderr=subprocess.STDOUT,
110+ universal_newlines=True,
111+ )
112+ logger.info(output)
113+ pid = _get_unity_pid()
114+ except subprocess.CalledProcessError as e:
115+ e.args += ("Failed to start unity8: %s" % e.output,)
116+ raise
117+ else:
118+ return _get_unity_proxy_object(pid)
119+
120+
121+def _get_unity_status():
122+ try:
123+ return subprocess.check_output([
124+ 'initctl',
125+ 'status',
126+ 'unity8'
127+ ])
128+ except subprocess.CalledProcessError as e:
129+ raise CannotAccessUnity("Unable to get unity's status: %s" % str(e))
130+
131+
132+def _get_unity_pid():
133+ status = _get_unity_status()
134+ if not "start/" in status:
135+ raise CannotAccessUnity("Unity is not in the running state.")
136+ return int(status.split()[-1])
137+
138+
139+def _get_unity_proxy_object(pid):
140+ return get_proxy_object_for_existing_process(
141+ pid=pid,
142+ emulator_base=UnityEmulatorBase,
143+ )
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−7
@@ -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
@@ -64,12 +67,6 @@ class MainWindow(object):
64 def get_dash(self):
67 def get_dash(self):
65 return self.app.select_single(Dash)
68 return self.app.select_single(Dash)
66
69
67− def get_dash_home_applications_grid(self):
68− return self.app.select_single(
69− "ApplicationsFilterGrid",
70− objectName="dashHomeApplicationsGrid"
71− )
72−
73 def get_bottombar(self):
70 def get_bottombar(self):
74 return self.app.select_single("Bottombar")
71 return self.app.select_single("Bottombar")
75
72
@@ -93,3 +90,6 @@ class MainWindow(object):
93
90
94 def get_pinentryField(self):
91 def get_pinentryField(self):
95 return self.app.select_single(objectName="pinentryField")
92 return self.app.select_single(objectName="pinentryField")
93+
94+ def get_shell_background(self):
95+ return self.app.select_single("CrossFadeImage", objectName="backgroundImage")
tests/autopilot/unity8/shell/tests/__init__.py+54−36
@@ -28,13 +28,12 @@ from autopilot.platform import model
28from autopilot.testcase import AutopilotTestCase
28from autopilot.testcase import AutopilotTestCase
29from autopilot.matchers import Eventually
29from autopilot.matchers import Eventually
30from autopilot.input import Touch
30from autopilot.input import Touch
31−from autopilot.introspection import get_proxy_object_for_existing_process
32from autopilot.display import Display
31from autopilot.display import Display
33import logging
32import logging
34import os.path
33import os.path
35import subprocess
34import subprocess
36import sys
35import sys
37−from testtools.matchers import Equals, NotEquals
36+from testtools.matchers import Equals
38
37
39from unity8 import (
38from unity8 import (
40 get_lib_path,
39 get_lib_path,
@@ -43,7 +42,7 @@ from unity8 import (
43 get_default_extra_mock_libraries,
42 get_default_extra_mock_libraries,
44 get_data_dirs
43 get_data_dirs
45)
44)
46−from unity8.shell.emulators import UnityEmulatorBase
45+from unity8.process_helpers import restart_unity_with_testability
47from unity8.shell.emulators.dash import Dash
46from unity8.shell.emulators.dash import Dash
48from unity8.shell.emulators.main_window import MainWindow
47from unity8.shell.emulators.main_window import MainWindow
49
48
@@ -53,7 +52,7 @@ logger = logging.getLogger(__name__)
53UNITYSHELL_GSETTINGS_SCHEMA = "org.compiz.unityshell"
52UNITYSHELL_GSETTINGS_SCHEMA = "org.compiz.unityshell"
54UNITYSHELL_GSETTINGS_PATH = "/org/compiz/profiles/unity/plugins/unityshell/"
53UNITYSHELL_GSETTINGS_PATH = "/org/compiz/profiles/unity/plugins/unityshell/"
55UNITYSHELL_LAUNCHER_KEY = "launcher-hide-mode"
54UNITYSHELL_LAUNCHER_KEY = "launcher-hide-mode"
56−UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
55+UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
57
56
58
57
59def _get_device_emulation_scenarios(devices='All'):
58def _get_device_emulation_scenarios(devices='All'):
@@ -93,17 +92,25 @@ class UnityTestCase(AutopilotTestCase):
93 ], stderr=subprocess.STDOUT)
92 ], stderr=subprocess.STDOUT)
94 except subprocess.CalledProcessError, e:
93 except subprocess.CalledProcessError, e:
95 sys.stderr.write(
94 sys.stderr.write(
96− "Error: `initctl status unity8` failed, most probably the unity8 session could not be found:\n\n"
95+ "Error: `initctl status unity8` failed, most probably the "
96+ "unity8 session could not be found:\n\n"
97 "{0}\n"
97 "{0}\n"
98− "Please install unity8 or copy data/unity8.conf to {1}\n".format(
98+ "Please install unity8 or copy data/unity8.conf to "
99+ "{1}\n".format(
99 e.output,
100 e.output,
100− os.path.join(os.getenv("XDG_CONFIG_HOME", os.path.join(os.getenv("HOME"), ".config")), "upstart")
101+ os.path.join(os.getenv("XDG_CONFIG_HOME",
102+ os.path.join(os.getenv("HOME"),
103+ ".config")
104+ ),
105+ "upstart")
106+ )
101− ))
107+ )
102 sys.exit(1)
108 sys.exit(1)
103
109
104 if "start/" in output:
110 if "start/" in output:
105 sys.stderr.write(
111 sys.stderr.write(
106− "Error: Unity is currently running, these tests require it to be 'stopped'.\n"
112+ "Error: Unity is currently running, these tests require it to "
113+ "be 'stopped'.\n"
107 "Please run this command before running these tests: \n"
114 "Please run this command before running these tests: \n"
108 "initctl stop unity8\n"
115 "initctl stop unity8\n"
109 )
116 )
@@ -111,11 +118,22 @@ class UnityTestCase(AutopilotTestCase):
111
118
112 def setUp(self):
119 def setUp(self):
113 super(UnityTestCase, self).setUp()
120 super(UnityTestCase, self).setUp()
121+ if (Gio is not None and
122+ UNITYSHELL_GSETTINGS_SCHEMA in
114− if Gio is not None and UNITYSHELL_GSETTINGS_SCHEMA in Gio.Settings.list_relocatable_schemas():
123+ Gio.Settings.list_relocatable_schemas()):
124+
115 # Hide Unity launcher
125 # Hide Unity launcher
116− self._unityshell_schema = Gio.Settings.new_with_path(UNITYSHELL_GSETTINGS_SCHEMA, UNITYSHELL_GSETTINGS_PATH)
126+ self._unityshell_schema = Gio.Settings.new_with_path(
127+ UNITYSHELL_GSETTINGS_SCHEMA,
128+ UNITYSHELL_GSETTINGS_PATH,
129+ )
117− self._launcher_hide_mode = self._unityshell_schema.get_int(UNITYSHELL_LAUNCHER_KEY)
130+ self._launcher_hide_mode = self._unityshell_schema.get_int(
131+ UNITYSHELL_LAUNCHER_KEY,
132+ )
118− self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, UNITYSHELL_LAUNCHER_MODE)
133+ self._unityshell_schema.set_int(
134+ UNITYSHELL_LAUNCHER_KEY,
135+ UNITYSHELL_LAUNCHER_MODE,
136+ )
119 self.addCleanup(self._reset_launcher)
137 self.addCleanup(self._reset_launcher)
120
138
121 self._proxy = None
139 self._proxy = None
@@ -136,7 +154,10 @@ class UnityTestCase(AutopilotTestCase):
136
154
137 def _reset_launcher(self):
155 def _reset_launcher(self):
138 """Reset Unity launcher hide mode"""
156 """Reset Unity launcher hide mode"""
139− self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, self._launcher_hide_mode)
157+ self._unityshell_schema.set_int(
158+ UNITYSHELL_LAUNCHER_KEY,
159+ self._launcher_hide_mode,
160+ )
140
161
141 def _setup_display_details(self):
162 def _setup_display_details(self):
142 scale_divisor = self._determine_geometry()
163 scale_divisor = self._determine_geometry()
@@ -217,7 +238,10 @@ class UnityTestCase(AutopilotTestCase):
217 def _upstart_reset_env(self, key, value):
238 def _upstart_reset_env(self, key, value):
218 logger.info("Resetting upstart env %s to %s", key, value)
239 logger.info("Resetting upstart env %s to %s", key, value)
219 if value is None:
240 if value is None:
241+ subprocess.call(
220− subprocess.call(["/sbin/initctl", "unset-env", key], stderr=subprocess.STDOUT)
242+ ["/sbin/initctl", "unset-env", key],
243+ stderr=subprocess.STDOUT,
244+ )
221 else:
245 else:
222 subprocess.call([
246 subprocess.call([
223 "/sbin/initctl",
247 "/sbin/initctl",
@@ -244,9 +268,13 @@ class UnityTestCase(AutopilotTestCase):
244 self._setup_extra_mock_environment_patch()
268 self._setup_extra_mock_environment_patch()
245
269
246 # FIXME: we shouldn't be doing this
270 # FIXME: we shouldn't be doing this
247− # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and /tmp/mir_socket as last resort
271+ # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and
272+ # /tmp/mir_socket as last resort
248 try:
273 try:
274+ os.unlink(
275+ os.getenv('MIR_SOCKET',
249− os.unlink(os.getenv('MIR_SOCKET', os.path.join(os.getenv('XDG_RUNTIME_DIR', "/tmp"), "mir_socket")))
276+ os.path.join(os.getenv('XDG_RUNTIME_DIR', "/tmp"),
277+ "mir_socket")))
250 except OSError:
278 except OSError:
251 pass
279 pass
252 try:
280 try:
@@ -256,7 +284,7 @@ class UnityTestCase(AutopilotTestCase):
256
284
257 app_proxy = self._launch_unity_with_upstart(
285 app_proxy = self._launch_unity_with_upstart(
258 binary_path,
286 binary_path,
259− self.unity_geometry_args
287+ self.unity_geometry_args,
260 )
288 )
261
289
262 self._set_proxy(app_proxy)
290 self._set_proxy(app_proxy)
@@ -274,29 +302,20 @@ class UnityTestCase(AutopilotTestCase):
274
302
275 binary_arg = "BINARY=%s" % binary_path
303 binary_arg = "BINARY=%s" % binary_path
276 extra_args = "ARGS=%s" % " ".join(args)
304 extra_args = "ARGS=%s" % " ".join(args)
277−
278− output = subprocess.check_output([
279− "/sbin/initctl",
280− "start",
281− "unity8",
282− binary_arg,
283− extra_args
284− ] + ["%s=%s" % (k,v) for k,v in self._environment.iteritems()],
305+ env_args = ["%s=%s" % (k, v) for k, v in self._environment.iteritems()]
285− stderr=subprocess.STDOUT)
306+ all_args = [binary_arg, extra_args] + env_args
286
307
287 self.addCleanup(self._cleanup_launching_upstart_unity)
308 self.addCleanup(self._cleanup_launching_upstart_unity)
288
309
289− pid = int(output.split()[-1])
310+ return restart_unity_with_testability(*all_args)
290−
291− return get_proxy_object_for_existing_process(
292− pid=pid,
293− emulator_base=UnityEmulatorBase,
294− )
295
311
296 def _cleanup_launching_upstart_unity(self):
312 def _cleanup_launching_upstart_unity(self):
297 logger.info("Stopping unity")
313 logger.info("Stopping unity")
298 try:
314 try:
299− subprocess.check_output(["/sbin/initctl", "stop", "unity8"], stderr=subprocess.STDOUT)
315+ subprocess.check_output(
316+ ["/sbin/initctl", "stop", "unity8"],
317+ stderr=subprocess.STDOUT
318+ )
300 except subprocess.CalledProcessError:
319 except subprocess.CalledProcessError:
301 logger.warning("Appears unity was already stopped!")
320 logger.warning("Appears unity was already stopped!")
302
321
@@ -366,8 +385,7 @@ class UnityTestCase(AutopilotTestCase):
366 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
385 self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
367
386
368 def get_dash(self):
387 def get_dash(self):
369− dash = self._proxy.select_single(Dash)
388+ dash = self._proxy.wait_select_single(Dash)
370− self.assertThat(dash, NotEquals(None))
371 return dash
389 return dash
372
390
373 @property
391 @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_hud.py+11−10
@@ -19,6 +19,7 @@
19
19
20from __future__ import absolute_import
20from __future__ import absolute_import
21
21
22+from unity8.process_helpers import unlock_unity
22from unity8.shell import with_lightdm_mock, DragMixin
23from unity8.shell import with_lightdm_mock, DragMixin
23from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
24from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
24
25
@@ -38,8 +39,8 @@ class TestHud(UnityTestCase, DragMixin):
38 The button must disappear when touching somewhere on the screen except the button itself.
39 The button must disappear when touching somewhere on the screen except the button itself.
39
40
40 """
41 """
41− self.launch_unity()
42+ unity_proxy = self.launch_unity()
42− self.main_window.get_greeter().swipe()
43+ unlock_unity(unity_proxy)
43 window = self.main_window.get_qml_view()
44 window = self.main_window.get_qml_view()
44 hud_show_button = self.main_window.get_hud_show_button()
45 hud_show_button = self.main_window.get_hud_show_button()
45 edge_drag_area = self.main_window.get_hud_edge_drag_area()
46 edge_drag_area = self.main_window.get_hud_edge_drag_area()
@@ -80,8 +81,8 @@ class TestHud(UnityTestCase, DragMixin):
80 Test that the hud button stays on screen and tapping it opens the hud.
81 Test that the hud button stays on screen and tapping it opens the hud.
81
82
82 """
83 """
83− self.launch_unity()
84+ unity_proxy = self.launch_unity()
84− self.main_window.get_greeter().swipe()
85+ unlock_unity(unity_proxy)
85 window = self.main_window.get_qml_view()
86 window = self.main_window.get_qml_view()
86 hud_show_button = self.main_window.get_hud_show_button()
87 hud_show_button = self.main_window.get_hud_show_button()
87 hud = self.main_window.get_hud()
88 hud = self.main_window.get_hud()
@@ -117,8 +118,8 @@ class TestHud(UnityTestCase, DragMixin):
117
118
118 def test_hide_hud_click(self):
119 def test_hide_hud_click(self):
119 """Tapping the close button of the Hud must dismiss it."""
120 """Tapping the close button of the Hud must dismiss it."""
120− self.launch_unity()
121+ unity_proxy = self.launch_unity()
121− self.main_window.get_greeter().swipe()
122+ unlock_unity(unity_proxy)
122 hud = self.main_window.get_hud()
123 hud = self.main_window.get_hud()
123
124
124 self._launch_test_app_from_app_screen()
125 self._launch_test_app_from_app_screen()
@@ -134,8 +135,8 @@ class TestHud(UnityTestCase, DragMixin):
134 released downward.
135 released downward.
135
136
136 """
137 """
137− self.launch_unity()
138+ unity_proxy = self.launch_unity()
138− self.main_window.get_greeter().swipe()
139+ unlock_unity(unity_proxy)
139 window = self.main_window.get_qml_view()
140 window = self.main_window.get_qml_view()
140 hud = self.main_window.get_hud()
141 hud = self.main_window.get_hud()
141
142
@@ -152,8 +153,8 @@ class TestHud(UnityTestCase, DragMixin):
152
153
153 def test_launcher_hides_hud(self):
154 def test_launcher_hides_hud(self):
154 """Opening the Launcher while the Hud is active must close the Hud."""
155 """Opening the Launcher while the Hud is active must close the Hud."""
155− self.launch_unity()
156+ unity_proxy = self.launch_unity()
156− self.main_window.get_greeter().swipe()
157+ unlock_unity(unity_proxy)
157 hud = self.main_window.get_hud()
158 hud = self.main_window.get_hud()
158 launcher = self.main_window.get_launcher()
159 launcher = self.main_window.get_launcher()
159
160
tests/autopilot/unity8/shell/tests/test_notifications.py+74−72
@@ -21,6 +21,7 @@
21
21
22from __future__ import absolute_import
22from __future__ import absolute_import
23
23
24+from unity8.process_helpers import unlock_unity
24from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
25from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
25
26
26from testtools.matchers import Equals, NotEquals
27from testtools.matchers import Equals, NotEquals
@@ -45,7 +46,7 @@ class NotificationsBase(UnityTestCase):
45 """Given an icons file name returns the full path (either system or
46 """Given an icons file name returns the full path (either system or
46 source tree.
47 source tree.
47
48
48− Consider the graphics directory as root so for example (runnign tests
49+ Consider the graphics directory as root so for example (running tests
49 from installed unity8-autopilot package):
50 from installed unity8-autopilot package):
50 >>> self.get_icon_path('clock.png')
51 >>> self.get_icon_path('clock.png')
51 /usr/share/unity8/graphics/clock.png
52 /usr/share/unity8/graphics/clock.png
@@ -118,9 +119,8 @@ class InteractiveNotificationBase(NotificationsBase):
118
119
119 def test_interactive(self):
120 def test_interactive(self):
120 """Interactive notification must react upon click on itself."""
121 """Interactive notification must react upon click on itself."""
121− self.launch_unity()
122+ unity_proxy = self.launch_unity()
122− greeter = self.main_window.get_greeter()
123+ unlock_unity(unity_proxy)
123− greeter.swipe()
124
124
125 notify_list = self._get_notifications_list()
125 notify_list = self._get_notifications_list()
126
126
@@ -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,10 +156,10 @@ 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+ unity_proxy = self.launch_unity()
161− greeter = self.main_window.get_greeter()
162+ unlock_unity(unity_proxy)
162− greeter.swipe()
163
163
164 notify_list = self._get_notifications_list()
164 notify_list = self._get_notifications_list()
165
165
@@ -191,8 +191,8 @@ class InteractiveNotificationBase(NotificationsBase):
191 hints
191 hints
192 )
192 )
193
193
194+ get_notification = lambda: notify_list.wait_select_single(
194− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
195+ 'Notification', objectName='notification1')
195− self.assertThat(get_notification, Eventually(NotEquals(None)))
196 notification = get_notification()
196 notification = get_notification()
197 self._assert_notification(notification, None, None, True, True, 1.0)
197 self._assert_notification(notification, None, None, True, True, 1.0)
198 initial_height = notification.height
198 initial_height = notification.height
@@ -200,8 +200,10 @@ class InteractiveNotificationBase(NotificationsBase):
200 self.assertThat(
200 self.assertThat(
201 notification.height,
201 notification.height,
202 Eventually(Equals(initial_height +
202 Eventually(Equals(initial_height +
203+ 3 * notification.select_single(
203− 3 * notification.select_single(objectName="buttonColumn").spacing +
204+ objectName="buttonColumn").spacing +
204− 3 * notification.select_single(objectName="button4").height)))
205+ 3 * notification.select_single(
206+ objectName="button4").height)))
205 self.touch.tap_object(notification.select_single(objectName="button4"))
207 self.touch.tap_object(notification.select_single(objectName="button4"))
206 self.assert_notification_action_id_was_called("action_decline_4")
208 self.assert_notification_action_id_was_called("action_decline_4")
207
209
@@ -333,9 +335,8 @@ class EphemeralNotificationsTests(NotificationsBase):
333
335
334 def test_icon_summary_body(self):
336 def test_icon_summary_body(self):
335 """Notification must display the expected summary and body text."""
337 """Notification must display the expected summary and body text."""
336− self.launch_unity()
338+ unity_proxy = self.launch_unity()
337− greeter = self.main_window.get_greeter()
339+ unlock_unity(unity_proxy)
338− greeter.swipe()
339
340
340 notify_list = self._get_notifications_list()
341 notify_list = self._get_notifications_list()
341
342
@@ -360,16 +361,22 @@ class EphemeralNotificationsTests(NotificationsBase):
360
361
361 notification.show()
362 notification.show()
362
363
364+ notification = lambda: notify_list.wait_select_single(
363− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
365+ '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)
366+ self._assert_notification(
367+ notification(),
368+ summary,
369+ body,
370+ True,
371+ True,
372+ 1.0,
373+ )
367
374
368 def test_icon_summary(self):
375 def test_icon_summary(self):
369− """Notification must display the expected summary and secondary icon."""
376+ """Notification must display the expected summary and secondary
370− self.launch_unity()
377+ icon."""
371− greeter = self.main_window.get_greeter()
378+ unity_proxy = self.launch_unity()
372− greeter.swipe()
379+ unlock_unity(unity_proxy)
373
380
374 notify_list = self._get_notifications_list()
381 notify_list = self._get_notifications_list()
375
382
@@ -391,11 +398,11 @@ class EphemeralNotificationsTests(NotificationsBase):
391
398
392 notification.show()
399 notification.show()
393
400
401+ notification = lambda: notify_list.wait_select_single(
394− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
402+ 'Notification', objectName='notification1')
395− self.assertThat(get_notification, Eventually(NotEquals(None)))
403+
396− notification = get_notification()
397 self._assert_notification(
404 self._assert_notification(
398− notification,
405+ notification(),
399 summary,
406 summary,
400 None,
407 None,
401 False,
408 False,
@@ -404,10 +411,10 @@ class EphemeralNotificationsTests(NotificationsBase):
404 )
411 )
405
412
406 def test_urgency_order(self):
413 def test_urgency_order(self):
407− """Notifications must be displayed in order according to their urgency."""
414+ """Notifications must be displayed in order according to their
408− self.launch_unity()
415+ urgency."""
409− greeter = self.main_window.get_greeter()
416+ unity_proxy = self.launch_unity()
410− greeter.swipe()
417+ unlock_unity(unity_proxy)
411
418
412 notify_list = self._get_notifications_list()
419 notify_list = self._get_notifications_list()
413
420
@@ -448,11 +455,10 @@ class EphemeralNotificationsTests(NotificationsBase):
448 )
455 )
449 notification_critical.show()
456 notification_critical.show()
450
457
451− get_notification = lambda: notify_list.select_single(
458+ get_notification = lambda: notify_list.wait_select_single(
452 'Notification',
459 'Notification',
453 summary=summary_critical
460 summary=summary_critical
454 )
461 )
455− self.assertThat(get_notification, Eventually(NotEquals(None)))
456
462
457 notification = get_notification()
463 notification = get_notification()
458 self._assert_notification(
464 self._assert_notification(
@@ -464,11 +470,10 @@ class EphemeralNotificationsTests(NotificationsBase):
464 1.0
470 1.0
465 )
471 )
466
472
467− get_normal_notification = lambda: notify_list.select_single(
473+ get_normal_notification = lambda: notify_list.wait_select_single(
468 'Notification',
474 'Notification',
469 summary=summary_normal
475 summary=summary_normal
470 )
476 )
471− self.assertThat(get_normal_notification, Eventually(NotEquals(None)))
472 notification = get_normal_notification()
477 notification = get_normal_notification()
473 self._assert_notification(
478 self._assert_notification(
474 notification,
479 notification,
@@ -479,11 +484,10 @@ class EphemeralNotificationsTests(NotificationsBase):
479 1.0
484 1.0
480 )
485 )
481
486
482− get_low_notification = lambda: notify_list.select_single(
487+ get_low_notification = lambda: notify_list.wait_select_single(
483 'Notification',
488 'Notification',
484 summary=summary_low
489 summary=summary_low
485 )
490 )
486− self.assertThat(get_low_notification, Eventually(NotEquals(None)))
487 notification = get_low_notification()
491 notification = get_low_notification()
488 self._assert_notification(
492 self._assert_notification(
489 notification,
493 notification,
@@ -496,9 +500,8 @@ class EphemeralNotificationsTests(NotificationsBase):
496
500
497 def test_summary_and_body(self):
501 def test_summary_and_body(self):
498 """Notification must display the expected summary- and body-text."""
502 """Notification must display the expected summary- and body-text."""
499− self.launch_unity()
503+ unity_proxy = self.launch_unity()
500− greeter = self.main_window.get_greeter()
504+ unlock_unity(unity_proxy)
501− greeter.swipe()
502
505
503 notify_list = self._get_notifications_list()
506 notify_list = self._get_notifications_list()
504
507
@@ -508,9 +511,9 @@ class EphemeralNotificationsTests(NotificationsBase):
508 notification = self._create_ephemeral_notification(summary, body)
511 notification = self._create_ephemeral_notification(summary, body)
509 notification.show()
512 notification.show()
510
513
514+ notification = notify_list.wait_select_single(
511− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
515+ 'Notification', objectName='notification1')
512− self.assertThat(get_notification, Eventually(NotEquals(None)))
516+
513− notification = get_notification()
514 self._assert_notification(
517 self._assert_notification(
515 notification,
518 notification,
516 summary,
519 summary,
@@ -522,9 +525,8 @@ class EphemeralNotificationsTests(NotificationsBase):
522
525
523 def test_summary_only(self):
526 def test_summary_only(self):
524 """Notification must display only the expected summary-text."""
527 """Notification must display only the expected summary-text."""
525− self.launch_unity()
528+ unity_proxy = self.launch_unity()
526− greeter = self.main_window.get_greeter()
529+ unlock_unity(unity_proxy)
527− greeter.swipe()
528
530
529 notify_list = self._get_notifications_list()
531 notify_list = self._get_notifications_list()
530
532
@@ -533,17 +535,16 @@ class EphemeralNotificationsTests(NotificationsBase):
533 notification = self._create_ephemeral_notification(summary)
535 notification = self._create_ephemeral_notification(summary)
534 notification.show()
536 notification.show()
535
537
538+ notification = notify_list.wait_select_single(
536− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
539+ 'Notification', objectName='notification1')
537− self.assertThat(get_notification, Eventually(NotEquals(None)))
538− notification = get_notification()
539
540
540 self._assert_notification(notification, summary, '', False, False, 1.0)
541 self._assert_notification(notification, summary, '', False, False, 1.0)
541
542
542 def test_update_notification_same_layout(self):
543 def test_update_notification_same_layout(self):
543− """Notification must allow updating its contents while being displayed."""
544+ """Notification must allow updating its contents while being
544− self.launch_unity()
545+ displayed."""
545− greeter = self.main_window.get_greeter()
546+ unity_proxy = self.launch_unity()
546− greeter.swipe()
547+ unlock_unity(unity_proxy)
547
548
548 notify_list = self._get_notifications_list()
549 notify_list = self._get_notifications_list()
549
550
@@ -558,8 +559,8 @@ class EphemeralNotificationsTests(NotificationsBase):
558 )
559 )
559 notification.show()
560 notification.show()
560
561
561− get_notification = lambda: notify_list.select_single('Notification', summary=summary)
562+ get_notification = lambda: notify_list.wait_select_single(
562− self.assertThat(get_notification, Eventually(NotEquals(None)))
563+ 'Notification', summary=summary)
563 self._assert_notification(
564 self._assert_notification(
564 get_notification(),
565 get_notification(),
565 summary,
566 summary,
@@ -575,14 +576,13 @@ class EphemeralNotificationsTests(NotificationsBase):
575 icon_path = self._get_icon_path('avatars/amanda.png')
576 icon_path = self._get_icon_path('avatars/amanda.png')
576 notification.update(summary, body, icon_path)
577 notification.update(summary, body, icon_path)
577 notification.show()
578 notification.show()
578− self.assertThat(get_notification, Eventually(NotEquals(None)))
579 self._assert_notification(get_notification(), summary, body)
579 self._assert_notification(get_notification(), summary, body)
580
580
581 def test_update_notification_layout_change(self):
581 def test_update_notification_layout_change(self):
582− """Notification must allow updating its contents and layout while being displayed."""
582+ """Notification must allow updating its contents and layout while
583− self.launch_unity()
583+ being displayed."""
584− greeter = self.main_window.get_greeter()
584+ unity_proxy = self.launch_unity()
585− greeter.swipe()
585+ unlock_unity(unity_proxy)
586
586
587 notify_list = self._get_notifications_list()
587 notify_list = self._get_notifications_list()
588
588
@@ -603,8 +603,9 @@ class EphemeralNotificationsTests(NotificationsBase):
603 )
603 )
604 notification.show()
604 notification.show()
605
605
606+ get_notification = lambda: notify_list.wait_select_single(
606− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
607+ 'Notification', objectName='notification1')
607− self.assertThat(get_notification, Eventually(NotEquals(None)))
608+
608 self._assert_notification(
609 self._assert_notification(
609 get_notification(),
610 get_notification(),
610 summary,
611 summary,
@@ -626,9 +627,8 @@ class EphemeralNotificationsTests(NotificationsBase):
626
627
627 def test_append_hint(self):
628 def test_append_hint(self):
628 """Notification has to accumulate body-text using append-hint."""
629 """Notification has to accumulate body-text using append-hint."""
629− self.launch_unity()
630+ unity_proxy = self.launch_unity()
630− greeter = self.main_window.get_greeter()
631+ unlock_unity(unity_proxy)
631− greeter.swipe()
632
632
633 notify_list = self._get_notifications_list()
633 notify_list = self._get_notifications_list()
634
634
@@ -645,8 +645,9 @@ class EphemeralNotificationsTests(NotificationsBase):
645
645
646 notification.show()
646 notification.show()
647
647
648+ get_notification = lambda: notify_list.wait_select_single(
648− get_notification = lambda: notify_list.select_single('Notification', objectName='notification1')
649+ 'Notification', objectName='notification1')
649− self.assertThat(get_notification, Eventually(NotEquals(None)))
650+
650 notification = get_notification()
651 notification = get_notification()
651 self._assert_notification(
652 self._assert_notification(
652 notification,
653 notification,
@@ -662,7 +663,8 @@ class EphemeralNotificationsTests(NotificationsBase):
662 'Did you watch the air-race in Oshkosh last week?',
663 'Did you watch the air-race in Oshkosh last week?',
663 'Phil owned the place like no one before him!',
664 'Phil owned the place like no one before him!',
664 'Did really everything in the race work according to regulations?',
665 '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.',
666+ 'Somehow I think to remember Burt Williams did cut corners and '
667+ 'was not punished for this.',
666 'Hopefully the referees will watch the videos of the race.',
668 'Hopefully the referees will watch the videos of the race.',
667 'Burt could get fined with US$ 50000 for that rule-violation :)'
669 'Burt could get fined with US$ 50000 for that rule-violation :)'
668 ]
670 ]
@@ -677,11 +679,11 @@ class EphemeralNotificationsTests(NotificationsBase):
677 hints=[('x-canonical-append', 'true')]
679 hints=[('x-canonical-append', 'true')]
678 )
680 )
679 notification.show()
681 notification.show()
682+
680− get_notification = lambda: notify_list.select_single(
683+ get_notification = lambda: notify_list.wait_select_single(
681 'Notification',
684 'Notification',
682 objectName='notification1'
685 objectName='notification1'
683 )
686 )
684− self.assertThat(get_notification, Eventually(NotEquals(None)))
685 notification = get_notification()
687 notification = get_notification()
686 self._assert_notification(
688 self._assert_notification(
687 notification,
689 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+}
plugins/Unity/Indicators/Messaging/qml/utils.js → tests/mocks/Unity/Indicators/IndicatorWidget.qmlrenamed+8−7
@@ -14,14 +14,15 @@
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 * Authors:
16 * Authors:
17− * Renato Araujo Oliveira Filho <renato@canonical.com>
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18− * Olivier Tilloy <olivier.tilloy@canonical.com>
19 */
18 */
20
19
21−.pragma library
20+import QtQuick 2.0
21+import Unity.Indicators 0.1 as Indicators
22
22
23−function formatDate(timestamp) {
23+IndicatorBase {
24− // timestamp is in microseconds since epoch
24+ id: indicatorWidget
25− var date = new Date(timestamp / 1000);
25+
26− return Qt.formatDateTime(date, "hh:mm - MMM dd");
26+ enabled: false
27+ property int iconSize: height
27}
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_preview.cpp+9−1
@@ -16,9 +16,13 @@
16
16
17#include "fake_preview.h"
17#include "fake_preview.h"
18
18
19+Preview::Preview(QObject *parent): QObject(parent)
20+{
21+}
22+
19QString Preview::rendererName() const
23QString Preview::rendererName() const
20{
24{
21− return "foo";
25+ return "generic-preview";
22}
26}
23
27
24QString Preview::title() const
28QString Preview::title() const
@@ -61,3 +65,7 @@ void Preview::execute(const QString& actionId, const QHash<QString, QVariant>& h
61 Q_UNUSED(actionId);
65 Q_UNUSED(actionId);
62 Q_UNUSED(hints);
66 Q_UNUSED(hints);
63}
67}
68+
69+void Preview::cancelAction()
70+{
71+}
tests/mocks/Unity/fake_preview.h+2
@@ -51,6 +51,8 @@ public:
51
51
52 Q_INVOKABLE void execute(const QString& actionId, const QHash<QString, QVariant>& hints);
52 Q_INVOKABLE void execute(const QString& actionId, const QHash<QString, QVariant>& hints);
53
53
54+ Q_INVOKABLE void cancelAction();
55+
54Q_SIGNALS:
56Q_SIGNALS:
55 void previewChanged();
57 void previewChanged();
56};
58};
tests/mocks/Unity/fake_scope.cpp+21−17
@@ -14,31 +14,19 @@
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−// Self
18#include "fake_scope.h"
17#include "fake_scope.h"
19−
20−#include <dee.h>
18+#include "fake_preview.h"
21#include "paths.h"
19#include "paths.h"
22
20
23−#include "fake_preview.h"
21+#include <dee.h>
24
22
25static DeeModel* create_categories_model(unsigned category_count);
23static DeeModel* create_categories_model(unsigned category_count);
26static DeeModel* create_results_model(unsigned category_count, unsigned result_count);
24static DeeModel* create_results_model(unsigned category_count, unsigned result_count);
27
25
28// TODO: Implement remaining pieces
26// TODO: Implement remaining pieces
29
27
30−Scope::Scope(QObject* parent)
28+Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
31− : QObject(parent)
32− , m_visible(false)
33− , m_searching(false)
34− , m_isActive(false)
35− , m_categories(new Categories(this))
36− , m_results(new DeeListModel(this))
37{
29{
38− DeeModel* results_model = create_results_model(4, 30);
39− m_categories->setResultModel(results_model);
40− m_categories->setModel(create_categories_model(4));
41− m_results->setModel(results_model);
42}
30}
43
31
44Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
32Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
@@ -51,10 +39,17 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
51 , m_categories(new Categories(this))
39 , m_categories(new Categories(this))
52 , m_results(new DeeListModel(this))
40 , m_results(new DeeListModel(this))
53{
41{
54− DeeModel* results_model = create_results_model(4, 30);
42+ DeeModel* results_model = create_results_model(20, 300);
55 m_categories->setResultModel(results_model);
43 m_categories->setResultModel(results_model);
56− m_categories->setModel(create_categories_model(4));
44+ m_categories->setModel(create_categories_model(20));
57 m_results->setModel(results_model);
45 m_results->setModel(results_model);
46+
47+ m_timer.setInterval(1000);
48+ m_timer.setSingleShot(true);
49+ connect(&m_timer, &QTimer::timeout, [this]() {
50+ Preview *p = new Preview(this);
51+ Q_EMIT previewReady(p);
52+ });
58}
53}
59
54
60QString Scope::id() const {
55QString Scope::id() const {
@@ -168,6 +163,8 @@ void Scope::activate(const QVariant &uri, const QVariant &icon_hint, const QVari
168 Q_UNUSED(comment);
163 Q_UNUSED(comment);
169 Q_UNUSED(dnd_uri);
164 Q_UNUSED(dnd_uri);
170 Q_UNUSED(metadata);
165 Q_UNUSED(metadata);
166+
167+ m_timer.start();
171}
168}
172
169
173void Scope::preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
170void Scope::preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
@@ -183,6 +180,8 @@ void Scope::preview(const QVariant &uri, const QVariant &icon_hint, const QVaria
183 Q_UNUSED(comment);
180 Q_UNUSED(comment);
184 Q_UNUSED(dnd_uri);
181 Q_UNUSED(dnd_uri);
185 Q_UNUSED(metadata);
182 Q_UNUSED(metadata);
183+
184+ m_timer.start();
186}
185}
187
186
188static const gchar * categories_model_schema[] = {
187static const gchar * categories_model_schema[] = {
@@ -248,3 +247,8 @@ DeeModel* create_results_model(unsigned category_count, unsigned result_count) {
248 }
247 }
249 return results_model;
248 return results_model;
250}
249}
250+
251+void Scope::cancelActivation()
252+{
253+ m_timer.stop();
254+}
tests/mocks/Unity/fake_scope.h+7−2
@@ -17,10 +17,11 @@
17#ifndef FAKE_SCOPE_H
17#ifndef FAKE_SCOPE_H
18#define FAKE_SCOPE_H
18#define FAKE_SCOPE_H
19
19
20−// Qt
21−#include <QObject>
22#include "fake_categories.h"
20#include "fake_categories.h"
23
21
22+#include <QObject>
23+#include <QDebug>
24+
24class Preview;
25class Preview;
25
26
26class Scope : public QObject
27class Scope : public QObject
@@ -78,6 +79,8 @@ public:
78 const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
79 const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
79 const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
80 const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
80
81
82+ Q_INVOKABLE void cancelActivation();
83+
81Q_SIGNALS:
84Q_SIGNALS:
82 void idChanged(const QString&);
85 void idChanged(const QString&);
83 void nameChanged(const QString&);
86 void nameChanged(const QString&);
@@ -115,6 +118,8 @@ protected:
115
118
116 Categories* m_categories;
119 Categories* m_categories;
117 DeeListModel* m_results;
120 DeeListModel* m_results;
121+
122+ QTimer m_timer;
118};
123};
119
124
120#endif // FAKE_SCOPE_H
125#endif // FAKE_SCOPE_H
tests/mocks/Unity/fake_unity_plugin.cpp+3
@@ -22,6 +22,7 @@
22// local
22// local
23#include "fake_scopes.h"
23#include "fake_scopes.h"
24#include "fake_categories.h"
24#include "fake_categories.h"
25+#include "fake_preview.h"
25#include "categoryresults.h"
26#include "categoryresults.h"
26
27
27// External
28// External
@@ -37,8 +38,10 @@ void FakeUnityPlugin::registerTypes(const char *uri)
37
38
38 Q_ASSERT(uri == QLatin1String("Unity"));
39 Q_ASSERT(uri == QLatin1String("Unity"));
39
40
41+ qmlRegisterUncreatableType<Preview>(uri, 0, 1, "Preview", "Can't create Preview object in QML.");
40 qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
42 qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
41 qmlRegisterType<Scope>(uri, 0, 1, "Scope");
43 qmlRegisterType<Scope>(uri, 0, 1, "Scope");
42 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
44 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
43 qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create");
45 qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create");
46+ qmlRegisterType<DeeListModel>(uri, 0, 1, "DeeListModel");
44}
47}
tests/plugins/ListViewWithPageHeader/CMakeLists.txt+7
@@ -1,3 +1,6 @@
1+# add_qml_test macro
2+include(QmlTest)
3+
1# There's no cmake var for v8 include path :-/
4# There's no cmake var for v8 include path :-/
2# so create one
5# so create one
3LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
6LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
@@ -37,6 +40,10 @@ qt5_use_modules(listviewwithpageheadertestsectionexternalmodelExec Test Core Qml
37target_link_libraries(listviewwithpageheadertestsectionexternalmodelExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
40target_link_libraries(listviewwithpageheadertestsectionexternalmodelExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
38add_custom_target(testlistviewwithpageheadersectionexternalmodel ${CMAKE_CURRENT_BINARY_DIR}/listviewwithpageheadertestsectionexternalmodelExec -o ${CMAKE_BINARY_DIR}/testlistviewwithpageheadersectionexternalmodel.xml,xunitxml -o -,txt)
41add_custom_target(testlistviewwithpageheadersectionexternalmodel ${CMAKE_CURRENT_BINARY_DIR}/listviewwithpageheadertestsectionexternalmodelExec -o ${CMAKE_BINARY_DIR}/testlistviewwithpageheadersectionexternalmodel.xml,xunitxml -o -,txt)
39
42
43+set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
44+add_qml_test(. listviewwithpageheaderqml IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
45+
40add_dependencies(qmluitests testlistviewwithpageheader)
46add_dependencies(qmluitests testlistviewwithpageheader)
41add_dependencies(qmluitests testlistviewwithpageheadersection)
47add_dependencies(qmluitests testlistviewwithpageheadersection)
42add_dependencies(qmluitests testlistviewwithpageheadersectionexternalmodel)
48add_dependencies(qmluitests testlistviewwithpageheadersectionexternalmodel)
49+add_dependencies(qmluitests testlistviewwithpageheaderqml)
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+42
@@ -1589,6 +1589,28 @@ private Q_SLOTS:
1589 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1589 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1590 }
1590 }
1591
1591
1592+ void testMaximizeVisibleAreaTopWithHalfPageHeaderUpDown()
1593+ {
1594+ testMaximizeVisibleAreaTopWithHalfPageHeader();
1595+
1596+ changeContentY(-60);
1597+ changeContentY(15);
1598+
1599+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1600+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1601+ verifyItem(0, -140., 150., false);
1602+ verifyItem(1, 10., 200., false);
1603+ verifyItem(2, 210, 350., false);
1604+ verifyItem(3, 560, 350., true);
1605+ QCOMPARE(lvwph->m_minYExtent, 0.);
1606+ QCOMPARE(lvwph->m_clipItem->y(), 190.);
1607+ QCOMPARE(lvwph->m_clipItem->clip(), true);
1608+ QCOMPARE(lvwph->m_headerItem->y(), 140.);
1609+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1610+ QCOMPARE(lvwph->contentY(), 155.);
1611+ QCOMPARE(lvwph->m_headerItemShownHeight, 35.);
1612+ }
1613+
1592 void testMaximizeVisibleAreaBottomWithHalfPageHeader()
1614 void testMaximizeVisibleAreaBottomWithHalfPageHeader()
1593 {
1615 {
1594 changeContentY(430);
1616 changeContentY(430);
@@ -1724,6 +1746,9 @@ private Q_SLOTS:
1724
1746
1725 void testMaximizeVisibleAreaMoveUpAndShowHeader()
1747 void testMaximizeVisibleAreaMoveUpAndShowHeader()
1726 {
1748 {
1749+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1750+ QSKIP("This test is extremely unstable in 5.0.x");
1751+#endif
1727 model->setProperty(0, "size", 800);
1752 model->setProperty(0, "size", 800);
1728 verifyItem(0, 50., 800., false);
1753 verifyItem(0, 50., 800., false);
1729
1754
@@ -1824,6 +1849,23 @@ private Q_SLOTS:
1824 lvwph->positionAtBeginning();
1849 lvwph->positionAtBeginning();
1825 }
1850 }
1826
1851
1852+ void testHeaderPositionBug1240118()
1853+ {
1854+ scrollToBottom();
1855+ lvwph->showHeader();
1856+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1857+ QTest::qWait(100); // Make sure stuff is stable
1858+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 100));
1859+ model->setProperty(3, "size", 10);
1860+ model->setProperty(4, "size", 10);
1861+ model->setProperty(5, "size", 10);
1862+ model->setProperty(6, "size", 10);
1863+#if (QT_VERSION > QT_VERSION_CHECK(5, 0, 3))
1864+ QTRY_COMPARE(lvwph->m_minYExtent, 210.);
1865+#endif
1866+ QTRY_COMPARE(lvwph->m_headerItem->y(), -lvwph->m_minYExtent);
1867+ }
1868+
1827private:
1869private:
1828 QQuickView *view;
1870 QQuickView *view;
1829 ListViewWithPageHeader *lvwph;
1871 ListViewWithPageHeader *lvwph;
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cpp+81−1
@@ -1734,7 +1734,25 @@ private Q_SLOTS:
1734 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1734 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1735 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1735 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1736
1736
1737− changeContentY(140);
1737+ changeContentY(5);
1738+
1739+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1740+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1741+ verifyItem(0, 45., 90., false, "Agressive", false);
1742+ verifyItem(1, 135., 50., false, QString(), false);
1743+ verifyItem(2, 185., 150., false, QString(), false);
1744+ verifyItem(3, 335., 240., false, "Regular", false);
1745+ verifyItem(4, 575., 390., true, "Mild", true);
1746+ QCOMPARE(lvwph->m_minYExtent, 0.);
1747+ QCOMPARE(lvwph->m_clipItem->y(), 5.);
1748+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1749+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1750+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1751+ QCOMPARE(lvwph->contentY(), 5.);
1752+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1753+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1754+
1755+ changeContentY(135);
1738
1756
1739 QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1757 QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1740 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1758 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
@@ -2076,6 +2094,68 @@ private Q_SLOTS:
2076 QCOMPARE(spy.count(), 0);
2094 QCOMPARE(spy.count(), 0);
2077 }
2095 }
2078
2096
2097+ void testDownAndUp()
2098+ {
2099+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 1), Q_ARG(QVariant, 5));
2100+
2101+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 1);
2102+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
2103+ verifyItem(0, 50., 190., false, "Agressive", false);
2104+ QCOMPARE(lvwph->m_minYExtent, 0.);
2105+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
2106+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2107+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
2108+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
2109+ QCOMPARE(lvwph->contentY(), 0.);
2110+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2111+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2112+
2113+ QTest::qWait(1);
2114+
2115+ changeContentY(-15);
2116+
2117+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 1);
2118+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
2119+ verifyItem(0, 65., 190., false, "Agressive", false);
2120+ QCOMPARE(lvwph->m_minYExtent, 0.);
2121+ QCOMPARE(lvwph->m_clipItem->y(), -15.);
2122+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2123+ QCOMPARE(lvwph->m_headerItem->y(), -15.);
2124+ QCOMPARE(lvwph->m_headerItem->height(), 65.);
2125+ QCOMPARE(lvwph->contentY(), -15.);
2126+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2127+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2128+
2129+ changeContentY(25);
2130+
2131+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 1);
2132+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
2133+ verifyItem(0, 40., 190., false, "Agressive", false);
2134+ QCOMPARE(lvwph->m_minYExtent, 0.);
2135+ QCOMPARE(lvwph->m_clipItem->y(), 10.);
2136+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2137+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
2138+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
2139+ QCOMPARE(lvwph->contentY(), 10.);
2140+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2141+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2142+
2143+
2144+ QTest::mouseClick(view, Qt::LeftButton, Qt::NoModifier, QPoint(0, 0));
2145+
2146+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 1);
2147+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
2148+ verifyItem(0, 50., 190., false, "Agressive", false);
2149+ QCOMPARE(lvwph->m_minYExtent, 0.);
2150+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
2151+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2152+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
2153+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
2154+ QCOMPARE(lvwph->contentY(), 0.);
2155+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2156+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2157+ }
2158+
2079private:
2159private:
2080 QQuickView *view;
2160 QQuickView *view;
2081 ListViewWithPageHeader *lvwph;
2161 ListViewWithPageHeader *lvwph;
tests/plugins/ListViewWithPageHeader/tst_listviewwithpageheaderqml.qmlnew file+138
@@ -0,0 +1,138 @@
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 QtTest 1.0
19+import ListViewWithPageHeader 0.1
20+
21+Rectangle {
22+ width: 300
23+ height: 542
24+ color: "lightblue"
25+
26+ ListModel {
27+ id: model
28+
29+ function insertItem(index, size, type) {
30+ insert(index, { size: size, type: type });
31+ }
32+
33+ function removeItems(index, count) {
34+ remove(index, count);
35+ }
36+
37+ function moveItems(indexFrom, indexTo, count) {
38+ move(indexFrom, indexTo, count);
39+ }
40+
41+ ListElement { type: "Agressive"; size: 150 }
42+ ListElement { type: "Regular"; size: 200 }
43+ ListElement { type: "Mild"; size: 350 }
44+ ListElement { type: "Bold"; size: 350 }
45+ ListElement { type: "Bold"; size: 350 }
46+ ListElement { type: "Lazy"; size: 350 }
47+ }
48+
49+ ListViewWithPageHeader {
50+ id: listView
51+ width: parent.width
52+ anchors.top: parent.top
53+ anchors.bottom: parent.bottom
54+ model: model
55+ delegate: Rectangle {
56+ property bool timerDone: false
57+ width: parent.width - 20
58+ x: 10
59+ color: index % 2 == 0 ? "red" : "blue"
60+ height: size
61+ Text {
62+ text: index
63+ }
64+ }
65+
66+ pageHeader: Rectangle {
67+ color: "transparent"
68+ width: parent.width
69+ height: 50
70+ implicitHeight: 50
71+ Text {
72+ anchors.fill: parent
73+ text: "APPS"
74+ font.pixelSize: 40
75+ }
76+ }
77+
78+ sectionProperty: "type"
79+
80+ property int sectionHeaderHeight: 40
81+ sectionDelegate: Component {
82+ id: sectionHeaderComponent
83+ Rectangle {
84+ color: "green"
85+ height: listView.sectionHeaderHeight
86+ Text { text: section; font.pixelSize: 34 }
87+ anchors { left: parent.left; right: parent.right }
88+ }
89+ }
90+ }
91+
92+ Component {
93+ id: otherSectionHeaderComponent
94+ Rectangle {
95+ color: "green"
96+ height: 50
97+ Text { text: section; font.pixelSize: 34 }
98+ anchors { left: parent.left; right: parent.right }
99+ }
100+ }
101+
102+ SignalSpy {
103+ id: stickyHeaderHeigthSpy
104+ target: listView
105+ signalName: "stickyHeaderHeightChanged"
106+ }
107+
108+ TestCase {
109+ name: "ListViewWithPageHeaderTest"
110+ when: windowShown
111+
112+ function test_stickyHeaderHeightNewHeader() {
113+ stickyHeaderHeigthSpy.clear();
114+ compare(listView.stickyHeaderHeight, 40);
115+
116+ listView.sectionDelegate = otherSectionHeaderComponent;
117+ compare(listView.stickyHeaderHeight, 50);
118+ compare(stickyHeaderHeigthSpy.count, 1);
119+
120+ listView.sectionDelegate = sectionHeaderComponent;
121+ compare(listView.stickyHeaderHeight, 40);
122+ compare(stickyHeaderHeigthSpy.count, 2);
123+ }
124+
125+ function test_stickyHeaderHeightGrowingHeader() {
126+ stickyHeaderHeigthSpy.clear();
127+
128+ compare(listView.stickyHeaderHeight, 40);
129+
130+ listView.sectionHeaderHeight = 60;
131+ compare(listView.stickyHeaderHeight, 60);
132+ compare(stickyHeaderHeigthSpy.count, 1);
133+
134+ // Restore height for other tests
135+ listView.sectionHeaderHeight = 40;
136+ }
137+ }
138+}
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−26
@@ -1,33 +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− )
43+indicator_test(timeformattertest ADDITIONAL_LIBS IndicatorsQml)
tests/plugins/Unity/Indicators/timeformattertest.cppnew file+55
@@ -0,0 +1,55 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Lars Uebernickel <lars.uebernickel@canonical.com>
17+ */
18+
19+#include "timeformatter.h"
20+
21+#include <QtTest>
22+#include <QDebug>
23+
24+class TimeFormatterTest : public QObject
25+{
26+ Q_OBJECT
27+private Q_SLOTS:
28+
29+ void initTestCase()
30+ {
31+ setenv("UNITY_TEST_ENV", "1", 1);
32+ }
33+
34+ void cleanupTestCase()
35+ {
36+ unsetenv("UNITY_TEST_ENV");
37+ }
38+
39+ void testFormat()
40+ {
41+ const QString format = "hh:mm dd.MM.yy";
42+
43+ QDateTime time = QDateTime::currentDateTime();
44+
45+ TimeFormatter formatter;
46+ formatter.setTime(time.toMSecsSinceEpoch() * 1000);
47+ formatter.setFormat(format);
48+
49+ QCOMPARE(formatter.timeString(), time.toString(format));
50+ }
51+};
52+
53+QTEST_GUILESS_MAIN(TimeFormatterTest)
54+
55+#include "timeformattertest.moc"
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/plugins/Unity/resultstest.cpp+3−3
@@ -143,7 +143,7 @@ void ResultsTest::testSpecialIcons_data()
143 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
143 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
144 g_variant_builder_add(&builder, "{sv}", "content", g_variant_builder_end(&inner_builder));
144 g_variant_builder_add(&builder, "{sv}", "content", g_variant_builder_end(&inner_builder));
145
145
146− QTest::newRow("simple") << "file:///foo.mp3" << GVariantWrapper(g_variant_builder_end(&builder)) << "image://albumart/U2/War";
146+ QTest::newRow("simple") << "file:///foo.mp3" << GVariantWrapper(g_variant_builder_end(&builder)) << "image://albumart/artist=U2&album=War";
147
147
148 g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_VARDICT);
148 g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_VARDICT);
149 g_variant_builder_add(&inner_builder, "{sv}", "artist", g_variant_new_string("U2"));
149 g_variant_builder_add(&inner_builder, "{sv}", "artist", g_variant_new_string("U2"));
@@ -153,7 +153,7 @@ void ResultsTest::testSpecialIcons_data()
153 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
153 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
154 g_variant_builder_add(&builder, "{sv}", "content", inner);
154 g_variant_builder_add(&builder, "{sv}", "content", inner);
155
155
156− QTest::newRow("with-slash") << "file:///foo.mp3" << GVariantWrapper(g_variant_builder_end(&builder)) << "image://albumart/U2/War%2FJoshua%20tree";
156+ QTest::newRow("with-slash") << "file:///foo.mp3" << GVariantWrapper(g_variant_builder_end(&builder)) << "image://albumart/artist=U2&album=War/Joshua tree";
157
157
158 g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_VARDICT);
158 g_variant_builder_init(&inner_builder, G_VARIANT_TYPE_VARDICT);
159 g_variant_builder_add(&inner_builder, "{sv}", "artist", g_variant_new_string("U2"));
159 g_variant_builder_add(&inner_builder, "{sv}", "artist", g_variant_new_string("U2"));
@@ -166,7 +166,7 @@ void ResultsTest::testSpecialIcons_data()
166 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
166 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
167 g_variant_builder_add(&builder, "{sv}", "content", g_variant_builder_end(&inner_builder));
167 g_variant_builder_add(&builder, "{sv}", "content", g_variant_builder_end(&inner_builder));
168
168
169− QTest::newRow("nested") << "file:///foo.mp3" << GVariantWrapper(g_variant_builder_end(&builder)) << "image://albumart/U2/War";
169+ QTest::newRow("nested") << "file:///foo.mp3" << GVariantWrapper(g_variant_builder_end(&builder)) << "image://albumart/artist=U2&album=War";
170}
170}
171
171
172void ResultsTest::testSpecialIcons()
172void ResultsTest::testSpecialIcons()
tests/qmltests/CMakeLists.txt+5−5
@@ -13,11 +13,8 @@ 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)
19−add_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)
18add_qml_test(Panel IndicatorItem)
22add_qml_test(utils/Unity/Test UnityTest)
19add_qml_test(utils/Unity/Test UnityTest)
23
20
@@ -47,7 +44,6 @@ add_qml_test(Dash DashContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest
47add_qml_test(Dash DashPreview)
44add_qml_test(Dash DashPreview)
48add_qml_test(Dash GenericPreview)
45add_qml_test(Dash GenericPreview)
49add_qml_test(Dash GenericScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
46add_qml_test(Dash GenericScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
50−add_qml_test(Dash ScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
51add_qml_test(Dash FilterGrids IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins
47add_qml_test(Dash FilterGrids IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins
52 ${CMAKE_BINARY_DIR}/tests/mocks)
48 ${CMAKE_BINARY_DIR}/tests/mocks)
53add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
49add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
@@ -61,15 +57,19 @@ add_qml_test(Greeter Phone IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DE
61 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
57 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
62add_qml_test(Greeter Infographics IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
58add_qml_test(Greeter Infographics IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
63 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
59 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
60+add_qml_test(Greeter Clock IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
61+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
64add_qml_test(Hud Hud)
62add_qml_test(Hud Hud)
65add_qml_test(Hud Result)
63add_qml_test(Hud Result)
66add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
64add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
67−add_qml_test(Notifications Notifications IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_SOURCE_DIR}/tests/mocks)
65+add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
68add_qml_test(Panel IndicatorRow)
66add_qml_test(Panel IndicatorRow)
69add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
67add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
70add_qml_test(Panel MenuContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
68add_qml_test(Panel MenuContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
71add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
69add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
72add_qml_test(Panel SearchIndicator)
70add_qml_test(Panel SearchIndicator)
71+add_qml_test(Panel/Indicators DefaultIndicatorWidget IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
72+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
73add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
73add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
74 ${CMAKE_BINARY_DIR}/tests/mocks
74 ${CMAKE_BINARY_DIR}/tests/mocks
75 ${CMAKE_BINARY_DIR}/plugins)
75 ${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/Components/tst_PageHeader.qml+43−3
@@ -37,6 +37,10 @@ Item {
37 property alias searchEnabled : pageHeader.searchEntryEnabled
37 property alias searchEnabled : pageHeader.searchEntryEnabled
38 property alias searchQuery : pageHeader.searchQuery
38 property alias searchQuery : pageHeader.searchQuery
39
39
40+ function init() {
41+ searchEnabled = true;
42+ }
43+
40 function test_search_disabled() {
44 function test_search_disabled() {
41 searchEnabled = false
45 searchEnabled = false
42 pageHeader.resetSearch()
46 pageHeader.resetSearch()
@@ -151,12 +155,48 @@ Item {
151 scopeMock.searchInProgress = true
155 scopeMock.searchInProgress = true
152 compare(searchIndicator.running, true, "Search indicator isn't running.")
156 compare(searchIndicator.running, true, "Search indicator isn't running.")
153 tryCompare(primaryImage, "visible", false)
157 tryCompare(primaryImage, "visible", false)
154−
155− pageHeader.resetSearch()
156 }
158 }
157
159
158 function cleanup() {
160 function cleanup() {
159− scopeMock.searchInProgress = false
161+ scopeMock.searchInProgress = false;
162+ pageHeader.resetSearch();
163+ }
164+
165+ function test_popover() {
166+ searchEnabled = true;
167+ pageHeader.searchHistory.clear();
168+
169+ pageHeader.searchHistory.addQuery("Search1");
170+ pageHeader.searchHistory.addQuery("Search2");
171+
172+ pageHeader.triggerSearch();
173+
174+ var searchContainer = findChild(pageHeader, "searchContainer");
175+ verify(searchContainer !== undefined, "searchContainer != undefined");
176+ tryCompareFunction(function() { return searchContainer.popover !== null; }, true);
177+
178+ tryCompare(searchContainer.popover, "visible", true);
179+ }
180+
181+ function test_resetSearch_onPopupClose() {
182+ searchEnabled = true;
183+ pageHeader.searchHistory.clear();
184+
185+ pageHeader.searchHistory.addQuery("Search1");
186+ pageHeader.searchHistory.addQuery("Search2");
187+
188+ pageHeader.triggerSearch();
189+
190+ var searchContainer = findChild(pageHeader, "searchContainer");
191+ verify(searchContainer !== undefined, "searchContainer != undefined");
192+ tryCompareFunction(function() { return searchContainer.popover !== null; }, true);
193+ compare(searchContainer.popover.visible, true);
194+
195+ pageHeader.searchQuery = "test";
196+ tryCompareFunction( function() { return (searchContainer.popover===null || !searchContainer.popover.visible) }, true);
197+
198+ pageHeader.resetSearch();
199+ compare((searchContainer.popover===null || !searchContainer.popover.visible), true);
160 }
200 }
161 }
201 }
162
202
tests/qmltests/Components/tst_TimeLocal.qmldeleted−117
@@ -1,117 +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/Time.js" as TimeLocal
20−
21−TestCase {
22− name: "TimeLocal"
23−
24− property var readableDate
25−
26− function test_readableFromNow_dateUndefined() {
27− readableDate = TimeLocal.readableFromNow()
28− compare(readableDate, "", "readable date should have been null")
29− }
30−
31− function test_readableFromNow_dateNaN() {
32− readableDate = TimeLocal.readableFromNow("this is a string, not a date")
33− compare(readableDate, "", "readable date should have been null")
34− }
35−
36− function test_readableFromNow_justNow() {
37− readableDate = TimeLocal.readableFromNow(new Date())
38− compare(readableDate, "just now", "readable date should have been now")
39− }
40−
41− function test_readableFromNow_nowNaN() {
42− var fail = false
43− try {
44− TimeLocal.readableFromNow(new Date(), "this is a string, not a date")
45− } catch (err) {
46− fail = true
47− } finally {
48− compare(fail, true, "readable date should have thrown an exception")
49− }
50− }
51−
52− function cycleTime(diff, previous, next, units, endIterator) {
53− var now = new Date()
54− var time = now.getTime()
55− readableDate = TimeLocal.readableFromNow(time - diff, now)
56− compare(readableDate, previous, "different time predicted")
57− readableDate = TimeLocal.readableFromNow(time + diff, now)
58− compare(readableDate, next, "different time predicted")
59− for (var i = 2; i < endIterator; i++) {
60− var tmpDiff = i * diff
61− readableDate = TimeLocal.readableFromNow(time - tmpDiff, now)
62− compare(readableDate, i + " " + units + " ago", "different time predicted")
63− readableDate = TimeLocal.readableFromNow(time + tmpDiff, now)
64− compare(readableDate, "in " + i + " " + units, "different time predicted")
65− }
66− }
67−
68− function test_readableFromNow_seconds() {
69− cycleTime(1000, "a second ago", "in a second", "seconds", 60)
70− }
71−
72− function test_readableFromNow_minutes() {
73− cycleTime(1000 * 60, "a minute ago", "in a minute", "minutes", 60)
74− }
75−
76− function test_readableFromNow_hours() {
77− cycleTime(1000 * 60 * 60, "an hour ago", "in an hour", "hours", 24)
78− }
79−
80− function test_readableFromNow_days() {
81− cycleTime(1000 * 60 * 60 * 24, "yesterday", "tomorrow", "days", 7)
82− }
83−
84− function test_readableFromNow_weeks() {
85− var now = new Date()
86− for (var i = 7; i < 30; i++) {
87− readableDate = TimeLocal.readableFromNow(now.getTime() - i * 1000 * 60 * 60 * 24, now)
88− if (i < 14)
89− compare(readableDate, "a week ago", "different time predicted")
90− else if (i < 18)
91− compare(readableDate, "about 2 weeks ago", "different time predicted")
92− else if (i < 25)
93− compare(readableDate, "about 3 weeks ago", "different time predicted")
94− else
95− compare(readableDate, "about 4 weeks ago", "different time predicted")
96− }
97− for (var i = 7; i < 30; i++) {
98− readableDate = TimeLocal.readableFromNow(now.getTime() + i * 1000 * 60 * 60 * 24, now)
99− if (i < 14)
100− compare(readableDate, "in a week", "different time predicted")
101− else if (i < 18)
102− compare(readableDate, "in about 2 weeks", "different time predicted")
103− else if (i < 25)
104− compare(readableDate, "in about 3 weeks", "different time predicted")
105− else
106− compare(readableDate, "in about 4 weeks", "different time predicted")
107− }
108− }
109−
110− function test_readableFromNow_months() {
111− cycleTime(1000 * 60 * 60 * 24 * 30.45, "a month ago", "in a month", "months", 12)
112− }
113−
114− function test_readableFromNow_years() {
115− cycleTime(1000 * 60 * 60 * 24 * 366, "a year ago", "in a year", "years", 5)
116− }
117−}
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+3−68
@@ -19,13 +19,13 @@ import Unity 0.1
19
19
20import "../../../../Dash"
20import "../../../../Dash"
21
21
22−ScopeView {
22+GenericScopeView {
23 id: fakeScopeView
23 id: fakeScopeView
24
24
25 property alias backColor : back.color
25 property alias backColor : back.color
26
26
27 onEndReached: {
27 onEndReached: {
28− if (shell != undefined && shell.scopeStatus != undefined) {
28+ if (scope != undefined && shell != undefined && shell.scopeStatus != undefined) {
29 shell.scopeStatus[scope.id].endReached++;
29 shell.scopeStatus[scope.id].endReached++;
30 }
30 }
31 }
31 }
@@ -44,71 +44,6 @@ ScopeView {
44 id: back
44 id: back
45 anchors.fill: parent
45 anchors.fill: parent
46 color: "grey"
46 color: "grey"
47− }
47+ z: -1
48−
49− function randomBg()
50− {
51− var hex1=new Array("4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
52− var bg="#"+hex1[Math.floor(Math.random()*hex1.length)]+
53− hex1[Math.floor(Math.random()*hex1.length)]+
54− hex1[Math.floor(Math.random()*hex1.length)]+
55− hex1[Math.floor(Math.random()*hex1.length)]+
56− hex1[Math.floor(Math.random()*hex1.length)]+
57− hex1[Math.floor(Math.random()*hex1.length)]
58− return bg
59− }
60−
61−
62− ListView {
63− id: listView
64− anchors.fill: parent
65− model: scope ? scope.categories : null
66− orientation: ListView.Vertical
67−
68− delegate: Column {
69− id: column
70− width: listView.width
71− height: childrenRect.height
72−
73− Rectangle {
74− width: listView.width
75− height: units.gu(3)
76− color: randomBg()
77−
78− Text {
79− text: name
80− font.family: "Ubuntu"
81− font.weight: Font.Bold
82− font.pixelSize: 20
83− anchors.horizontalCenter: parent.horizontalCenter
84− }
85− }
86− GridView {
87− id: resultsGrid
88− model: results
89− cellWidth: units.gu(10); cellHeight: units.gu(10)
90− height: childrenRect.height
91− width: listView.width
92− interactive: false
93−
94− delegate: Component {
95− id: resultDelegate
96− Item {
97− width: resultsGrid.cellWidth; height: resultsGrid.cellHeight
98− Column {
99− anchors.verticalCenter: parent.verticalCenter
100− anchors.horizontalCenter: parent.horizontalCenter
101− Image {
102− width: units.gu(5)
103− height: units.gu(5)
104− source: icon
105− anchors.horizontalCenter: parent.horizontalCenter
106− }
107− Text { text: title; anchors.horizontalCenter: parent.horizontalCenter }
108− }
109− }
110− }
111− }
112− }
113 }
48 }
114}
49}
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+35−2
@@ -28,6 +28,18 @@ Item {
28
28
29 property ListModel searchHistory: ListModel {}
29 property ListModel searchHistory: ListModel {}
30
30
31+ Item {
32+ // Fake. Make a few components less noisy
33+ id: greeter
34+ signal shownChanged
35+ }
36+
37+ Item {
38+ // Fake. Make a few components less noisy
39+ id: panel
40+ signal searchClicked
41+ }
42+
31 property var scopeStatus: {
43 property var scopeStatus: {
32 'MockScope1': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
44 'MockScope1': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
33 'MockScope2': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
45 'MockScope2': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
@@ -111,10 +123,17 @@ Item {
111 clear_scope_status();
123 clear_scope_status();
112 dashContent.visible = true;
124 dashContent.visible = true;
113
125
114− scopesModel.clear();
115− // wait for dash to empty scopes.
116 var dashContentList = findChild(dashContent, "dashContentList");
126 var dashContentList = findChild(dashContent, "dashContentList");
117 verify(dashContentList != undefined);
127 verify(dashContentList != undefined);
128+ // TODO For Qt 5.2 remove this wait
129+ // and the tryCompare and see if it still crashes when
130+ // looping the test
131+ wait(1000);
132+ if (dashContentList.currentItem !== null) {
133+ tryCompare(dashContentList.currentItem, "moving", false);
134+ }
135+ scopesModel.clear();
136+ // wait for dash to empty scopes.
118 tryCompare(dashContentList, "count", 0);
137 tryCompare(dashContentList, "count", 0);
119 }
138 }
120
139
@@ -229,5 +248,19 @@ Item {
229 tryCompare(scopesModel.get(1), "isActive", data.active1);
248 tryCompare(scopesModel.get(1), "isActive", data.active1);
230 tryCompare(scopesModel.get(2), "isActive", data.active2);
249 tryCompare(scopesModel.get(2), "isActive", data.active2);
231 }
250 }
251+
252+ function test_hswipe_disabled_vswipe() {
253+ var dashContentList = findChild(dashContent, "dashContentList");
254+
255+ tryCompare(dashContentList, "interactive", true);
256+
257+ var startX = dashContentList.width/2;
258+ var startY = dashContentList.height/2;
259+ touchFlick(dashContentList, startX, startY, startX, startY - units.gu(80));
260+
261+ tryCompare(dashContentList.currentItem, "moving", true);
262+
263+ compare(dashContentList.interactive, false);
264+ }
232 }
265 }
233}
266}
tests/qmltests/Dash/tst_FilterGrids.qml+1−2
@@ -108,8 +108,7 @@ Rectangle {
108 function test_clicked_signal_data() {
108 function test_clicked_signal_data() {
109 return [
109 return [
110 {tag: "VideoFilterGrid", component: "Video/VideoFilterGrid.qml"},
110 {tag: "VideoFilterGrid", component: "Video/VideoFilterGrid.qml"},
111− {tag: "MusicFilterGrid", component: "Music/MusicFilterGrid.qml"},
111+ {tag: "MusicFilterGrid", component: "Music/MusicFilterGrid.qml"}
112− {tag: "ApplicationsFilterGrid", component: "Apps/ApplicationsFilterGrid.qml"}
113 ]
112 ]
114 }
113 }
115
114
tests/qmltests/Dash/tst_GenericScopeView.qml+148−13
@@ -23,11 +23,21 @@ import Ubuntu.Components 0.1
23import Unity.Test 0.1 as UT
23import Unity.Test 0.1 as UT
24
24
25Item {
25Item {
26+ id: shell
26 width: units.gu(120)
27 width: units.gu(120)
27 height: units.gu(80)
28 height: units.gu(80)
28
29
29 Scopes {
30 Scopes {
30 id: scopes
31 id: scopes
32+
33+ onLoadedChanged: {
34+ genericScopeView.scope = scopes.get(0)
35+ }
36+ }
37+
38+ property Item applicationManager: Item {
39+ signal sideStageFocusedApplicationChanged()
40+ signal mainStageFocusedApplicationChanged()
31 }
41 }
32
42
33 GenericScopeView {
43 GenericScopeView {
@@ -38,44 +48,169 @@ Item {
38 name: "GenericScopeView"
48 name: "GenericScopeView"
39 when: scopes.loaded
49 when: scopes.loaded
40
50
41− function init() {
42− genericScopeView.scope = scopes.get(0)
43− }
44−
45 function test_isCurrent() {
51 function test_isCurrent() {
46 var pageHeader = findChild(genericScopeView, "pageHeader");
52 var pageHeader = findChild(genericScopeView, "pageHeader");
47− var previewLoader = findChild(genericScopeView, "previewLoader");
53+ var previewListView = findChild(genericScopeView, "previewListView");
48 genericScopeView.isCurrent = true
54 genericScopeView.isCurrent = true
49 pageHeader.searchQuery = "test"
55 pageHeader.searchQuery = "test"
50− previewLoader.open = true
56+ previewListView.open = true
51 genericScopeView.isCurrent = false
57 genericScopeView.isCurrent = false
52 tryCompare(pageHeader, "searchQuery", "")
58 tryCompare(pageHeader, "searchQuery", "")
53 tryCompare(genericScopeView, "previewShown", false);
59 tryCompare(genericScopeView, "previewShown", false);
54 }
60 }
55
61
56 function test_showDash() {
62 function test_showDash() {
57− var previewLoader = findChild(genericScopeView, "previewLoader");
63+ var previewListView = findChild(genericScopeView, "previewListView");
58− previewLoader.open = true;
64+ previewListView.open = true;
59 scopes.get(0).showDash();
65 scopes.get(0).showDash();
60 tryCompare(genericScopeView, "previewShown", false);
66 tryCompare(genericScopeView, "previewShown", false);
61 }
67 }
62
68
63 function test_hideDash() {
69 function test_hideDash() {
64− var previewLoader = findChild(genericScopeView, "previewLoader");
70+ var previewListView = findChild(genericScopeView, "previewListView");
65− previewLoader.open = true;
71+ previewListView.open = true;
66 scopes.get(0).hideDash();
72 scopes.get(0).hideDash();
67 tryCompare(genericScopeView, "previewShown", false);
73 tryCompare(genericScopeView, "previewShown", false);
68 }
74 }
69
75
76+ function openPreview() {
77+ var categoryListView = findChild(genericScopeView, "categoryListView");
78+ categoryListView.positionAtBeginning();
79+
80+ var tile = findChild(genericScopeView, "delegate0");
81+ mouseClick(tile, tile.width / 2, tile.height / 2);
82+ var openEffect = findChild(genericScopeView, "openEffect");
83+ tryCompare(openEffect, "gap", 1);
84+ }
85+
86+ function checkArrowPosition(index) {
87+ var tile = findChild(genericScopeView, "delegate" + index);
88+ var tileCenter = tile.x + tile.width/2;
89+ var pointerArrow = findChild(genericScopeView, "pointerArrow");
90+ var pointerArrowCenter = pointerArrow.x + pointerArrow.width/2;
91+ compare(pointerArrowCenter, tileCenter, "Pointer did not move to tile");
92+ }
93+
94+ function closePreview() {
95+ var closePreviewMouseArea = findChild(genericScopeView, "closePreviewMouseArea");
96+ mouseClick(closePreviewMouseArea, closePreviewMouseArea.width / 2, closePreviewMouseArea.height / 2);
97+
98+ var previewListView = findChild(genericScopeView, "previewListView");
99+ tryCompare(previewListView, "open", false);
100+ var openEffect = findChild(genericScopeView, "openEffect");
101+ tryCompare(openEffect, "gap", 0);
102+
103+ var categoryListView = findChild(genericScopeView, "categoryListView");
104+ categoryListView.flick(0, units.gu(200));
105+ tryCompare(categoryListView, "flicking", false);
106+ }
107+
108+ function test_previewOpenClose() {
109+ var previewListView = findChild(genericScopeView, "previewListView");
110+ tryCompare(previewListView, "open", false);
111+
112+ openPreview();
113+
114+ // check for it opening successfully
115+ var currentPreviewItem = findChild(genericScopeView, "previewLoader0");
116+ tryCompareFunction(function() {
117+ var parts = currentPreviewItem.source.toString().split("/");
118+ var name = parts[parts.length - 1];
119+ return name == "DashPreviewPlaceholder.qml";
120+ },
121+ true);
122+ tryCompareFunction(function() {
123+ var parts = currentPreviewItem.source.toString().split("/");
124+ var name = parts[parts.length - 1];
125+ return name == "GenericPreview.qml";
126+ },
127+ true);
128+ tryCompare(currentPreviewItem, "progress", 1);
129+ tryCompare(previewListView, "open", true);
130+
131+ closePreview();
132+ tryCompare(previewListView, "open", false);
133+ }
134+
135+ function test_hiddenPreviewOpen() {
136+ var categoryListView = findChild(genericScopeView, "categoryListView");
137+ categoryListView.positionAtBeginning();
138+ waitForRendering(categoryListView);
139+ categoryListView.flick(0, -units.gu(80));
140+ tryCompare(categoryListView.flicking, false);
141+
142+ var tile = findChild(genericScopeView, "delegate0");
143+ mouseClick(tile, tile.width / 2, tile.height - 1);
144+ var openEffect = findChild(genericScopeView, "openEffect");
145+ tryCompare(openEffect, "gap", 1);
146+
147+ var pageHeader = findChild(genericScopeView, "pageHeader");
148+ verify(openEffect.positionPx >= pageHeader.height + categoryListView.stickyHeaderHeight);
149+ }
150+
151+ function test_previewCycle() {
152+ var previewListView = findChild(genericScopeView, "previewListView");
153+ tryCompare(previewListView, "open", false);
154+
155+ openPreview();
156+
157+ // wait for it to be loaded
158+ var currentPreviewItem = findChild(genericScopeView, "previewLoader0");
159+ tryCompareFunction(function() {
160+ var parts = currentPreviewItem.source.toString().split("/");
161+ var name = parts[parts.length - 1];
162+ return name == "GenericPreview.qml";
163+ },
164+ true);
165+ tryCompare(currentPreviewItem, "progress", 1);
166+ waitForRendering(currentPreviewItem);
167+
168+ checkArrowPosition(0);
169+
170+ // flick to the next previews
171+
172+ for (var i = 1; i < previewListView.count; ++i) {
173+
174+ mouseFlick(previewListView, previewListView.width - units.gu(1),
175+ previewListView.height / 2,
176+ units.gu(2),
177+ previewListView.height / 2);
178+
179+ // wait for it to be loaded
180+ var nextPreviewItem = findChild(genericScopeView, "previewLoader" + i);
181+ tryCompareFunction(function() {
182+ var parts = nextPreviewItem.source.toString().split("/");
183+ var name = parts[parts.length - 1];
184+ return name == "GenericPreview.qml";
185+ },
186+ true);
187+ tryCompare(nextPreviewItem, "progress", 1);
188+ waitForRendering(nextPreviewItem);
189+
190+ checkArrowPosition(i);
191+ }
192+ closePreview();
193+ }
194+
70 function test_show_spinner() {
195 function test_show_spinner() {
196+ openPreview();
71− var previewLoader = findChild(genericScopeView, "previewLoader");
197+ var previewListView = findChild(genericScopeView, "previewListView");
72− previewLoader.open = true;
198+ var previewLoader = findChild(genericScopeView, "previewLoader0");
73− previewLoader.source = "../../../Dash/Generic/GenericPreview.qml";
199+
74 previewLoader.item.showProcessingAction = true;
200 previewLoader.item.showProcessingAction = true;
75 var waitingForAction = findChild(genericScopeView, "waitingForActionMouseArea");
201 var waitingForAction = findChild(genericScopeView, "waitingForActionMouseArea");
76 tryCompare(waitingForAction, "enabled", true);
202 tryCompare(waitingForAction, "enabled", true);
77 previewLoader.closePreviewSpinner();
203 previewLoader.closePreviewSpinner();
78 tryCompare(waitingForAction, "enabled", false);
204 tryCompare(waitingForAction, "enabled", false);
205+
206+ closePreview();
207+ }
208+
209+ function test_changeScope() {
210+ genericScopeView.scope.searchQuery = "test"
211+ genericScopeView.scope = scopes.get(1)
212+ genericScopeView.scope = scopes.get(0)
213+ tryCompare(genericScopeView.scope, "searchQuery", "")
79 }
214 }
80 }
215 }
81 }
216 }
tests/qmltests/Dash/tst_ScopeView.qmldeleted−52
@@ -1,52 +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 Unity 0.1
20−import ".."
21−import "../../../Dash"
22−import Ubuntu.Components 0.1
23−
24−Item {
25− width: units.gu(120)
26− height: units.gu(80)
27−
28− Scopes {
29− id: scopes
30− }
31−
32− ScopeView {
33− id: scopeView
34− anchors.fill: parent
35−
36− TestCase {
37− name: "ScopeView"
38− when: scopes.loaded
39−
40− function init() {
41− scopeView.scope = scopes.get(0)
42− }
43−
44− function test_changeScope() {
45− scopeView.scope.searchQuery = "test"
46− scopeView.scope = scopes.get(1)
47− scopeView.scope = scopes.get(0)
48− tryCompare(scopeView.scope, "searchQuery", "")
49− }
50− }
51− }
52−}
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/Launcher/tst_Launcher.qml+47−11
@@ -363,25 +363,60 @@ Item {
363 var draggedItem = findChild(launcher, "launcherDelegate5")
363 var draggedItem = findChild(launcher, "launcherDelegate5")
364 var item0 = findChild(launcher, "launcherDelegate0")
364 var item0 = findChild(launcher, "launcherDelegate0")
365 var fakeDragItem = findChild(launcher, "fakeDragItem")
365 var fakeDragItem = findChild(launcher, "fakeDragItem")
366− var dndArea = findChild(launcher, "dndArea")
366+ var quickListShape = findChild(launcher, "quickListShape")
367
367
368 // Initial state
368 // Initial state
369− compare(dndArea.quickListPopover, null)
369+ compare(quickListShape.visible, false)
370
370
371 // Doing longpress
371 // Doing longpress
372 mousePress(draggedItem, draggedItem.width / 2, draggedItem.height / 2)
372 mousePress(draggedItem, draggedItem.width / 2, draggedItem.height / 2)
373 tryCompare(fakeDragItem, "visible", true) // Wait longpress happening
373 tryCompare(fakeDragItem, "visible", true) // Wait longpress happening
374− verify(dndArea.quickListPopover != null)
374+ tryCompare(quickListShape, "visible", true)
375
375
376 // Dragging a bit (> 1.5 gu)
376 // Dragging a bit (> 1.5 gu)
377 mouseMove(draggedItem, -units.gu(2), draggedItem.height / 2)
377 mouseMove(draggedItem, -units.gu(2), draggedItem.height / 2)
378
378
379 // QuickList needs to be closed when a drag operation starts
379 // QuickList needs to be closed when a drag operation starts
380− tryCompare(dndArea, "quickListPopover", null)
380+ tryCompare(quickListShape, "visible", false)
381
381
382 mouseRelease(draggedItem);
382 mouseRelease(draggedItem);
383 }
383 }
384
384
385+ function test_quicklist_positioning_data() {
386+ return [
387+ {tag: "top", flickTo: "top", itemIndex: 0},
388+ {tag: "bottom", flickTo: "bottom", itemIndex: 9}
389+ ];
390+ }
391+
392+ function test_quicklist_positioning(data) {
393+ revealer.dragLauncherIntoView();
394+ var quickList = findChild(launcher, "quickList")
395+ var draggedItem = findChild(launcher, "launcherDelegate" + data.itemIndex)
396+ var quickListShape = findChild(launcher, "quickListShape")
397+
398+ // Position launcher to where we need it
399+ var listView = findChild(launcher, "launcherListView");
400+ listView.flick(0, units.gu(200) * (data.flickTo === "top" ? 1 : -1));
401+ tryCompare(listView, "flicking", false);
402+
403+ // Doing longpress
404+ mousePress(draggedItem, draggedItem.width / 2, draggedItem.height / 2)
405+ tryCompare(quickListShape, "opacity", 0.8)
406+ mouseRelease(draggedItem);
407+
408+ verify(quickList.y >= units.gu(1))
409+ verify(quickList.y + quickList.height + units.gu(1) <= launcher.height)
410+
411+ // Click somewhere in the empty space to dismiss the quicklist
412+ mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
413+ tryCompare(quickListShape, "visible", false)
414+
415+ // Click somewhere in the empty space to dismiss the launcher
416+ mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
417+ revealer.waitUntilLauncherDisappears()
418+ }
419+
385 function test_quicklist_click_data() {
420 function test_quicklist_click_data() {
386 return [
421 return [
387 {tag: "non-clickable", index: 1, clickable: false },
422 {tag: "non-clickable", index: 1, clickable: false },
@@ -392,19 +427,20 @@ Item {
392 function test_quicklist_click(data) {
427 function test_quicklist_click(data) {
393 revealer.dragLauncherIntoView();
428 revealer.dragLauncherIntoView();
394 var clickedItem = findChild(launcher, "launcherDelegate5")
429 var clickedItem = findChild(launcher, "launcherDelegate5")
395− var dndArea = findChild(launcher, "dndArea")
430+ var quickList = findChild(launcher, "quickList")
431+ var quickListShape = findChild(launcher, "quickListShape")
396
432
397 // Initial state
433 // Initial state
398− compare(dndArea.quickListPopover, null)
434+ tryCompare(quickListShape, "visible", false)
399
435
400 // Doing longpress
436 // Doing longpress
401 mousePress(clickedItem, clickedItem.width / 2, clickedItem.height / 2)
437 mousePress(clickedItem, clickedItem.width / 2, clickedItem.height / 2)
402 tryCompare(clickedItem, "itemOpacity", 0) // Wait for longpress to happen
438 tryCompare(clickedItem, "itemOpacity", 0) // Wait for longpress to happen
403− verify(dndArea.quickListPopover != null)
439+ verify(quickListShape.visible, "QuickList must be visible")
404
440
405 mouseRelease(clickedItem);
441 mouseRelease(clickedItem);
406
442
407− var quickListEntry = findChild(dndArea.quickListPopover, "quickListEntry" + data.index)
443+ var quickListEntry = findChild(quickList, "quickListEntry" + data.index)
408
444
409 signalSpy.clear();
445 signalSpy.clear();
410 signalSpy.signalName = "quickListTriggered"
446 signalSpy.signalName = "quickListTriggered"
@@ -413,7 +449,7 @@ Item {
413
449
414 if (data.clickable) {
450 if (data.clickable) {
415 // QuickList needs to be closed when some clickable item is clicked
451 // QuickList needs to be closed when some clickable item is clicked
416− tryCompare(dndArea, "quickListPopover", null)
452+ tryCompare(quickListShape, "visible", false)
417
453
418 compare(signalSpy.count, 1, "Quicklist signal wasn't triggered")
454 compare(signalSpy.count, 1, "Quicklist signal wasn't triggered")
419 compare(signalSpy.signalArguments[0][0], LauncherModel.get(5).appId)
455 compare(signalSpy.signalArguments[0][0], LauncherModel.get(5).appId)
@@ -422,13 +458,13 @@ Item {
422 } else {
458 } else {
423
459
424 // QuickList must not be closed when a non-clickable item is clicked
460 // QuickList must not be closed when a non-clickable item is clicked
425− verify(dndArea.quickListPopover != null)
461+ verify(quickListShape.visible, "QuickList must be visible")
426
462
427 compare(signalSpy.count, 0, "Quicklist signal must NOT be triggered when clicking a non-clickable item")
463 compare(signalSpy.count, 0, "Quicklist signal must NOT be triggered when clicking a non-clickable item")
428
464
429 // Click somewhere in the empty space to dismiss the quicklist
465 // Click somewhere in the empty space to dismiss the quicklist
430 mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
466 mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
431− tryCompare(dndArea, "quickListPopover", null)
467+ tryCompare(quickListShape, "visible", false)
432 }
468 }
433 }
469 }
434 }
470 }
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+13−5
@@ -48,10 +48,12 @@ Item {
48
48
49 function get_window_data() {
49 function get_window_data() {
50 return [
50 return [
51+ {tag: "pinned", fullscreenFlag: false, alreadyOpen: false },
52+ {tag: "fullscreen", fullscreenFlag: true, alreadyOpen: false },
51− {tag: "pinned", fullscreenFlag: false },
53+ {tag: "pinned-alreadyOpen", fullscreenFlag: false, alreadyOpen: true },
52− {tag: "fullscreen", fullscreenFlag: true }
54+ {tag: "fullscreen-alreadyOpen", fullscreenFlag: true, alreadyOpen: true }
55+ ];
53− ]}
56+ }
54−
55
57
56 function init() {
58 function init() {
57 searchClicked = false;
59 searchClicked = false;
@@ -135,6 +137,10 @@ Item {
135 // expose more of the panel, binding it to the selected indicator and opening it's menu.
137 // expose more of the panel, binding it to the selected indicator and opening it's menu.
136 function test_drag_show(data) {
138 function test_drag_show(data) {
137 panel.fullscreenMode = data.fullscreenFlag;
139 panel.fullscreenMode = data.fullscreenFlag;
140+ if (data.alreadyOpen) {
141+ panel.indicators.show();
142+ tryCompare(panel.indicators, "fullyOpened", true);
143+ }
138
144
139 var indicatorRow = findChild(panel.indicators, "indicatorRow");
145 var indicatorRow = findChild(panel.indicators, "indicatorRow");
140 verify(indicatorRow != undefined);
146 verify(indicatorRow != undefined);
@@ -186,7 +192,9 @@ Item {
186 compare(menuContent.currentMenuIndex, i, "Menu conetent should be enabled for item at position " + i);
192 compare(menuContent.currentMenuIndex, i, "Menu conetent should be enabled for item at position " + i);
187
193
188 // init for next indicatorItem
194 // init for next indicatorItem
195+ if (!data.alreadyOpen) {
189− init();
196+ init();
197+ }
190 }
198 }
191 }
199 }
192
200
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+36
@@ -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
@@ -213,6 +214,8 @@ TestCase {
213
214
214 // speed is in pixels/second
215 // speed is in pixels/second
215 function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
216 function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
217+ // Make sure the item is rendered
218+ waitForRendering(item);
216
219
217 // Default to true for beginTouch if not present
220 // Default to true for beginTouch if not present
218 beginTouch = (beginTouch !== undefined) ? beginTouch : true
221 beginTouch = (beginTouch !== undefined) ? beginTouch : true
@@ -297,4 +300,37 @@ TestCase {
297 event.release(0 /* touchId */, x, y)
300 event.release(0 /* touchId */, x, y)
298 event.commit()
301 event.commit()
299 }
302 }
303+
304+ Component.onCompleted: {
305+ var rootItem = parent;
306+ while (rootItem.parent != undefined) {
307+ rootItem = rootItem.parent;
308+ }
309+ removeTimeConstraintsFromDirectionalDragAreas(rootItem);
310+ }
311+
312+ /*
313+ In qmltests, sequences of touch events are sent all at once, unlike in "real life".
314+ Also qmltests might run really slowly, e.g. when run from inside virtual machines.
315+ Thus to remove a variable that qmltests cannot really control, namely time, this
316+ function removes all constraints from DirectionalDragAreas that are sensible to
317+ elapsed time.
318+
319+ This effectively makes DirectionalDragAreas easier to fool.
320+ */
321+ function removeTimeConstraintsFromDirectionalDragAreas(item) {
322+
323+ // use duck-typing to identify a DirectionalDragArea
324+ if (item.minSpeed != undefined
325+ && item.maxSilenceTime != undefined
326+ && item.compositionTime != undefined) {
327+ item.minSpeed = 0;
328+ item.maxSilenceTime = 60 * 60 * 1000;
329+ item.compositionTime = 0;
330+ } else {
331+ for (var i in item.children) {
332+ removeTimeConstraintsFromDirectionalDragAreas(item.children[i]);
333+ }
334+ }
335+ }
300}
336}