on xenial help sign in
merge trunk
8182fb8Michał Sawicz
CODING+2−11
@@ -23,16 +23,10 @@ $ cd ~/unity8/trunk
23$ ./build --setup
23$ ./build --setup
24
24
25 this will:
25 this will:
26− - add ppa:ubuntu-unity/next
27 - install the required dependencies to build, as well as run on the desktop
26 - install the required dependencies to build, as well as run on the desktop
28 - it should also install unity-scope-home and unity-lens-application which
27 - it should also install unity-scope-home and unity-lens-application which
29 are technically "recommends", not strict dependencies
28 are technically "recommends", not strict dependencies
30
29
31−Note, once the PPA is added, the script runs apt-get update, if you have
32−any failures associated with it, the build script will bail out of the setup
33−and fail to install all the required dependencies.
34−
35−
36build Unity 8
30build Unity 8
37-------------
31-------------
38
32
@@ -75,14 +69,11 @@ Notes
75Running Unity 8 on devices
69Running Unity 8 on devices
76==========================
70==========================
77- Ubuntu Touch builds are currently only available in 13.10 flavour
71- Ubuntu Touch builds are currently only available in 13.10 flavour
78−- supported hardware should match one those listed here
72+- supported hardware should match one of those listed here
79 https://wiki.ubuntu.com/Touch/Devices#Running_fine
73 https://wiki.ubuntu.com/Touch/Devices#Running_fine
80- follow the Ubuntu Touch install instructions for your chosen device
74- follow the Ubuntu Touch install instructions for your chosen device
81 https://wiki.ubuntu.com/Touch/Install
75 https://wiki.ubuntu.com/Touch/Install
82−- make sure your device is connected to a WiFi network
76+- make sure your device is connected to a network
83−- If you haven’t already or if you’ve just freshly flashed your device
84− make sure you run phablet-network-setup which will allow package updates to
85− the device
86- also make sure you have your SSH key in ~/.ssh/id_rsa.pub (or install one
77- also make sure you have your SSH key in ~/.ssh/id_rsa.pub (or install one
87 on the device yourself)
78 on the device yourself)
88
79
Components/ApplicationManagerWrapper.qml+10−1
@@ -29,6 +29,8 @@ Item {
29 property bool keyboardVisible: ApplicationManager.keyboardVisible
29 property bool keyboardVisible: ApplicationManager.keyboardVisible
30 property int keyboardHeight: ApplicationManager.keyboardHeight
30 property int keyboardHeight: ApplicationManager.keyboardHeight
31
31
32+ property bool fake: ApplicationManager.fake ? ApplicationManager.fake : false
33+
32 Component.onCompleted: {
34 Component.onCompleted: {
33 // Start the watcher so that the ApplicationManager applications model can be populated.
35 // Start the watcher so that the ApplicationManager applications model can be populated.
34 ApplicationManager.startWatcher();
36 ApplicationManager.startWatcher();
@@ -121,9 +123,16 @@ Item {
121 desktopFile = "/usr/share/applications/share-app.desktop"
123 desktopFile = "/usr/share/applications/share-app.desktop"
122 } else if (favoriteApplication == ApplicationManager.BrowserApplication) {
124 } else if (favoriteApplication == ApplicationManager.BrowserApplication) {
123 desktopFile = "/usr/share/applications/webbrowser-app.desktop"
125 desktopFile = "/usr/share/applications/webbrowser-app.desktop"
124− } else if (favoriteApplication == 4) { // ApplicationManager.PhoneApplication
126+ } else if (favoriteApplication == ApplicationManager.PhoneApplication) {
125 desktopFile = "/usr/share/applications/phone-app.desktop"
127 desktopFile = "/usr/share/applications/phone-app.desktop"
128+ } else if (favoriteApplication == ApplicationManager.DialerApplication) {
129+ desktopFile = "/usr/share/applications/dialer-app.desktop"
130+ } else if (favoriteApplication == ApplicationManager.MessagingApplication) {
131+ desktopFile = "/usr/share/applications/messaging-app.desktop"
132+ } else if (favoriteApplication == ApplicationManager.AddressbookApplication) {
133+ desktopFile = "/usr/share/applications/address-book-app.desktop"
126 }
134 }
135+
127 applicationManager.focusRequested(desktopFile);
136 applicationManager.focusRequested(desktopFile);
128 }
137 }
129 }
138 }
Components/Stage.qml+14
@@ -39,6 +39,7 @@ Showable {
39 type == ApplicationInfo.MainStage ? applicationManager.mainStageApplications
39 type == ApplicationInfo.MainStage ? applicationManager.mainStageApplications
40 : applicationManager.sideStageApplications
40 : applicationManager.sideStageApplications
41 property bool fullyShown: false
41 property bool fullyShown: false
42+ property bool fullyHidden: true
42 readonly property var focusedApplication:
43 readonly property var focusedApplication:
43 type == ApplicationInfo.MainStage ? applicationManager.mainStageFocusedApplication
44 type == ApplicationInfo.MainStage ? applicationManager.mainStageFocusedApplication
44 : applicationManager.sideStageFocusedApplication
45 : applicationManager.sideStageFocusedApplication
@@ -249,6 +250,19 @@ Showable {
249 }
250 }
250 }
251 }
251
252
253+ Connections {
254+ target: stage.applications
255+ onCountChanged: { __discardObsoleteScreenshots(); }
256+ ignoreUnknownSignals: true
257+ }
258+ onFullyHiddenChanged: { __discardObsoleteScreenshots(); }
259+ function __discardObsoleteScreenshots() {
260+ if (stage.fullyHidden && stage.applications && stage.applications.count == 0) {
261+ stage.focusedApplicationWhenUsingScreenshots = undefined;
262+ stage.__hideScreenshots();
263+ }
264+ }
265+
252
266
253 SequentialAnimation {
267 SequentialAnimation {
254 id: showStartingApplicationAnimation
268 id: showStartingApplicationAnimation
Dash/DashApps.qml+1−1
@@ -87,7 +87,7 @@ ScopeView {
87 model: scopeView.scope.categories
87 model: scopeView.scope.categories
88
88
89 delegate: Item {
89 delegate: Item {
90− Component.onCompleted: if (index == 3) scopeView.installedModel = Qt.binding(function() { return model.results; });
90+ Component.onCompleted: if (categoryId == "installed") scopeView.installedModel = Qt.binding(function() { return model.results; });
91 }
91 }
92 }
92 }
93
93
Dash/DashHome.qml+1
@@ -26,6 +26,7 @@ import "Music"
26
26
27ScopeView {
27ScopeView {
28 id: root
28 id: root
29+ objectName: "DashHome"
29
30
30 onMovementStarted: listView.showHeader()
31 onMovementStarted: listView.showHeader()
31
32
Dash/DashMusic.qml+2−2
@@ -52,7 +52,7 @@ ScopeView {
52
52
53 function getRenderer(categoryId) {
53 function getRenderer(categoryId) {
54 switch (categoryId) {
54 switch (categoryId) {
55− case 1: return "Music/MusicCarousel.qml"
55+ case "featured": return "Music/MusicCarousel.qml"
56 default: return "Music/MusicFilterGrid.qml"
56 default: return "Music/MusicFilterGrid.qml"
57 }
57 }
58 }
58 }
@@ -69,7 +69,7 @@ ScopeView {
69 id: base
69 id: base
70 highlightWhenPressed: false
70 highlightWhenPressed: false
71
71
72− property int categoryId: id
72+ property string categoryId: model.categoryId
73
73
74 Loader {
74 Loader {
75 anchors { top: parent.top; left: parent.left; right: parent.right }
75 anchors { top: parent.top; left: parent.left; right: parent.right }
Dash/DashVideos.qml+3−4
@@ -53,7 +53,7 @@ ScopeView {
53
53
54 function getRenderer(categoryId) {
54 function getRenderer(categoryId) {
55 switch (categoryId) {
55 switch (categoryId) {
56− case 1: return "Video/VideosCarousel.qml"
56+ case "featured": return "Video/VideosCarousel.qml"
57 default: return "Video/VideosFilterGrid.qml"
57 default: return "Video/VideosFilterGrid.qml"
58 }
58 }
59 }
59 }
@@ -102,8 +102,7 @@ ScopeView {
102 delegate: ListItems.Base {
102 delegate: ListItems.Base {
103 id: base
103 id: base
104 highlightWhenPressed: false
104 highlightWhenPressed: false
105− property int categoryIndex: index
105+ property string categoryId: model.categoryId
106− property int categoryId: id
107
106
108 Loader {
107 Loader {
109 id: loader
108 id: loader
@@ -119,7 +118,7 @@ ScopeView {
119 var dataItem;
118 var dataItem;
120 // VideosCarousel and VideosFilterGrid have different
119 // VideosCarousel and VideosFilterGrid have different
121 // clicked signals, accomodate for that
120 // clicked signals, accomodate for that
122− if (categoryId == 1) {
121+ if (categoryId == "featured") {
123 var fileUri = delegateItem.model.uri.replace(/^[^:]+:/, "")
122 var fileUri = delegateItem.model.uri.replace(/^[^:]+:/, "")
124 dataItem = {fileUri: fileUri, nfoUri: delegateItem.model.comment}
123 dataItem = {fileUri: fileUri, nfoUri: delegateItem.model.comment}
125 } else {
124 } else {
Dash/GenericScopeView.qml+9
@@ -114,7 +114,16 @@ ScopeView {
114 }
114 }
115 }
115 }
116
116
117+ function getDefaultRendererId(contentType) {
118+ switch (contentType) {
119+ default: return "grid";
120+ }
121+ }
122+
117 function getRenderer(rendererId, contentType) {
123 function getRenderer(rendererId, contentType) {
124+ if (rendererId == "default") {
125+ rendererId = getDefaultRendererId(contentType);
126+ }
118 switch (rendererId) {
127 switch (rendererId) {
119 case "grid": {
128 case "grid": {
120 switch (contentType) {
129 switch (contentType) {
Greeter/Greeter.qml+2−3
@@ -34,7 +34,7 @@ Showable {
34
34
35 property alias dragHandleWidth: dragHandle.width
35 property alias dragHandleWidth: dragHandle.width
36 property alias model: greeterContentLoader.model
36 property alias model: greeterContentLoader.model
37− property bool locked: shown && multiUser && !greeterContentLoader.promptless
37+ property bool locked: shown && !LightDM.Greeter.promptless
38
38
39 readonly property bool narrowMode: !multiUser && width <= units.gu(60)
39 readonly property bool narrowMode: !multiUser && width <= units.gu(60)
40 readonly property bool multiUser: LightDM.Users.count > 1
40 readonly property bool multiUser: LightDM.Users.count > 1
@@ -59,7 +59,6 @@ Showable {
59 anchors.fill: parent
59 anchors.fill: parent
60 property var model: LightDM.Users
60 property var model: LightDM.Users
61 property int currentIndex: 0
61 property int currentIndex: 0
62− property bool promptless: item ? item.promptless : false
63 property var infographicModel: LightDM.Infographic
62 property var infographicModel: LightDM.Infographic
64
63
65 source: required ? "GreeterContent.qml" : ""
64 source: required ? "GreeterContent.qml" : ""
@@ -113,7 +112,7 @@ Showable {
113 // UI element)
112 // UI element)
114 distanceThreshold: 0
113 distanceThreshold: 0
115
114
116− enabled: !greeter.locked
115+ enabled: greeter.narrowMode || !greeter.locked
117
116
118 direction: Direction.Leftwards
117 direction: Direction.Leftwards
119 }
118 }
Greeter/GreeterContent.qml−1
@@ -23,7 +23,6 @@ MouseArea {
23 id: root
23 id: root
24 anchors.fill: parent
24 anchors.fill: parent
25
25
26− property bool promptless: loginLoader.status == Loader.Ready && LightDM.Greeter.promptless
27 property bool ready: wallpaper.status == Image.Ready
26 property bool ready: wallpaper.status == Image.Ready
28 property bool leftTeaserPressed: teasingMouseArea.pressed &&
27 property bool leftTeaserPressed: teasingMouseArea.pressed &&
29 teasingMouseArea.mouseX < teasingMouseArea.width / 2
28 teasingMouseArea.mouseX < teasingMouseArea.width / 2
Greeter/Lockscreen.qml+9−9
@@ -69,7 +69,7 @@ Showable {
69 left: parent.left
69 left: parent.left
70 right: parent.right
70 right: parent.right
71 verticalCenter: parent.verticalCenter
71 verticalCenter: parent.verticalCenter
72− verticalCenterOffset: root.alphaNumeric ? -units.gu(10) : 0
72+ verticalCenterOffset: root.alphaNumeric ? -units.gu(10) : -units.gu(4)
73 }
73 }
74 property bool resetting: false
74 property bool resetting: false
75
75
@@ -107,11 +107,11 @@ Showable {
107 Column {
107 Column {
108 anchors {
108 anchors {
109 left: parent.left
109 left: parent.left
110− top: pinPadLoader.bottom
111− topMargin: units.gu(4)
112− right: parent.right
113 bottom: parent.bottom
110 bottom: parent.bottom
111+ bottomMargin: units.gu(4)
112+ right: parent.right
114 }
113 }
114+ height: childrenRect.height
115 spacing: units.gu(1)
115 spacing: units.gu(1)
116
116
117 Icon {
117 Icon {
@@ -120,8 +120,8 @@ Showable {
120 width: height
120 width: height
121 anchors.horizontalCenter: parent.horizontalCenter
121 anchors.horizontalCenter: parent.horizontalCenter
122 name: "phone-app-call-symbolic"
122 name: "phone-app-call-symbolic"
123− color: "white"
123+ color: "#f3f3e7"
124− opacity: 0.9
124+ opacity: 0.6
125
125
126 MouseArea {
126 MouseArea {
127 anchors.fill: parent
127 anchors.fill: parent
@@ -130,9 +130,9 @@ Showable {
130 }
130 }
131
131
132 Label {
132 Label {
133− text: i18n.tr("Emergency call")
133+ text: i18n.tr("Emergency Call")
134− color: "white"
134+ color: "#f3f3e7"
135− opacity: 0.9
135+ opacity: 0.6
136 fontSize: "medium"
136 fontSize: "medium"
137 anchors.horizontalCenter: parent.horizontalCenter
137 anchors.horizontalCenter: parent.horizontalCenter
138 }
138 }
Greeter/PinLockscreen.qml+110−41
@@ -16,15 +16,17 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import Ubuntu.Components.ListItems 0.1
19import "../Components"
20import "../Components"
20
21
21Column {
22Column {
22 id: root
23 id: root
23 anchors.centerIn: parent
24 anchors.centerIn: parent
24− spacing: units.gu(2.5)
25+ spacing: units.gu(3.5)
25
26
26 property alias placeholderText: pinentryField.placeholderText
27 property alias placeholderText: pinentryField.placeholderText
27− property int padWidth: units.gu(32)
28+ property int padWidth: units.gu(34)
29+ property int padHeight: units.gu(28)
28 property int pinLength: 4
30 property int pinLength: 4
29
31
30 signal entered(string passphrase)
32 signal entered(string passphrase)
@@ -37,70 +39,137 @@ Column {
37 }
39 }
38 }
40 }
39
41
40− TextField {
42+
43+ UbuntuShape {
41 id: pinentryField
44 id: pinentryField
42 objectName: "pinentryField"
45 objectName: "pinentryField"
43 anchors.horizontalCenter: parent.horizontalCenter
46 anchors.horizontalCenter: parent.horizontalCenter
44− width: units.gu(32)
47+ color: "#55000000"
48+ width:root.padWidth
45 height: units.gu(5)
49 height: units.gu(5)
46− echoMode: TextInput.Password
50+ radius: "medium"
47− font.pixelSize: units.dp(44)
51+ property string text: ""
48− color: "white"
52+ property string placeholderText: ""
49− opacity: 0.9
50− hasClearButton: false
51− horizontalAlignment: Text.AlignHCenter
52−
53 onTextChanged: {
53 onTextChanged: {
54+ pinentryFieldLabel.text = "";
55+ for (var i = 0; i < text.length; ++i) {
56+ pinentryFieldLabel.text += "•";
57+ }
54− if (pinentryField.text.length === root.pinLength) {
58+ if (text.length === root.pinLength) {
55− root.entered(pinentryField.text);
59+ root.entered(text);
56 }
60 }
57 }
61 }
58
62
59− // Using a MouseArea to eat clicks. We don't want to disable the TextField for styling reasons
63+ Label {
60− MouseArea {
64+ id: pinentryFieldLabel
61− anchors.fill: parent
65+ anchors.centerIn: parent
66+ font.pixelSize: units.dp(44)
67+ color: "#f3f3e7"
68+ opacity: 0.6
69+ }
70+ Label {
71+ id: pinentryFieldPlaceHolder
72+ anchors.centerIn: parent
73+ color: "grey"
74+ text: parent.placeholderText
75+ visible: pinentryFieldLabel.text.length == 0
62 }
76 }
63 }
77 }
64
78
65− Grid {
79+ UbuntuShape {
66 anchors {
80 anchors {
67 left: parent.left
81 left: parent.left
68 right: parent.right
82 right: parent.right
69 margins: (parent.width - root.padWidth) / 2
83 margins: (parent.width - root.padWidth) / 2
70 }
84 }
85+ height: root.padHeight
86+ color: "#55000000"
87+ radius: "medium"
88+
89+ ThinDivider {
90+ anchors {
91+ left: parent.left
92+ right: parent.right
93+ top: parent.top
94+ topMargin: root.padHeight / 4
95+ }
96+ }
97+ ThinDivider {
98+ anchors {
99+ left: parent.left
100+ right: parent.right
101+ verticalCenter: parent.verticalCenter
102+ }
103+ }
104+ ThinDivider {
105+ anchors {
106+ left: parent.left
107+ right: parent.right
108+ bottom: parent.bottom
109+ bottomMargin: root.padHeight / 4
110+ }
111+ }
71
112
72− columns: 3
113+ ThinDivider {
73− spacing: units.gu(1)
114+ anchors.centerIn: parent
115+ anchors.horizontalCenterOffset: -root.padWidth / 6
116+ width: root.padHeight
117+ rotation: -90
118+ }
119+ ThinDivider {
120+ anchors.centerIn: parent
121+ anchors.horizontalCenterOffset: root.padWidth / 6
122+ width: root.padHeight
123+ rotation: -90
124+ }
74
125
75− Repeater {
126+ Grid {
76− model: 9
127+ anchors {
128+ left: parent.left
129+ right: parent.right
130+ margins: (parent.width - root.padWidth) / 2
131+ }
77
132
133+ columns: 3
134+
135+ Repeater {
136+ model: 9
137+
78− PinPadButton {
138+ PinPadButton {
79− objectName: "pinPadButton" + (index + 1)
139+ objectName: "pinPadButton" + (index + 1)
140+ width: root.padWidth / 3
141+ height: root.padHeight / 4
80− text: index + 1
142+ text: index + 1
81
143
82− onClicked: {
144+ onClicked: {
83− pinentryField.text = pinentryField.text + text
145+ pinentryField.text = pinentryField.text + text;
146+ }
84 }
147 }
85 }
148 }
86− }
87
149
88− PinPadButton {
150+ PinPadButton {
89− objectName: "pinPadButtonBack"
151+ objectName: "pinPadButtonBack"
152+ width: root.padWidth / 3
153+ height: root.padHeight / 4
90− iconName: "back"
154+ iconName: "back"
91− onClicked: root.cancel();
155+ onClicked: root.cancel();
156+ }
92
157
93− }
94− PinPadButton {
158+ PinPadButton {
95− objectName: "pinPadButton0"
159+ objectName: "pinPadButton0"
160+ width: root.padWidth / 3
161+ height: root.padHeight / 4
96− text: "0"
162+ text: "0"
97− onClicked: pinentryField.text = pinentryField.text + text
163+ onClicked: pinentryField.text = pinentryField.text + text
164+ }
98
165
99− }
100− PinPadButton {
166+ PinPadButton {
101− objectName: "pinPadButtonErase"
167+ objectName: "pinPadButtonErase"
168+ width: root.padWidth / 3
169+ height: root.padHeight / 4
102− iconName: "erase"
170+ iconName: "erase"
103− onClicked: pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1)
171+ onClicked: pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1)
172+ }
104 }
173 }
105 }
174 }
106
175
Greeter/PinPadButton.qml+5−16
@@ -17,28 +17,20 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19
19
20−UbuntuShape {
20+Item {
21 id: root
21 id: root
22− width: units.gu(10)
23− height: units.gu(7)
24− radius: "medium"
25
22
26 property alias text: label.text
23 property alias text: label.text
27 property alias iconName: icon.name
24 property alias iconName: icon.name
28
25
29 signal clicked()
26 signal clicked()
30
27
31− Behavior on color {
32− ColorAnimation { duration: 100 }
33− }
34−
35 Label {
28 Label {
36 id: label
29 id: label
37 anchors.centerIn: parent
30 anchors.centerIn: parent
38− color: "white"
31+ color: "#f3f3e7"
39− fontSize: "x-large"
32+ fontSize: "large"
40− font.weight: Font.Light
33+ font.weight: Font.DemiBold
41− opacity: 0.9
42 }
34 }
43
35
44 Icon {
36 Icon {
@@ -46,14 +38,11 @@ UbuntuShape {
46 height: units.gu(3)
38 height: units.gu(3)
47 width: height
39 width: height
48 anchors.centerIn: parent
40 anchors.centerIn: parent
49− color: "white"
41+ color: "#f3f3e7"
50− opacity: 0.9
51 }
42 }
52
43
53 MouseArea {
44 MouseArea {
54 anchors.fill: parent
45 anchors.fill: parent
55 onClicked: root.clicked()
46 onClicked: root.clicked()
56− onPressed: root.color = Qt.rgba(0, 0, 0, 0.3)
57− onReleased: root.color = Qt.rgba(0, 0, 0, 0)
58 }
47 }
59}
48}
Panel/IndicatorItem.qml+5
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Unity.Indicators 0.1 as Indicators
19import Unity.Indicators 0.1 as Indicators
20+import "../Components"
20
21
21Item {
22Item {
22 id: indicatorItem
23 id: indicatorItem
@@ -27,6 +28,7 @@ Item {
27 property var indicatorProperties: undefined
28 property var indicatorProperties: undefined
28
29
29 opacity: dimmed ? 0.4 : 1
30 opacity: dimmed ? 0.4 : 1
31+ Behavior on opacity { StandardAnimation {} }
30
32
31 // only visible when non-empty
33 // only visible when non-empty
32 visible: loader.item != undefined && loader.status == Loader.Ready ? loader.item.enabled : false
34 visible: loader.item != undefined && loader.status == Loader.Ready ? loader.item.enabled : false
@@ -53,5 +55,8 @@ Item {
53 width: parent.width
55 width: parent.width
54 anchors.top: parent.bottom
56 anchors.top: parent.bottom
55 visible: highlighted
57 visible: highlighted
58+
59+ opacity: highlighted ? 1 : 0
60+ Behavior on opacity { StandardAnimation {} }
56 }
61 }
57}
62}
Panel/IndicatorRow.qml+34−48
@@ -16,6 +16,7 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import "../Components"
19
20
20Item {
21Item {
21 id: indicatorRow
22 id: indicatorRow
@@ -25,21 +26,18 @@ Item {
25 property alias row: row
26 property alias row: row
26 property QtObject indicatorsModel: null
27 property QtObject indicatorsModel: null
27
28
28− Behavior on y {NumberAnimation {duration: 300; easing.type: Easing.OutCubic} }
29−
30 width: units.gu(40)
29 width: units.gu(40)
31 height: units.gu(3)
30 height: units.gu(3)
32
31
33− Component.onCompleted: setDefaultItem()
34−
35 function setDefaultItem() {
32 function setDefaultItem() {
36 // The leftmost indicator
33 // The leftmost indicator
37− var defaultItemIndex = 0
34+ setCurrentItem(0);
38− setItem(defaultItemIndex)
39 }
35 }
40
36
41− function setItem(index) {
37+ function setCurrentItem(index) {
38+ if (currentItemIndex !== index) {
42− currentItem = rowRepeater.itemAt(index)
39+ currentItem = rowRepeater.itemAt(index);
40+ }
43 }
41 }
44
42
45 Row {
43 Row {
@@ -54,51 +52,39 @@ Item {
54 objectName: "rowRepeater"
52 objectName: "rowRepeater"
55 model: indicatorsModel ? indicatorsModel : undefined
53 model: indicatorsModel ? indicatorsModel : undefined
56
54
57− IndicatorItem {
55+ Item {
58− id: indicatorItem
56+ id: itemWrapper
57+ height: indicatorRow.height
58+ width: childrenRect.width
59
59
60− property int ownIndex: index
60+ property int ownIndex: index
61+ property alias highlighted: indicatorItem.highlighted
62+ property alias dimmed: indicatorItem.dimmed
61
63
64+ IndicatorItem {
65+ id: indicatorItem
66+ height: parent.height
67+
68+ highlighted: indicatorRow.state != "initial" ? itemWrapper.ownIndex == indicatorRow.currentItemIndex : false
69+ dimmed: indicatorRow.state != "initial" ? itemWrapper.ownIndex != indicatorRow.currentItemIndex : false
70+
62− widgetSource: model.widgetSource
71+ widgetSource: model.widgetSource
72+ indicatorProperties : model.indicatorProperties
73+ }
63
74
64− indicatorProperties : model.indicatorProperties
75+ opacity: {
65− highlighted: indicatorRow.state == "reveal" || indicatorRow.state == "locked" || indicatorRow.state == "commit" ? ownIndex == indicatorRow.currentItemIndex : false
66− dimmed: { //See FIXME in Indicators regarding the "states" change
67− if (indicatorRow.state == "initial" || indicatorRow.state == "") {
68− return false;
69− } else if (indicatorRow.state == "hint") {
70− return true
71− } else {
72− return ownIndex != indicatorRow.currentItemIndex
73− }
74− }
75− height: indicatorRow.height
76− y: {
77− //FIXME: all indicators will be initial for now.
78− if (!highlighted && (indicatorRow.state == "locked" || indicatorRow.state == "commit")) {
76+ if (!indicatorItem.highlighted && (indicatorRow.state == "locked" || indicatorRow.state == "commit")) {
79− return -indicatorRow.height
77+ return 0.0;
80− } else {
78+ } else {
81− return 0
82− }
83− }
84− Behavior on y {
85− NumberAnimation{
86− duration: {
87− if (index == 0) {
88− return 250
79+ return 1.0;
89− } else if (index == 1) {
90− return 150
91− } else if (index == 2) {
92− return 550
93− } else if (index == 3) {
94− return 400
95− } else {
96− return 100 + Math.random() * 200
97− }
98− }
99− easing.type: Easing.OutCubic
100 }
80 }
101 }
81 }
82+ Behavior on opacity {
83+ StandardAnimation {
84+ // flow away from current index
85+ duration: (rowRepeater.count - Math.abs(indicatorRow.currentItemIndex - index)) * (500/rowRepeater.count)
86+ }
87+ }
102 }
88 }
103 }
89 }
104 }
90 }
Panel/Indicators.qml+89−102
@@ -25,16 +25,15 @@ import "../Components/Math.js" as MathLocal
25Showable {
25Showable {
26 id: indicators
26 id: indicators
27
27
28− property int referenceOpenedHeight: units.gu(71)
28+ property real openedHeight: units.gu(71)
29− property real openedHeight: pinnedMode ? referenceOpenedHeight - panelHeight
30− : referenceOpenedHeight
31 property int panelHeight: units.gu(3)
29 property int panelHeight: units.gu(3)
32 property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
30 property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
33
31
34 property int hintValue
32 property int hintValue
35− readonly property int lockThreshold: referenceOpenedHeight / 2
33+ readonly property int lockThreshold: openedHeight / 2
36 property bool fullyOpened: height == openedHeight
34 property bool fullyOpened: height == openedHeight
37 property bool partiallyOpened: height > panelHeight && !fullyOpened
35 property bool partiallyOpened: height > panelHeight && !fullyOpened
36+ property real visualBottom: Math.max(y+height, y+indicatorRow.y+indicatorRow.height)
38
37
39 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
38 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
40 // use its own values. Need to ask design about this.
39 // use its own values. Need to ask design about this.
@@ -43,6 +42,13 @@ Showable {
43 duration: 350
42 duration: 350
44 to: openedHeight
43 to: openedHeight
45 easing.type: Easing.OutCubic
44 easing.type: Easing.OutCubic
45+
46+ // Re-size if we've changed the openHeight while shown.
47+ onToChanged: {
48+ if (indicators.shown) {
49+ indicators.show();
50+ }
51+ }
46 }
52 }
47
53
48 hideAnimation: StandardAnimation {
54 hideAnimation: StandardAnimation {
@@ -56,28 +62,30 @@ Showable {
56
62
57 onHeightChanged: {
63 onHeightChanged: {
58 // need to use handle.get_height(). As the handle height depends on indicators.height changes (but this is called first!)
64 // need to use handle.get_height(). As the handle height depends on indicators.height changes (but this is called first!)
59− var contentProgress = indicators.height - handle.get_height();
65+ var revealProgress = indicators.height - panelHeight
60 if (!showAnimation.running && !hideAnimation.running) {
66 if (!showAnimation.running && !hideAnimation.running) {
67+ if (revealProgress == 0) {
61− if (contentProgress <= hintValue && indicators.state == "reveal") {
68+ indicators.state = "initial";
69+ } else if (revealProgress <= hintValue) {
62 indicators.state = "hint";
70 indicators.state = "hint";
63− } else if (contentProgress > hintValue && contentProgress < lockThreshold) {
71+ } else if (revealProgress > hintValue && revealProgress < lockThreshold) {
64 indicators.state = "reveal";
72 indicators.state = "reveal";
65− } else if (contentProgress >= lockThreshold && lockThreshold > 0) {
73+ } else if (revealProgress >= lockThreshold && lockThreshold > 0) {
66 indicators.state = "locked";
74 indicators.state = "locked";
67 }
75 }
68 }
76 }
69
77
70− if (contentProgress == 0) {
78+ if (revealProgress == 0) {
71 menuContent.releaseContent();
79 menuContent.releaseContent();
72 }
80 }
73 }
81 }
74
82
75 function calculateCurrentItem(xValue, useBuffer) {
83 function calculateCurrentItem(xValue, useBuffer) {
76− var rowCoordinates
84+ var rowCoordinates;
77− var itemCoordinates
85+ var itemCoordinates;
78− var currentItem
86+ var currentItem;
79− var distanceFromRightEdge
87+ var distanceFromRightEdge;
80− var bufferExceeded = false
88+ var bufferExceeded = false;
81
89
82 if (indicators.state == "commit" || indicators.state == "locked" || showAnimation.running || hideAnimation.running) return;
90 if (indicators.state == "commit" || indicators.state == "locked" || showAnimation.running || hideAnimation.running) return;
83
91
@@ -90,6 +98,14 @@ Showable {
90 MathLocal.clamp((indicators.height - handle.height - hintValue) /
98 MathLocal.clamp((indicators.height - handle.height - hintValue) /
91 (lockThreshold - hintValue), 0, 1);
99 (lockThreshold - hintValue), 0, 1);
92
100
101+ /*
102+ Vertical velocity check. Don't change the indicator if we're moving too quickly.
103+ */
104+ var verticalSpeed = Math.abs(yVelocityCalculator.calculate());
105+ if (verticalSpeed >= 0.05 && indicatorRow.currentItem!=null) {
106+ return;
107+ }
108+
93 /*
109 /*
94 Percentage of an indicator icon's width the user's press can stray horizontally from the
110 Percentage of an indicator icon's width the user's press can stray horizontally from the
95 focused icon before we change focus to another icon. E.g. a value of 0.5 means you must
111 focused icon before we change focus to another icon. E.g. a value of 0.5 means you must
@@ -110,7 +126,7 @@ Showable {
110 currentItem = indicatorRow.row.childAt(rowCoordinates.x, 0);
126 currentItem = indicatorRow.row.childAt(rowCoordinates.x, 0);
111 if (currentItem && currentItem != indicatorRow.currentItem ) {
127 if (currentItem && currentItem != indicatorRow.currentItem ) {
112 itemCoordinates = indicatorRow.row.mapToItem(currentItem, rowCoordinates.x, 0);
128 itemCoordinates = indicatorRow.row.mapToItem(currentItem, rowCoordinates.x, 0);
113− distanceFromRightEdge = (currentItem.width - itemCoordinates.x) / (currentItem.width)
129+ distanceFromRightEdge = (currentItem.width - itemCoordinates.x) / (currentItem.width);
114 if (Math.abs(currentItem.ownIndex - indicatorRow.currentItemIndex) > 1) {
130 if (Math.abs(currentItem.ownIndex - indicatorRow.currentItemIndex) > 1) {
115 bufferExceeded = true;
131 bufferExceeded = true;
116 } else {
132 } else {
@@ -123,6 +139,8 @@ Showable {
123 if ((!useBuffer || (useBuffer && bufferExceeded)) || indicatorRow.currentItem < 0 || indicatorRow.currentItem == null) {
139 if ((!useBuffer || (useBuffer && bufferExceeded)) || indicatorRow.currentItem < 0 || indicatorRow.currentItem == null) {
124 indicatorRow.currentItem = currentItem;
140 indicatorRow.currentItem = currentItem;
125 }
141 }
142+ } else if (!currentItem) {
143+ indicatorRow.setDefaultItem();
126 }
144 }
127 }
145 }
128
146
@@ -155,13 +173,20 @@ Showable {
155 left: parent.left
173 left: parent.left
156 right: parent.right
174 right: parent.right
157 top: indicatorRow.bottom
175 top: indicatorRow.bottom
158− bottom: parent.bottom
176+ bottom: handle.top
159 }
177 }
160 indicatorsModel: indicatorsModel
178 indicatorsModel: indicatorsModel
161 clip: !indicators.fullyOpened
179 clip: !indicators.fullyOpened
162
180
163− onMenuSelected: {
181+ Connections {
164− indicatorRow.setItem(index)
182+ target: indicatorRow
183+ onCurrentItemIndexChanged: menuContent.updateCurrentMenu();
184+ }
185+
186+ function updateCurrentMenu() {
187+ if (currentMenuIndex != indicatorRow.currentItemIndex) {
188+ currentMenuIndex = indicatorRow.currentItemIndex;
189+ }
165 }
190 }
166
191
167 //small shadow gradient at bottom of menu
192 //small shadow gradient at bottom of menu
@@ -188,7 +213,7 @@ Showable {
188 anchors {
213 anchors {
189 left: parent.left
214 left: parent.left
190 right: parent.right
215 right: parent.right
191− top: menuContent.bottom
216+ bottom: parent.bottom
192 }
217 }
193 height: get_height()
218 height: get_height()
194 clip: height < handleImage.height
219 clip: height < handleImage.height
@@ -212,33 +237,14 @@ Showable {
212 }
237 }
213 }
238 }
214
239
215− PanelSeparatorLine {
216− id: indicatorsSeparatorLine
217− visible: true
218− anchors {
219− top: handle.bottom
220− left: indicators.left
221− right: indicators.right
222− }
223− }
224−
225− BorderImage {
226− id: dropShadow
227− anchors {
228− top: indicators.top
229− bottom: indicatorsSeparatorLine.bottom
230− left: indicators.left
231− right: indicators.right
232− margins: -units.gu(1)
233− }
234− visible: indicators.height > panelHeight
235− source: "graphics/rectangular_dropshadow.sci"
236− }
237−
238 PanelBackground {
240 PanelBackground {
239 anchors.fill: indicatorRow
241 anchors.fill: indicatorRow
240 }
242 }
241
243
244+ IndicatorsDataModel {
245+ id: indicatorsModel
246+ }
247+
242 IndicatorRow {
248 IndicatorRow {
243 id: indicatorRow
249 id: indicatorRow
244 objectName: "indicatorRow"
250 objectName: "indicatorRow"
@@ -250,58 +256,45 @@ Showable {
250 indicatorsModel: indicatorsModel
256 indicatorsModel: indicatorsModel
251 state: indicators.state
257 state: indicators.state
252
258
253− onCurrentItemIndexChanged: menuContent.currentIndex = currentItemIndex
254−
255− }
256−
257− IndicatorsDataModel {
258− id: indicatorsModel
259− }
260−
261− Connections {
259+ Connections {
262− target: hideAnimation
260+ target: menuContent
263− onRunningChanged: {
261+ onCurrentMenuIndexChanged: {
264− if (hideAnimation.running) {
262+ indicatorRow.setCurrentItem(menuContent.currentMenuIndex);
265− indicators.state = "initial"
266− } else {
267− if (state == "initial") {
268− indicatorRow.setDefaultItem();
269− menuContent.releaseContent();
270− }
271 }
263 }
272 }
264 }
273 }
265 }
266+
274 Connections {
267 Connections {
275 target: showAnimation
268 target: showAnimation
276 onRunningChanged: {
269 onRunningChanged: {
277 if (showAnimation.running) {
270 if (showAnimation.running) {
278− indicators.calculateCurrentItem(dragHandle.touchX, false);
279 indicators.state = "commit";
271 indicators.state = "commit";
280 }
272 }
281 }
273 }
282 }
274 }
283
275
284 Connections {
276 Connections {
285− target: dragHandle
277+ target: hideAnimation
286− onTouchXChanged: {
278+ onRunningChanged: {
287− var buffer = dragHandle.dragging ? true : false;
279+ if (hideAnimation.running) {
288− indicators.calculateCurrentItem(dragHandle.touchX, buffer);
280+ indicators.state = "initial";
281+ indicatorRow.currentItem = null;
282+ }
289 }
283 }
290 }
284 }
291
285
292− // We start with pinned states. (default pinnedMode: true)
286+ property var activeDragHandle: showDragHandle.dragging ? showDragHandle : hideDragHandle.dragging ? hideDragHandle : null
293− states: pinnedModeStates
287+ // connections to the active drag handle
294− // because of dynamic assignment of states, we need to assign state after completion.
288+ Connections {
295− Component.onCompleted: state = "initial"
289+ target: activeDragHandle
296−
290+ onTouchXChanged: {
297− // changing states will reset state to "".
291+ indicators.calculateCurrentItem(activeDragHandle.touchX, true);
298− onPinnedModeChanged: {
292+ }
299− var last_state = state;
293+ onTouchSceneYChanged: {
300− states = (pinnedMode) ? pinnedModeStates : offScreenModeStates;
294+ yVelocityCalculator.trackedPosition = activeDragHandle.touchSceneY;
301− state = last_state;
295+ }
302 }
296 }
303
297
304− property var dragHandle: showDragHandle.dragging ? showDragHandle : hideDragHandle
305 DragHandle {
298 DragHandle {
306 id: showDragHandle
299 id: showDragHandle
307 anchors.bottom: parent.bottom
300 anchors.bottom: parent.bottom
@@ -315,7 +308,7 @@ Showable {
315 hintDisplacement: pinnedMode ? indicators.hintValue : 0
308 hintDisplacement: pinnedMode ? indicators.hintValue : 0
316 autoCompleteDragThreshold: maxTotalDragDistance / 2
309 autoCompleteDragThreshold: maxTotalDragDistance / 2
317 stretch: true
310 stretch: true
318− maxTotalDragDistance: openedHeight - handle.height
311+ maxTotalDragDistance: openedHeight - panelHeight
319 distanceThreshold: pinnedMode ? 0 : units.gu(3)
312 distanceThreshold: pinnedMode ? 0 : units.gu(3)
320
313
321 onStatusChanged: {
314 onStatusChanged: {
@@ -327,28 +320,40 @@ Showable {
327 DragHandle {
320 DragHandle {
328 id: hideDragHandle
321 id: hideDragHandle
329 anchors.fill: handle
322 anchors.fill: handle
330− height: panelHeight
331 direction: Direction.Upwards
323 direction: Direction.Upwards
332 enabled: indicators.shown
324 enabled: indicators.shown
333− hintDisplacement: units.gu(2)
325+ hintDisplacement: indicators.hintValue
334 autoCompleteDragThreshold: maxTotalDragDistance / 6
326 autoCompleteDragThreshold: maxTotalDragDistance / 6
335 stretch: true
327 stretch: true
336− maxTotalDragDistance: referenceOpenedHeight - 2*panelHeight
328+ maxTotalDragDistance: openedHeight - panelHeight
337 distanceThreshold: 0
329 distanceThreshold: 0
338 }
330 }
339
331
340− property list<State> offScreenModeStates: [
332+ AxisVelocityCalculator {
333+ id: yVelocityCalculator
334+ }
335+
336+ states: [
341 State {
337 State {
342 name: "initial"
338 name: "initial"
343 },
339 },
344 State {
340 State {
345 name: "hint"
341 name: "hint"
342+ PropertyChanges {
346− PropertyChanges { target: indicatorRow; y: panelHeight }
343+ target: indicatorRow;
344+ y: pinnedMode ? 0 : panelHeight
345+ }
346+ StateChangeScript {
347+ script: {
348+ if (activeDragHandle) {
349+ calculateCurrentItem(activeDragHandle.touchX, false);
350+ }
351+ }
352+ }
347 },
353 },
348 State {
354 State {
349 name: "reveal"
355 name: "reveal"
350 extend: "hint"
356 extend: "hint"
351− StateChangeScript { script: calculateCurrentItem(dragHandle.touchX, false); }
352 },
357 },
353 State {
358 State {
354 name: "locked"
359 name: "locked"
@@ -359,25 +364,7 @@ Showable {
359 extend: "hint"
364 extend: "hint"
360 }
365 }
361 ]
366 ]
362−
363− property list<State> pinnedModeStates: [
364− State {
365− name: "initial"
367+ state: "initial"
366− },
367− State {
368− name: "hint"
369− },
370− State {
371− name: "reveal"
372− StateChangeScript { script: calculateCurrentItem(dragHandle.touchX, false); }
373− },
374− State {
375− name: "locked"
376− },
377− State {
378− name: "commit"
379− }
380− ]
381
368
382 transitions: [
369 transitions: [
383 Transition {
370 Transition {
Panel/Indicators/client/IndicatorsClient.qml+8−9
@@ -27,16 +27,15 @@ Rectangle {
27
27
28 PageStack {
28 PageStack {
29 id: pages
29 id: pages
30−
31 anchors.fill: parent
30 anchors.fill: parent
32− Component.onCompleted: root.reset()
31+ Component.onCompleted: reset()
33− }
34
32
35− function reset() {
33+ function reset() {
36− pages.clear();
34+ clear();
37− var component = Qt.createComponent("IndicatorsList.qml");
35+ var component = Qt.createComponent("IndicatorsList.qml");
38− var page = component.createObject(pages);
36+ var page = component.createObject(pages);
39− console.log(component.errorString());
37+ console.log(component.errorString());
40− pages.push(page);
38+ push(page);
39+ }
41 }
40 }
42}
41}
Panel/Indicators/client/IndicatorsPage.qml+57−12
@@ -15,35 +15,80 @@
15 *
15 *
16 * Authors:
16 * Authors:
17 * Renato Araujo Oliveira Filho <renato@canonical.com>
17 * Renato Araujo Oliveira Filho <renato@canonical.com>
18+ * Nick Dedekind <nick.dedekind@canonical.com>
18 */
19 */
19
20
20import QtQuick 2.0
21import QtQuick 2.0
21import Ubuntu.Components 0.1
22import Ubuntu.Components 0.1
23+import Ubuntu.Components.ListItems 0.1 as ListItem
22
24
23Page {
25Page {
24− id: _page
26+ id: page
25
27
26 title: indicatorProperties && indicatorProperties.title ? indicatorProperties.title : ""
28 title: indicatorProperties && indicatorProperties.title ? indicatorProperties.title : ""
27 property variant indicatorProperties
29 property variant indicatorProperties
28− property alias pageSource : page_loader.source
30+ property string pageSource : pageLoader.source
29
31
30 anchors.fill: parent
32 anchors.fill: parent
31
33
34+ ListItem.Standard {
35+ id: visualCheckItem
36+ text: "Enable Visual Representation"
37+ control: Switch {
38+ id: visualCheck
39+ checked: true
40+ }
41+ }
42+
32 Loader {
43 Loader {
33− id: page_loader
44+ id: pageLoader
34− objectName: "page_loader"
45+ objectName: "pageLoader"
35
46
36− anchors.fill: parent
47+ anchors {
48+ top: visualCheckItem.bottom
49+ left: parent.left
50+ right: parent.right
51+ bottom: buttons.top
52+ topMargin: units.gu(2)
53+ bottomMargin: units.gu(2)
54+ }
55+ source : visualCheck.checked ? page.pageSource : "IndicatorsTree.qml"
37
56
38− onStatusChanged: {
57+ onLoaded: {
39− if (status == Loader.Ready) {
40− for(var pName in indicatorProperties) {
58+ for(var pName in indicatorProperties) {
41− if (item.hasOwnProperty(pName)) {
59+ if (item.hasOwnProperty(pName)) {
42− item[pName] = indicatorProperties[pName];
60+ item[pName] = indicatorProperties[pName];
43− }
44 }
61 }
45− item.start();
46 }
62 }
63+ item.start();
64+ }
65+ }
66+
67+ Item {
68+ id: buttons
69+ anchors {
70+ left: parent.left
71+ right: parent.right
72+ bottom: parent.bottom
73+ margins: units.gu(1)
74+ }
75+ height: childrenRect.height
76+
77+ Button {
78+ anchors {
79+ left: parent.left
80+ }
81+ text: "Back"
82+ onClicked: page.pageStack.reset()
83+ }
84+ Button {
85+ id: refresh
86+ visible: !visualCheck.checked
87+ anchors {
88+ right: parent.right
89+ }
90+ text: "Refresh"
91+ onClicked: pageLoader.item.refresh()
47 }
92 }
48 }
93 }
49}
94}
Panel/Indicators/client/IndicatorsTree.qmlnew file+62
@@ -0,0 +1,62 @@
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.dededkind@canonical.com>
18+ */
19+
20+import QtQuick 2.0
21+import Ubuntu.Components 0.1
22+import Unity.Indicators 0.1 as Indicators
23+import QMenuModel 0.1
24+import Ubuntu.Components.ListItems 0.1 as ListItem
25+
26+Page {
27+ id: page
28+ anchors.fill: parent
29+
30+ property alias busType: menuModel.busType
31+ property alias busName: menuModel.busName
32+ property string actionsObjectPath
33+ property var menuObjectPaths: undefined
34+ readonly property string device: "phone"
35+
36+ property string deviceMenuObjectPath: menuObjectPaths.hasOwnProperty(device) ? menuObjectPaths[device] : ""
37+
38+ function start() {
39+ menuModel.start();
40+ }
41+
42+ QDBusMenuModel {
43+ id: menuModel
44+ objectPath: page.deviceMenuObjectPath
45+ }
46+
47+ Indicators.ModelPrinter {
48+ id: printer
49+ model: menuModel
50+ }
51+
52+ Flickable {
53+ anchors.fill: parent
54+ contentHeight: all_data.height
55+ clip:true
56+ Text {
57+ id: all_data
58+ color: "white"
59+ text: printer.text
60+ }
61+ }
62+}
Panel/MenuContent.qml+2−2
@@ -24,7 +24,7 @@ Rectangle {
24
24
25 property QtObject indicatorsModel: null
25 property QtObject indicatorsModel: null
26 property bool __contentActive: false
26 property bool __contentActive: false
27− property alias currentIndex : menus.currentIndex
27+ property alias currentMenuIndex : menus.currentIndex
28 property color backgroundColor: "#221e1c" // FIXME not in palette yet
28 property color backgroundColor: "#221e1c" // FIXME not in palette yet
29 property int contentReleaseInterval: 20000
29 property int contentReleaseInterval: 20000
30
30
@@ -146,7 +146,7 @@ Rectangle {
146 Indicators.MenuContentActivator {
146 Indicators.MenuContentActivator {
147 id: menuActivator
147 id: menuActivator
148 running: content.__contentActive
148 running: content.__contentActive
149− baseIndex: content.currentIndex
149+ baseIndex: content.currentMenuIndex
150 count: indicatorsModel.count
150 count: indicatorsModel.count
151 }
151 }
152}
152}
Panel/Panel.qml+28−9
@@ -39,11 +39,8 @@ Item {
39 }
39 }
40 height: __panelMinusSeparatorLineHeight
40 height: __panelMinusSeparatorLineHeight
41 y: 0
41 y: 0
42− onYChanged: indicatorsMenu.y = y;
43
42
44− Behavior on y {
43+ Behavior on y { StandardAnimation {} }
45− NumberAnimation { duration: 200 }
46− }
47 }
44 }
48
45
49 PanelSeparatorLine {
46 PanelSeparatorLine {
@@ -78,18 +75,40 @@ Item {
78 id: indicatorsMenu
75 id: indicatorsMenu
79
76
80 anchors.right: parent.right
77 anchors.right: parent.right
81− y: 0
78+ y: panelBackground.y
82 width: root.indicatorsMenuWidth
79 width: root.indicatorsMenuWidth
83 shown: false
80 shown: false
84 hintValue: __panelMinusSeparatorLineHeight * 3
81 hintValue: __panelMinusSeparatorLineHeight * 3
85 panelHeight: __panelMinusSeparatorLineHeight
82 panelHeight: __panelMinusSeparatorLineHeight
86− referenceOpenedHeight: parent.height
83+ openedHeight: parent.height + (pinnedMode ? 0 : root.panelHeight)
87−
88 pinnedMode: !fullscreenMode
84 pinnedMode: !fullscreenMode
89
85
90 property real unitProgress: (height - panelHeight) / (openedHeight - panelHeight)
86 property real unitProgress: (height - panelHeight) / (openedHeight - panelHeight)
91 }
87 }
92
88
89+ PanelSeparatorLine {
90+ id: indicatorsSeparatorLine
91+ visible: true
92+ anchors {
93+ left: indicatorsMenu.left
94+ right: indicatorsMenu.right
95+ }
96+ y: indicatorsMenu.visualBottom
97+ }
98+
99+ BorderImage {
100+ id: dropShadow
101+ anchors {
102+ top: indicators.top
103+ bottom: indicatorsSeparatorLine.bottom
104+ left: indicators.left
105+ right: indicators.right
106+ margins: -units.gu(1)
107+ }
108+ visible: indicatorsMenu.height > indicatorsMenu.panelHeight
109+ source: "graphics/rectangular_dropshadow.sci"
110+ }
111+
93 SearchIndicator {
112 SearchIndicator {
94 id: search
113 id: search
95 objectName: "search"
114 objectName: "search"
@@ -98,14 +117,14 @@ Item {
98 state: {
117 state: {
99 if (parent.width < indicatorsMenu.width + width) {
118 if (parent.width < indicatorsMenu.width + width) {
100 if (indicatorsMenu.state != "initial") {
119 if (indicatorsMenu.state != "initial") {
101− return "hiddenUp";
120+ return "hidden";
102 }
121 }
103 }
122 }
104 if (root.searchVisible) {
123 if (root.searchVisible) {
105 return "visible";
124 return "visible";
106 }
125 }
107
126
108− return "hiddenUp";
127+ return "hidden";
109 }
128 }
110
129
111 width: units.gu(13)
130 width: units.gu(13)
Panel/SearchIndicator.qml+3−5
@@ -16,6 +16,7 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import "../Components"
19
20
20Item {
21Item {
21 id: search
22 id: search
@@ -40,8 +41,7 @@ Item {
40 width: parent.width
41 width: parent.width
41 height: parent.height
42 height: parent.height
42
43
43− Behavior on opacity {NumberAnimation {}}
44+ Behavior on opacity { StandardAnimation {} }
44− Behavior on y {NumberAnimation {duration: 300; easing.type: Easing.OutCubic}}
45
45
46 Image {
46 Image {
47 id: icon
47 id: icon
@@ -67,15 +67,13 @@ Item {
67 name: "visible"
67 name: "visible"
68 PropertyChanges {
68 PropertyChanges {
69 target: container
69 target: container
70− y: 0
71 opacity: 1
70 opacity: 1
72 }
71 }
73 },
72 },
74 State {
73 State {
75− name: "hiddenUp"
74+ name: "hidden"
76 PropertyChanges {
75 PropertyChanges {
77 target: container
76 target: container
78− y: -height
79 opacity: 0
77 opacity: 0
80 }
78 }
81 }
79 }
Shell.qml+77−33
@@ -19,6 +19,7 @@ import Ubuntu.Application 0.1
19import Ubuntu.Components 0.1
19import Ubuntu.Components 0.1
20import Ubuntu.Gestures 0.1
20import Ubuntu.Gestures 0.1
21import LightDM 0.1 as LightDM
21import LightDM 0.1 as LightDM
22+import Powerd 0.1
22import "Dash"
23import "Dash"
23import "Greeter"
24import "Greeter"
24import "Launcher"
25import "Launcher"
@@ -36,8 +37,8 @@ FocusScope {
36
37
37 // this is only here to select the width / height of the window if not running fullscreen
38 // this is only here to select the width / height of the window if not running fullscreen
38 property bool tablet: false
39 property bool tablet: false
39− width: tablet ? units.gu(160) : ApplicationArguments.hasGeometry() ? ApplicationArguments.width() : units.gu(40)
40+ width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
40− height: tablet ? units.gu(100) : ApplicationArguments.hasGeometry() ? ApplicationArguments.height() : units.gu(71)
41+ height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
41
42
42 property real edgeSize: units.gu(2)
43 property real edgeSize: units.gu(2)
43 property url default_background: shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg"
44 property url default_background: shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg"
@@ -121,19 +122,22 @@ FocusScope {
121 Keys.onVolumeUpPressed: volumeControl.volumeUp()
122 Keys.onVolumeUpPressed: volumeControl.volumeUp()
122 Keys.onVolumeDownPressed: volumeControl.volumeDown()
123 Keys.onVolumeDownPressed: volumeControl.volumeDown()
123
124
124− Keys.onReleased: {
125− if (event.key == Qt.Key_PowerOff) {
126− greeter.show()
127− }
128− }
129−
130 Item {
125 Item {
131 id: underlay
126 id: underlay
127+ objectName: "underlay"
132 anchors.fill: parent
128 anchors.fill: parent
129+
130+ // Whether the underlay is fully covered by opaque UI elements.
133− visible: !(panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth)
131+ property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth
134− && (stages.fullyHidden
132+
133+ // Whether the user should see the topmost application surface (if there's one at all).
134+ property bool applicationSurfaceShouldBeSeen:
135+ (mainStage.applications && mainStage.applications.count > 0)
135− || (stages.fullyShown && mainStage.usingScreenshots)
136+ && (!stages.fullyHidden && !mainStage.usingScreenshots)
136− || !stages.fullyShown && (mainStage.usingScreenshots || (sideStage.shown && sideStage.usingScreenshots)))
137+
138+ // NB! Application surfaces are stacked behing the shell one. So they can only be seen by the user
139+ // through the translucent parts of the shell surface.
140+ visible: !fullyCovered && !applicationSurfaceShouldBeSeen
137
141
138 Image {
142 Image {
139 id: backgroundImage
143 id: backgroundImage
@@ -151,6 +155,7 @@ FocusScope {
151
155
152 Dash {
156 Dash {
153 id: dash
157 id: dash
158+ objectName: "dash"
154
159
155 available: !greeter.shown && !lockscreen.shown
160 available: !greeter.shown && !lockscreen.shown
156 hides: [stages, launcher, panel.indicators]
161 hides: [stages, launcher, panel.indicators]
@@ -178,7 +183,7 @@ FocusScope {
178 }
183 }
179 }
184 }
180
185
181− // FIXME: only necessary because stagesRevealer.animatedProgress and
186+ // FIXME: only necessary because stagesOuterContainer.showProgress and
182 // greeterRevealer.animatedProgress are not animated
187 // greeterRevealer.animatedProgress are not animated
183 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
188 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
184 }
189 }
@@ -198,6 +203,7 @@ FocusScope {
198
203
199 Showable {
204 Showable {
200 id: stages
205 id: stages
206+ objectName: "stages"
201
207
202 x: width
208 x: width
203
209
@@ -254,6 +260,7 @@ FocusScope {
254
260
255 anchors.fill: parent
261 anchors.fill: parent
256 fullyShown: stages.fullyShown
262 fullyShown: stages.fullyShown
263+ fullyHidden: stages.fullyHidden
257 shouldUseScreenshots: !fullyShown
264 shouldUseScreenshots: !fullyShown
258 rightEdgeEnabled: !sideStage.enabled
265 rightEdgeEnabled: !sideStage.enabled
259
266
@@ -338,7 +345,7 @@ FocusScope {
338 }
345 }
339
346
340 DragHandle {
347 DragHandle {
341− id: stagesRevealer
348+ id: stagesDragHandle
342
349
343 anchors.top: parent.top
350 anchors.top: parent.top
344 anchors.bottom: parent.bottom
351 anchors.bottom: parent.bottom
@@ -346,7 +353,11 @@ FocusScope {
346
353
347 width: shell.edgeSize
354 width: shell.edgeSize
348 direction: Direction.Leftwards
355 direction: Direction.Leftwards
349− enabled: mainStage.applications.count > 0 || sideStage.applications.count > 0
356+ property bool haveApps: mainStage.applications.count > 0 || sideStage.applications.count > 0
357+
358+ maxTotalDragDistance: haveApps ? parent.width : parent.width * 0.7
359+ // Make autocompletion impossible when !haveApps
360+ edgeDragEvaluator.minDragDistance: haveApps ? maxTotalDragDistance * 0.1 : Number.MAX_VALUE
350 }
361 }
351 }
362 }
352 }
363 }
@@ -404,9 +415,6 @@ FocusScope {
404
415
405 dragHandleWidth: shell.edgeSize
416 dragHandleWidth: shell.edgeSize
406
417
407− property var previousMainApp: null
408− property var previousSideApp: null
409−
410 onShownChanged: {
418 onShownChanged: {
411 if (shown) {
419 if (shown) {
412 lockscreen.reset();
420 lockscreen.reset();
@@ -416,20 +424,6 @@ FocusScope {
416 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
424 LightDM.Greeter.authenticate(LightDM.Users.data(0, LightDM.UserRoles.NameRole));
417 }
425 }
418 greeter.forceActiveFocus();
426 greeter.forceActiveFocus();
419− // FIXME: *FocusedApplication are not updated when unfocused, hence the need to check whether
420− // the stage was actually shown
421− if (mainStage.fullyShown) greeter.previousMainApp = applicationManager.mainStageFocusedApplication;
422− if (sideStage.fullyShown) greeter.previousSideApp = applicationManager.sideStageFocusedApplication;
423− applicationManager.unfocusCurrentApplication();
424− } else {
425− if (greeter.previousMainApp) {
426− applicationManager.focusApplication(greeter.previousMainApp);
427− greeter.previousMainApp = null;
428− }
429− if (greeter.previousSideApp) {
430− applicationManager.focusApplication(greeter.previousSideApp);
431− greeter.previousSideApp = null;
432− }
433 }
427 }
434 }
428 }
435
429
@@ -451,6 +445,42 @@ FocusScope {
451 blockInput: greeter.shown || lockscreen.shown
445 blockInput: greeter.shown || lockscreen.shown
452 }
446 }
453
447
448+ Connections {
449+ id: powerConnection
450+ target: Powerd
451+
452+ property var previousMainApp: null
453+ property var previousSideApp: null
454+
455+ function setFocused(focused) {
456+ if (!focused) {
457+ // FIXME: *FocusedApplication are not updated when unfocused, hence the need to check whether
458+ // the stage was actually shown
459+ if (mainStage.fullyShown) powerConnection.previousMainApp = applicationManager.mainStageFocusedApplication;
460+ if (sideStage.fullyShown) powerConnection.previousSideApp = applicationManager.sideStageFocusedApplication;
461+ applicationManager.unfocusCurrentApplication();
462+ } else {
463+ if (powerConnection.previousMainApp) {
464+ applicationManager.focusApplication(powerConnection.previousMainApp);
465+ powerConnection.previousMainApp = null;
466+ }
467+ if (powerConnection.previousSideApp) {
468+ applicationManager.focusApplication(powerConnection.previousSideApp);
469+ powerConnection.previousSideApp = null;
470+ }
471+ }
472+ }
473+
474+ onPowerStateChange: {
475+ if (state == 0) { // suspend
476+ powerConnection.setFocused(false);
477+ greeter.show();
478+ } else if (state == 1) { // active
479+ powerConnection.setFocused(true);
480+ }
481+ }
482+ }
483+
454 Item {
484 Item {
455 id: overlay
485 id: overlay
456
486
@@ -536,7 +566,7 @@ FocusScope {
536 anchors.bottom: parent.bottom
566 anchors.bottom: parent.bottom
537 width: parent.width
567 width: parent.width
538 dragAreaWidth: shell.edgeSize
568 dragAreaWidth: shell.edgeSize
539− available: !greeter.locked
569+ available: !greeter.shown || greeter.narrowMode
540 onDashItemSelected: {
570 onDashItemSelected: {
541 greeter.hide()
571 greeter.hide()
542 // Animate if moving between application and dash
572 // Animate if moving between application and dash
@@ -631,4 +661,18 @@ FocusScope {
631
661
632 enabled: shell.applicationManager && shell.applicationManager.keyboardVisible
662 enabled: shell.applicationManager && shell.applicationManager.keyboardVisible
633 }
663 }
664+
665+ Label {
666+ anchors.fill: parent
667+ visible: applicationManager.fake
668+ text: "EARLY ALPHA\nNOT READY FOR USE"
669+ color: "lightgrey"
670+ opacity: 0.2
671+ font.weight: Font.Black
672+ horizontalAlignment: Text.AlignHCenter
673+ verticalAlignment: Text.AlignVCenter
674+ fontSizeMode: Text.Fit
675+ font.pixelSize: height/2
676+ rotation: -45
677+ }
634}
678}
build−1
@@ -36,7 +36,6 @@ BUILD_TYPE="debug"
36[ $# -eq 1 ] && BUILD_TYPE="$1"
36[ $# -eq 1 ] && BUILD_TYPE="$1"
37
37
38install_dependencies() {
38install_dependencies() {
39− [ -f /etc/apt/sources.list.d/ubuntu-unity-next-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:ubuntu-unity/next || exit 1
40 sudo apt-get update || exit 4
39 sudo apt-get update || exit 4
41 echo "Installing Unity 8 dependencies.."
40 echo "Installing Unity 8 dependencies.."
42 sudo apt-get install devscripts \
41 sudo apt-get install devscripts \
cmake/modules/Plugins.cmake+18−9
@@ -1,3 +1,9 @@
1+find_program(qmlplugindump_exe qmlplugindump)
2+
3+if(NOT qmlplugindump_exe)
4+ msg(FATAL_ERROR "Could not locate qmlplugindump.")
5+endif()
6+
1# Creates target for copying and installing qmlfiles
7# Creates target for copying and installing qmlfiles
2#
8#
3# export_qmlfiles(plugin sub_path)
9# export_qmlfiles(plugin sub_path)
@@ -40,16 +46,19 @@ macro(export_qmlplugin PLUGIN VERSION PLUGIN_SUBPATH)
40 set(multi_value_keywords TARGETS)
46 set(multi_value_keywords TARGETS)
41 cmake_parse_arguments(qmlplugin "" "" "${multi_value_keywords}" ${ARGN})
47 cmake_parse_arguments(qmlplugin "" "" "${multi_value_keywords}" ${ARGN})
42
48
49+ # Only try to generate .qmltypes if not cross compiling
50+ if(NOT CMAKE_CROSSCOMPILING)
43− # create the plugin.qmltypes file
51+ # create the plugin.qmltypes file
44− add_custom_target(${PLUGIN}-qmltypes ALL
52+ add_custom_target(${PLUGIN}-qmltypes ALL
45− COMMAND qmlplugindump -notrelocatable ${PLUGIN} ${VERSION} ${CMAKE_BINARY_DIR}/plugins > ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
53+ COMMAND ${qmlplugindump_exe} -notrelocatable ${PLUGIN} ${VERSION} ${CMAKE_BINARY_DIR}/plugins > ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
46− )
54+ )
47− add_dependencies(${PLUGIN}-qmltypes ${PLUGIN}-qmlfiles ${qmlplugin_TARGETS})
55+ add_dependencies(${PLUGIN}-qmltypes ${PLUGIN}-qmlfiles ${qmlplugin_TARGETS})
48
56
49− # install the qmltypes file.
57+ # install the qmltypes file.
50− install(FILES ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
58+ install(FILES ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
51− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
59+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
52− )
60+ )
61+ endif()
53
62
54 # install the additional targets
63 # install the additional targets
55 install(TARGETS ${qmlplugin_TARGETS}
64 install(TARGETS ${qmlplugin_TARGETS}
debian/changelog+236
@@ -1,3 +1,239 @@
1+unity8 (7.81.3+13.10.20130809-0ubuntu1) saucy; urgency=low
2+
3+ [ Michał Sawicz ]
4+ * Prepare unity8 for cross-building.
5+
6+ [ Ubuntu daily release ]
7+ * Automatic snapshot from revision 176
8+
9+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 09 Aug 2013 02:32:10 +0000
10+
11+unity8 (7.81.3+13.10.20130808-0ubuntu1) saucy; urgency=low
12+
13+ [ Michał Sawicz ]
14+ * Re-enable battery slider test.
15+
16+ [ Nick Dedekind ]
17+ * Workaround for non-deletion of indicator page menu items. (LP:
18+ #1183065, #1206991)
19+
20+ [ Albert Astals ]
21+ * LVPWH: Fix regression handling the sticky top section culling r166
22+ introduced the regression, this fixes it+tests.
23+ * Implement+test the maximizeVisibleArea function Tries to show as
24+ much possible of an index that is already shown on screen Will be
25+ used for the dash category expansion.
26+
27+ [ Ubuntu daily release ]
28+ * Automatic snapshot from revision 174
29+
30+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 08 Aug 2013 15:23:17 +0000
31+
32+unity8 (7.81.3+13.10.20130807-0ubuntu1) saucy; urgency=low
33+
34+ [ Michał Sawicz ]
35+ * Drop ppa:ubuntu-unity/next.
36+ * Revert revision 161 that causes issues with invalid background.
37+
38+ [ Albert Astals ]
39+ * Fix off by one in the culling condition If you are on 0 and your
40+ height is 1 and viewport starts at 1 you have to be culled since you
41+ are not visible.
42+
43+ [ Ubuntu daily release ]
44+ * Automatic snapshot from revision 168
45+
46+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 07 Aug 2013 02:32:00 +0000
47+
48+unity8 (7.81.3+13.10.20130806-0ubuntu1) saucy; urgency=low
49+
50+ [ Michael Terry ]
51+ * Show the greeter when powerd tells us to, not just whenever we press
52+ the power key. (LP: #1186256)
53+
54+ [ Ubuntu daily release ]
55+ * Automatic snapshot from revision 164
56+
57+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 06 Aug 2013 03:43:01 +0000
58+
59+unity8 (7.81.3+13.10.20130805-0ubuntu1) saucy; urgency=low
60+
61+ [ Michael Terry ]
62+ * Fixes the lockscreen and swiping on the greeter still being possible
63+ even when in tablet mode. (LP: #1204984)
64+ * Watch powerd signals to notice a sleep and unfocus current app when
65+ that happens.
66+
67+ [ Michael Zanetti ]
68+ * make findChild also find invisible childs This considerably
69+ increases the amount of items to be searched up to a level where
70+ testShell didn't finish any more with searching. Hence this commit
71+ also changes findChild to do a breadth-first instead of a depth-
72+ first search.
73+ * Read background from GSettings or fallback to default_background.
74+
75+ [ Andrea Cimitan ]
76+ * Read background from GSettings or fallback to default_background.
77+
78+ [ Albert Astals ]
79+ * Make LVWPH provide a delegateIndex for sectionHeaders This way we
80+ can match the sectionHeader to the model easier in the qml/js side .
81+ * Fix tryCompare call The 4th parameter of tryCompare is timeout not
82+ message .
83+
84+ [ Daniel d'Andrada ]
85+ * Read background from GSettings or fallback to default_background.
86+
87+ [ Ubuntu daily release ]
88+ * Automatic snapshot from revision 162
89+
90+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 05 Aug 2013 02:32:05 +0000
91+
92+unity8 (7.81.3+13.10.20130802-0ubuntu1) saucy; urgency=low
93+
94+ [ Michael Terry ]
95+ * Make hud autopilot tests more reliable by fixing how it calculates
96+ relative coordinates.
97+
98+ [ Albert Astals ]
99+ * Only update the "section" if we are not culling the item If the item
100+ is not shown we should not care about its section.
101+
102+ [ Ubuntu daily release ]
103+ * Automatic snapshot from revision 155
104+
105+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 02 Aug 2013 02:40:11 +0000
106+
107+unity8 (7.81.3+13.10.20130801.1-0ubuntu1) saucy; urgency=low
108+
109+ [ Michał Sawicz ]
110+ * Add a disclaimer for the fake applications plugin.
111+
112+ [ Nick Dedekind ]
113+ * Removed animations from fake indicator pages.
114+
115+ [ Ubuntu daily release ]
116+ * Automatic snapshot from revision 152
117+
118+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 01 Aug 2013 14:30:40 +0000
119+
120+unity8 (7.81.3+13.10.20130801ubuntu.unity.next-0ubuntu1) saucy; urgency=low
121+
122+ [ Michael Zanetti ]
123+ * implemented new Lockscreen design.
124+
125+ [ Michał Sawicz ]
126+ * Fix mock VideoPreview to use the string categoryId as well.
127+
128+ [ Nick Dedekind ]
129+ * Added a text tree representation of the qmenumodel to the
130+ indicators-client application.
131+
132+ [ Albert Astals ]
133+ * Don't need deelistmodel here.
134+
135+ [ Ubuntu daily release ]
136+ * Automatic snapshot from revision 149 (ubuntu-unity/next)
137+
138+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 01 Aug 2013 02:32:03 +0000
139+
140+unity8 (7.81.3+13.10.20130730ubuntu.unity.next-0ubuntu1) saucy; urgency=low
141+
142+ [ Michał Sawicz ]
143+ * Adapt to Qt 5.1.
144+
145+ [ Albert Astals ]
146+ * Adapt to Qt 5.1.
147+
148+ [ Ubuntu daily release ]
149+ * Automatic snapshot from revision 143 (ubuntu-unity/next)
150+
151+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 30 Jul 2013 02:33:12 +0000
152+
153+unity8 (7.81.3+13.10.20130729ubuntu.unity.next-0ubuntu1) saucy; urgency=low
154+
155+ [ Michal Hruby ]
156+ * Remove the variant conversions methods as they were moved to dee-qt.
157+
158+ [ Michał Sawicz ]
159+ * Re-enable passphrase tests under UInput.
160+ * Use the new string categoryIds in custom video and music scope
161+ views. (LP: #1199322)
162+
163+ [ Nick Dedekind ]
164+ * Behavioural changes for indicators - Part 1 - Use standard
165+ animations. - Search bar animation less distracting. - Hinting
166+ animation shows header. - Vertical velocity detector to reduce
167+ accidental menu switches in dragging phase.
168+
169+ [ Gustavo Pichorim Boiko ]
170+ * Add entries to the new applications resulted from the split of the
171+ phone-app.
172+
173+ [ Ubuntu daily release ]
174+ * Automatic snapshot from revision 141 (ubuntu-unity/next)
175+
176+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 29 Jul 2013 03:41:07 +0000
177+
178+unity8 (7.81.3+13.10.20130726ubuntu.unity.next-0ubuntu1) saucy; urgency=low
179+
180+ [ Michal Hruby ]
181+ * Expose real category ids and not just indices.
182+ * Provide fallbacks for default renderer.
183+
184+ [ Daniel d'Andrada ]
185+ * Give a visual feedback on right-edge drag with no running apps (LP:
186+ #1116207). (LP: #1116207)
187+
188+ [ Albert Astals ]
189+ * Update m_firstVisibleIndex if there's no visible items anymore Also
190+ remove the check for m_visibleItems.isEmpty() on insert, the
191+ m_firstVisibleIndex == 0 already protects us against that.
192+
193+ [ Christopher Lee ]
194+ * Tests now use a default lightdm mock if not decorated. (LP:
195+ #1204772)
196+
197+ [ Ubuntu daily release ]
198+ * Automatic snapshot from revision 135 (ubuntu-unity/next)
199+
200+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 26 Jul 2013 07:06:08 +0000
201+
202+unity8 (7.81.3+13.10.20130725ubuntu.unity.next-0ubuntu1) saucy; urgency=low
203+
204+ [ Michal Hruby ]
205+ * Fix adding items into an empty LVWPH.
206+
207+ [ Michał Sawicz ]
208+ * Move to using upstart in run_on_device.
209+ * Added heeding and qmltest for button-tint hint.
210+ * Refactoring and cleanup of the Unity8 Autopilot tests.
211+ * Hide the Unity launcher during autopiloting and skip battery tests
212+ if unavailable.
213+
214+ [ Ying-Chun Liu ]
215+ * Let GenericScope support loading different renderers.
216+
217+ [ Nick Dedekind ]
218+ * Removed overview from indicators.
219+ * Menus for indicators is now created prioritised by distance from
220+ current item to speed up user experience.
221+ * Add ApplicationArguments to know the geometry from start.
222+
223+ [ Mirco Müller ]
224+ * Added heeding and qmltest for button-tint hint.
225+
226+ [ Christopher Lee ]
227+ * Refactoring and cleanup of the Unity8 Autopilot tests.
228+
229+ [ Thomi Richards ]
230+ * Refactoring and cleanup of the Unity8 Autopilot tests.
231+
232+ [ Ubuntu daily release ]
233+ * Automatic snapshot from revision 129 (ubuntu-unity/next)
234+
235+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 25 Jul 2013 03:02:12 +0000
236+
1unity8 (7.81.3+13.10.20130718ubuntu.unity.next-0ubuntu1) saucy; urgency=low
237unity8 (7.81.3+13.10.20130718ubuntu.unity.next-0ubuntu1) saucy; urgency=low
2
238
3 [ Andrea Cimitan ]
239 [ Andrea Cimitan ]
debian/control+5−3
@@ -4,7 +4,7 @@ Priority: optional
4Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
4Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
5Build-Depends: cmake,
5Build-Depends: cmake,
6 debhelper (>= 9),
6 debhelper (>= 9),
7− libdee-qt5-dev (>= 3.0),
7+ libdee-qt5-dev (>= 3.2),
8 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
8 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
9 libgl1-mesa-dri,
9 libgl1-mesa-dri,
10 libgles2-mesa-dev[armhf],
10 libgles2-mesa-dev[armhf],
@@ -22,9 +22,9 @@ Build-Depends: cmake,
22 libusermetricsoutput1-dev,
22 libusermetricsoutput1-dev,
23 libxcb1-dev,
23 libxcb1-dev,
24 pkg-config,
24 pkg-config,
25− python (>= 2.7),
25+ python:any (>= 2.7),
26 python-setuptools,
26 python-setuptools,
27− python3,
27+ python3:any,
28 qt5-default,
28 qt5-default,
29 qtbase5-dev,
29 qtbase5-dev,
30 qtbase5-private-dev,
30 qtbase5-private-dev,
@@ -87,6 +87,8 @@ Depends: indicators-client (>= ${source:Version}),
87 ${misc:Depends},
87 ${misc:Depends},
88 ${python:Depends},
88 ${python:Depends},
89 ${shlibs:Depends},
89 ${shlibs:Depends},
90+Recommends: gir1.2-glib-2.0,
91+ python-gi,
90Description: Test package for Unity 8 shell
92Description: Test package for Unity 8 shell
91 Autopilot tests for the unity8 package
93 Autopilot tests for the unity8 package
92
94
debian/unity8-private.install+1
@@ -1,6 +1,7 @@
1usr/lib/*/unity8/qml/HudClient
1usr/lib/*/unity8/qml/HudClient
2usr/lib/*/unity8/qml/LightDM
2usr/lib/*/unity8/qml/LightDM
3usr/lib/*/unity8/qml/ListViewWithPageHeader
3usr/lib/*/unity8/qml/ListViewWithPageHeader
4+usr/lib/*/unity8/qml/Powerd
4usr/lib/*/unity8/qml/Ubuntu
5usr/lib/*/unity8/qml/Ubuntu
5usr/lib/*/unity8/qml/Unity
6usr/lib/*/unity8/qml/Unity
6usr/lib/*/unity8/qml/Utils
7usr/lib/*/unity8/qml/Utils
main.cpp+1−1
@@ -113,7 +113,7 @@ int main(int argc, char** argv)
113 view->setResizeMode(QQuickView::SizeRootObjectToView);
113 view->setResizeMode(QQuickView::SizeRootObjectToView);
114 view->setTitle("Qml Phone Shell");
114 view->setTitle("Qml Phone Shell");
115 view->engine()->setBaseUrl(QUrl::fromLocalFile(::shellAppDirectory()));
115 view->engine()->setBaseUrl(QUrl::fromLocalFile(::shellAppDirectory()));
116− view->rootContext()->setContextProperty("ApplicationArguments", &qmlArgs);
116+ view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
117 if (args.contains(QLatin1String("-frameless"))) {
117 if (args.contains(QLatin1String("-frameless"))) {
118 view->setFlags(Qt::FramelessWindowHint);
118 view->setFlags(Qt::FramelessWindowHint);
119 }
119 }
plugins/CMakeLists.txt+1
@@ -4,3 +4,4 @@ add_subdirectory(Unity)
4add_subdirectory(HudClient)
4add_subdirectory(HudClient)
5add_subdirectory(LightDM)
5add_subdirectory(LightDM)
6add_subdirectory(ListViewWithPageHeader)
6add_subdirectory(ListViewWithPageHeader)
7+add_subdirectory(Powerd)
plugins/ListViewWithPageHeader/CMakeLists.txt+5−1
@@ -4,7 +4,11 @@ include(Plugins)
4# There's no cmake var for v8 include path :-/
4# There's no cmake var for v8 include path :-/
5# so create one
5# so create one
6LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
6LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
7+if(${Qt5Core_VERSION_STRING} VERSION_LESS "5.1.0")
7−SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
8+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
9+else()
10+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
11+endif()
8
12
9include_directories(
13include_directories(
10 ${CMAKE_CURRENT_SOURCE_DIR}
14 ${CMAKE_CURRENT_SOURCE_DIR}
plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+167−29
@@ -96,7 +96,11 @@
96#include <qqmlengine.h>
96#include <qqmlengine.h>
97#pragma GCC diagnostic push
97#pragma GCC diagnostic push
98#pragma GCC diagnostic ignored "-pedantic"
98#pragma GCC diagnostic ignored "-pedantic"
99+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
99#include <private/qquickvisualdatamodel_p.h>
100#include <private/qquickvisualdatamodel_p.h>
101+#else
102+#include <private/qqmldelegatemodel_p.h>
103+#endif
100#include <private/qqmlglobal_p.h>
104#include <private/qqmlglobal_p.h>
101#include <private/qquickitem_p.h>
105#include <private/qquickitem_p.h>
102#include <private/qquickanimation_p.h>
106#include <private/qquickanimation_p.h>
@@ -156,16 +160,16 @@ ListViewWithPageHeader::ListViewWithPageHeader()
156// m_clipItem = new QQuickRectangle(contentItem());
160// m_clipItem = new QQuickRectangle(contentItem());
157// ((QQuickRectangle*)m_clipItem)->setColor(Qt::gray);
161// ((QQuickRectangle*)m_clipItem)->setColor(Qt::gray);
158
162
159− m_headerShowAnimation = new QQuickNumberAnimation(this);
163+ m_contentYAnimation = new QQuickNumberAnimation(this);
160− m_headerShowAnimation->setEasing(QEasingCurve::OutQuad);
164+ m_contentYAnimation->setEasing(QEasingCurve::OutQuad);
161− m_headerShowAnimation->setProperty("contentY");
165+ m_contentYAnimation->setProperty("contentY");
162− m_headerShowAnimation->setDuration(200);
166+ m_contentYAnimation->setDuration(200);
163− m_headerShowAnimation->setTargetObject(this);
167+ m_contentYAnimation->setTargetObject(this);
164
168
165 connect(this, SIGNAL(contentWidthChanged()), this, SLOT(onContentWidthChanged()));
169 connect(this, SIGNAL(contentWidthChanged()), this, SLOT(onContentWidthChanged()));
166 connect(this, SIGNAL(contentHeightChanged()), this, SLOT(onContentHeightChanged()));
170 connect(this, SIGNAL(contentHeightChanged()), this, SLOT(onContentHeightChanged()));
167 connect(this, SIGNAL(heightChanged()), this, SLOT(onHeightChanged()));
171 connect(this, SIGNAL(heightChanged()), this, SLOT(onHeightChanged()));
168− connect(m_headerShowAnimation, SIGNAL(stopped()), this, SLOT(onShowHeaderAnimationFinished()));
172+ connect(m_contentYAnimation, SIGNAL(stopped()), this, SLOT(onShowHeaderAnimationFinished()));
169}
173}
170
174
171ListViewWithPageHeader::~ListViewWithPageHeader()
175ListViewWithPageHeader::~ListViewWithPageHeader()
@@ -183,10 +187,17 @@ void ListViewWithPageHeader::setModel(QAbstractItemModel *model)
183 if (!m_delegateModel) {
187 if (!m_delegateModel) {
184 createDelegateModel();
188 createDelegateModel();
185 } else {
189 } else {
190+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
186 disconnect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
191 disconnect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
187 }
192 }
188 m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
193 m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
189 connect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
194 connect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
195+#else
196+ disconnect(m_delegateModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)), this, SLOT(onModelUpdated(QQmlChangeSet,bool)));
197+ }
198+ m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
199+ connect(m_delegateModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)), this, SLOT(onModelUpdated(QQmlChangeSet,bool)));
200+#endif
190 Q_EMIT modelChanged();
201 Q_EMIT modelChanged();
191 // TODO?
202 // TODO?
192// Q_EMIT contentHeightChanged();
203// Q_EMIT contentHeightChanged();
@@ -269,7 +280,7 @@ void ListViewWithPageHeader::setSectionDelegate(QQmlComponent *delegate)
269
280
270 m_sectionDelegate = delegate;
281 m_sectionDelegate = delegate;
271
282
272− m_topSectionItem = getSectionItem(QString());
283+ m_topSectionItem = getSectionItem(-1, QString());
273 m_topSectionItem->setZ(3);
284 m_topSectionItem->setZ(3);
274 QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
285 QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
275
286
@@ -363,11 +374,48 @@ void ListViewWithPageHeader::showHeader()
363 layout();
374 layout();
364 }
375 }
365 }
376 }
366− m_headerShowAnimation->setTo(to);
377+ m_contentYAnimation->setTo(to);
367− m_headerShowAnimation->start();
378+ contentYAnimationType = ContentYAnimationShowHeader;
379+ m_contentYAnimation->start();
368 }
380 }
369}
381}
370
382
383+bool ListViewWithPageHeader::maximizeVisibleArea(int modelIndex)
384+{
385+ ListItem *listItem = itemAtIndex(modelIndex);
386+ if (listItem)
387+ {
388+ const auto listItemY = m_clipItem->y() + listItem->y();
389+ if (listItemY > contentY() && listItemY + listItem->height() > contentY() + height()) {
390+ // we can scroll the list up to show more stuff
391+ const auto to = qMin(listItemY, listItemY + listItem->height() - height());
392+ m_contentYAnimation->setTo(to);
393+ contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
394+ m_contentYAnimation->start();
395+ } else if ((listItemY < contentY() && listItemY + listItem->height() < contentY() + height()) ||
396+ (m_topSectionItem && !listItem->m_sectionItem && listItemY - m_topSectionItem->height() < contentY() && listItemY + listItem->height() < contentY() + height()))
397+ {
398+ // we can scroll the list down to show more stuff
399+ auto realVisibleListItemY = listItemY;
400+ if (m_topSectionItem) {
401+ // If we are showing the top section sticky item and this item doesn't have a section
402+ // item we have to make sure to scroll it a bit more so that it is not underlapping
403+ // the top section sticky item
404+ bool topSectionShown = !QQuickItemPrivate::get(m_topSectionItem)->culled;
405+ if (topSectionShown && !listItem->m_sectionItem) {
406+ realVisibleListItemY -= m_topSectionItem->height();
407+ }
408+ }
409+ const auto to = qMax(realVisibleListItemY, listItemY + listItem->height() - height());
410+ m_contentYAnimation->setTo(to);
411+ contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
412+ m_contentYAnimation->start();
413+ }
414+ return true;
415+ }
416+ return false;
417+}
418+
371qreal ListViewWithPageHeader::minYExtent() const
419qreal ListViewWithPageHeader::minYExtent() const
372{
420{
373// qDebug() << "ListViewWithPageHeader::minYExtent" << m_minYExtent;
421// qDebug() << "ListViewWithPageHeader::minYExtent" << m_minYExtent;
@@ -389,6 +437,7 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
389 QQuickFlickable::viewportMoved(orient);
437 QQuickFlickable::viewportMoved(orient);
390// qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY();
438// qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY();
391 qreal diff = m_previousContentY - contentY();
439 qreal diff = m_previousContentY - contentY();
440+ const bool showHeaderAnimationRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationShowHeader;
392 if (m_headerItem) {
441 if (m_headerItem) {
393 auto oldHeaderItemShownHeight = m_headerItemShownHeight;
442 auto oldHeaderItemShownHeight = m_headerItemShownHeight;
394 if (contentY() < -m_minYExtent) {
443 if (contentY() < -m_minYExtent) {
@@ -399,16 +448,20 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
399 m_headerItem->setHeight(m_headerItem->implicitHeight());
448 m_headerItem->setHeight(m_headerItem->implicitHeight());
400 // We are going down (but it's not because of the rebound at the end)
449 // We are going down (but it's not because of the rebound at the end)
401 // (but the header was not shown by it's own position)
450 // (but the header was not shown by it's own position)
402− // or the header is partially shown
451+ // or the header is partially shown and we are not doing a maximizeVisibleArea either
403 const bool scrolledUp = m_previousContentY > contentY();
452 const bool scrolledUp = m_previousContentY > contentY();
404 const bool notRebounding = contentY() + height() < contentHeight();
453 const bool notRebounding = contentY() + height() < contentHeight();
405 const bool notShownByItsOwn = contentY() + diff > m_headerItem->y() + m_headerItem->height();
454 const bool notShownByItsOwn = contentY() + diff > m_headerItem->y() + m_headerItem->height();
455+ const bool maximizeVisibleAreaRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationMaximizeVisibleArea;
406
456
407 if (!scrolledUp && contentY() == -m_minYExtent) {
457 if (!scrolledUp && contentY() == -m_minYExtent) {
408 m_headerItemShownHeight = 0;
458 m_headerItemShownHeight = 0;
409 m_headerItem->setY(contentY());
459 m_headerItem->setY(contentY());
410− } else if ((scrolledUp && notRebounding && notShownByItsOwn) || (m_headerItemShownHeight > 0)) {
460+ } else if ((scrolledUp && notRebounding && notShownByItsOwn && !maximizeVisibleAreaRunning) || (m_headerItemShownHeight > 0)) {
461+ if (maximizeVisibleAreaRunning && diff > 0) // If we are maximizing and the header was shown, make sure we hide it
462+ m_headerItemShownHeight -= diff;
463+ else
411− m_headerItemShownHeight += diff;
464+ m_headerItemShownHeight += diff;
412 if (contentY() == -m_minYExtent) {
465 if (contentY() == -m_minYExtent) {
413 m_headerItemShownHeight = 0;
466 m_headerItemShownHeight = 0;
414 } else {
467 } else {
@@ -424,7 +477,7 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
424 // We will be changing the clip item, need to accomadate for it
477 // We will be changing the clip item, need to accomadate for it
425 // otherwise we move the firstItem down/up twice (unless the
478 // otherwise we move the firstItem down/up twice (unless the
426 // show header animation is running, where we want to keep the viewport stable)
479 // show header animation is running, where we want to keep the viewport stable)
427− if (!m_headerShowAnimation->isRunning()) {
480+ if (!showHeaderAnimationRunning) {
428 diff += oldHeaderItemShownHeight - m_headerItemShownHeight;
481 diff += oldHeaderItemShownHeight - m_headerItemShownHeight;
429 } else {
482 } else {
430 diff = -diff;
483 diff = -diff;
@@ -434,7 +487,7 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
434 updateClipItem();
487 updateClipItem();
435 ListItem *firstItem = m_visibleItems.first();
488 ListItem *firstItem = m_visibleItems.first();
436 firstItem->setY(firstItem->y() + diff);
489 firstItem->setY(firstItem->y() + diff);
437− if (m_headerShowAnimation->isRunning()) {
490+ if (showHeaderAnimationRunning) {
438 adjustMinYExtent();
491 adjustMinYExtent();
439 }
492 }
440 }
493 }
@@ -446,8 +499,13 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
446
499
447void ListViewWithPageHeader::createDelegateModel()
500void ListViewWithPageHeader::createDelegateModel()
448{
501{
502+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
449 m_delegateModel = new QQuickVisualDataModel(qmlContext(this), this);
503 m_delegateModel = new QQuickVisualDataModel(qmlContext(this), this);
450 connect(m_delegateModel, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(itemCreated(int,QQuickItem*)));
504 connect(m_delegateModel, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(itemCreated(int,QQuickItem*)));
505+#else
506+ m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
507+ connect(m_delegateModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(itemCreated(int,QObject*)));
508+#endif
451 if (isComponentComplete())
509 if (isComponentComplete())
452 m_delegateModel->componentComplete();
510 m_delegateModel->componentComplete();
453 updateWatchedRoles();
511 updateWatchedRoles();
@@ -528,8 +586,13 @@ bool ListViewWithPageHeader::addVisibleItems(qreal fillFrom, qreal fillTo, bool
528void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
586void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
529{
587{
530 QQuickItem *item = listItem->m_item;
588 QQuickItem *item = listItem->m_item;
589+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
531 QQuickVisualModel::ReleaseFlags flags = m_delegateModel->release(item);
590 QQuickVisualModel::ReleaseFlags flags = m_delegateModel->release(item);
532 if (flags & QQuickVisualModel::Destroyed) {
591 if (flags & QQuickVisualModel::Destroyed) {
592+#else
593+ QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
594+ if (flags & QQmlDelegateModel::Destroyed) {
595+#endif
533 item->setParentItem(nullptr);
596 item->setParentItem(nullptr);
534 }
597 }
535 delete listItem->m_sectionItem;
598 delete listItem->m_sectionItem;
@@ -578,16 +641,17 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyI
578 }
641 }
579 }
642 }
580
643
581− return getSectionItem(section);
644+ return getSectionItem(modelIndex, section);
582}
645}
583
646
584−QQuickItem *ListViewWithPageHeader::getSectionItem(const QString &sectionText)
647+QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, const QString &sectionText)
585{
648{
586 QQuickItem *sectionItem = nullptr;
649 QQuickItem *sectionItem = nullptr;
587
650
588 QQmlContext *creationContext = m_sectionDelegate->creationContext();
651 QQmlContext *creationContext = m_sectionDelegate->creationContext();
589 QQmlContext *context = new QQmlContext(creationContext ? creationContext : qmlContext(this));
652 QQmlContext *context = new QQmlContext(creationContext ? creationContext : qmlContext(this));
590 context->setContextProperty(QLatin1String("section"), sectionText);
653 context->setContextProperty(QLatin1String("section"), sectionText);
654+ context->setContextProperty(QLatin1String("delegateIndex"), modelIndex);
591 QObject *nobj = m_sectionDelegate->beginCreate(context);
655 QObject *nobj = m_sectionDelegate->beginCreate(context);
592 if (nobj) {
656 if (nobj) {
593 QQml_setParent_noEvent(context, nobj);
657 QQml_setParent_noEvent(context, nobj);
@@ -658,9 +722,27 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
658 return nullptr;
722 return nullptr;
659
723
660 m_asyncRequestedIndex = -1;
724 m_asyncRequestedIndex = -1;
725+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
661 QQuickItem *item = m_delegateModel->item(modelIndex, asynchronous);
726 QQuickItem *item = m_delegateModel->item(modelIndex, asynchronous);
727+#else
728+ QObject* object = m_delegateModel->object(modelIndex, asynchronous);
729+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
730+#endif
662 if (!item) {
731 if (!item) {
732+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
663 m_asyncRequestedIndex = modelIndex;
733 m_asyncRequestedIndex = modelIndex;
734+#else
735+ if (object) {
736+ m_delegateModel->release(object);
737+ if (!m_delegateValidated) {
738+ m_delegateValidated = true;
739+ QObject* delegateObj = delegate();
740+ qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
741+ }
742+ } else {
743+ m_asyncRequestedIndex = modelIndex;
744+ }
745+#endif
664 return 0;
746 return 0;
665 } else {
747 } else {
666// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
748// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
@@ -694,7 +776,7 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
694 releaseItem(listItem);
776 releaseItem(listItem);
695 listItem = nullptr;
777 listItem = nullptr;
696 } else {
778 } else {
697− listItem->setCulled(listItem->y() + listItem->height() + m_clipItem->y() < contentY() || listItem->y() + m_clipItem->y() >= contentY() + height());
779+ listItem->setCulled(listItem->y() + listItem->height() + m_clipItem->y() <= contentY() || listItem->y() + m_clipItem->y() >= contentY() + height());
698 if (m_visibleItems.isEmpty()) {
780 if (m_visibleItems.isEmpty()) {
699 m_visibleItems << listItem;
781 m_visibleItems << listItem;
700 } else {
782 } else {
@@ -711,8 +793,18 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
711 }
793 }
712}
794}
713
795
796+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
714void ListViewWithPageHeader::itemCreated(int modelIndex, QQuickItem *item)
797void ListViewWithPageHeader::itemCreated(int modelIndex, QQuickItem *item)
715{
798{
799+#else
800+void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
801+{
802+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
803+ if (!item) {
804+ qWarning() << "ListViewWithPageHeader::itemCreated got a non item for index" << modelIndex;
805+ return;
806+ }
807+#endif
716// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
808// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
717
809
718 item->setParentItem(m_clipItem);
810 item->setParentItem(m_clipItem);
@@ -747,13 +839,22 @@ void ListViewWithPageHeader::onHeightChanged()
747 polish();
839 polish();
748}
840}
749
841
842+
843+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
750void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bool /*reset*/)
844void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bool /*reset*/)
845+#else
846+void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool /*reset*/)
847+#endif
751{
848{
752 // TODO Do something with reset
849 // TODO Do something with reset
753// qDebug() << "ListViewWithPageHeader::onModelUpdated" << changeSet << reset;
850// qDebug() << "ListViewWithPageHeader::onModelUpdated" << changeSet << reset;
754 const auto oldFirstVisibleIndex = m_firstVisibleIndex;
851 const auto oldFirstVisibleIndex = m_firstVisibleIndex;
755
852
853+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
756 Q_FOREACH(const QQuickChangeSet::Remove &remove, changeSet.removes()) {
854 Q_FOREACH(const QQuickChangeSet::Remove &remove, changeSet.removes()) {
855+#else
856+ Q_FOREACH(const QQmlChangeSet::Remove &remove, changeSet.removes()) {
857+#endif
757// qDebug() << "ListViewWithPageHeader::onModelUpdated Remove" << remove.index << remove.count;
858// qDebug() << "ListViewWithPageHeader::onModelUpdated Remove" << remove.index << remove.count;
758 if (remove.index + remove.count > m_firstVisibleIndex && remove.index < m_firstVisibleIndex + m_visibleItems.count()) {
859 if (remove.index + remove.count > m_firstVisibleIndex && remove.index < m_firstVisibleIndex + m_visibleItems.count()) {
759 const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
860 const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
@@ -785,10 +886,14 @@ void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bo
785 }
886 }
786 if (growDown) {
887 if (growDown) {
787 adjustMinYExtent();
888 adjustMinYExtent();
788− } else if (remove.index <= m_firstVisibleIndex && !m_visibleItems.isEmpty()) {
889+ } else if (remove.index <= m_firstVisibleIndex) {
890+ if (!m_visibleItems.isEmpty()) {
789− // We removed the first item that is the one that positions the rest
891+ // We removed the first item that is the one that positions the rest
790− // position the new first item correctly
892+ // position the new first item correctly
791− m_visibleItems.first()->setY(oldFirstValidIndexPos);
893+ m_visibleItems.first()->setY(oldFirstValidIndexPos);
894+ } else {
895+ m_firstVisibleIndex = -1;
896+ }
792 }
897 }
793 } else if (remove.index + remove.count <= m_firstVisibleIndex) {
898 } else if (remove.index + remove.count <= m_firstVisibleIndex) {
794 m_firstVisibleIndex -= remove.count;
899 m_firstVisibleIndex -= remove.count;
@@ -803,10 +908,14 @@ void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bo
803 }
908 }
804 }
909 }
805
910
911+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
806 Q_FOREACH(const QQuickChangeSet::Insert &insert, changeSet.inserts()) {
912 Q_FOREACH(const QQuickChangeSet::Insert &insert, changeSet.inserts()) {
913+#else
914+ Q_FOREACH(const QQmlChangeSet::Insert &insert, changeSet.inserts()) {
915+#endif
807// qDebug() << "ListViewWithPageHeader::onModelUpdated Insert" << insert.index << insert.count;
916// qDebug() << "ListViewWithPageHeader::onModelUpdated Insert" << insert.index << insert.count;
808 const bool insertingInValidIndexes = insert.index > m_firstVisibleIndex && insert.index < m_firstVisibleIndex + m_visibleItems.count();
917 const bool insertingInValidIndexes = insert.index > m_firstVisibleIndex && insert.index < m_firstVisibleIndex + m_visibleItems.count();
809− const bool firstItemWithViewOnTop = insert.index == 0 && m_firstVisibleIndex == 0 && !m_visibleItems.isEmpty() && m_visibleItems.first()->y() + m_clipItem->y() > contentY();
918+ const bool firstItemWithViewOnTop = insert.index == 0 && m_firstVisibleIndex == 0 && m_visibleItems.first()->y() + m_clipItem->y() > contentY();
810 if (insertingInValidIndexes || firstItemWithViewOnTop)
919 if (insertingInValidIndexes || firstItemWithViewOnTop)
811 {
920 {
812 // If the items we are adding won't be really visible
921 // If the items we are adding won't be really visible
@@ -866,6 +975,14 @@ void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bo
866 adjustMinYExtent();
975 adjustMinYExtent();
867 }
976 }
868
977
978+ for (int i = 0; i < m_visibleItems.count(); ++i) {
979+ ListItem *item = m_visibleItems[i];
980+ if (item->m_sectionItem) {
981+ QQmlContext *context = QQmlEngine::contextForObject(item->m_sectionItem)->parentContext();
982+ context->setContextProperty(QLatin1String("delegateIndex"), m_firstVisibleIndex + i);
983+ }
984+ }
985+
869 layout();
986 layout();
870 polish();
987 polish();
871 m_contentHeightDirty = true;
988 m_contentHeightDirty = true;
@@ -965,24 +1082,31 @@ void ListViewWithPageHeader::layout()
965 int firstReallyVisibleItem = -1;
1082 int firstReallyVisibleItem = -1;
966 int modelIndex = m_firstVisibleIndex;
1083 int modelIndex = m_firstVisibleIndex;
967 Q_FOREACH(ListItem *item, m_visibleItems) {
1084 Q_FOREACH(ListItem *item, m_visibleItems) {
968− const bool cull = pos + item->height() < visibleFrom || pos >= visibleTo;
1085+ const bool cull = pos + item->height() <= visibleFrom || pos >= visibleTo;
969 item->setCulled(cull);
1086 item->setCulled(cull);
970 item->setY(pos);
1087 item->setY(pos);
971 if (!cull && firstReallyVisibleItem == -1) {
1088 if (!cull && firstReallyVisibleItem == -1) {
972 firstReallyVisibleItem = modelIndex;
1089 firstReallyVisibleItem = modelIndex;
973 if (m_topSectionItem) {
1090 if (m_topSectionItem) {
974− // Update the top sticky section header
975− const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
976− QQmlContext *context = QQmlEngine::contextForObject(m_topSectionItem)->parentContext();
977− context->setContextProperty(QLatin1String("section"), section);
978−
979 // Positing the top section sticky item is a two step process
1091 // Positing the top section sticky item is a two step process
980 // First we set it either we cull it (because it doesn't need to be sticked to the top)
1092 // First we set it either we cull it (because it doesn't need to be sticked to the top)
981 // or stick it to the top
1093 // or stick it to the top
982 // Then after the loop we'll make sure that if there's another section just below it
1094 // Then after the loop we'll make sure that if there's another section just below it
983 // pushed the sticky section up to make it disappear
1095 // pushed the sticky section up to make it disappear
984 const qreal topSectionStickPos = m_headerItemShownHeight + contentY() - m_clipItem->y();
1096 const qreal topSectionStickPos = m_headerItemShownHeight + contentY() - m_clipItem->y();
1097+ bool showStickySectionItem;
1098+ // We need to show the "top section sticky item" when the position at the "top" of the
1099+ // viewport is bigger than the start of the position of the first visible item
1100+ // i.e. the first visible item starts before the viewport, or when the first
1101+ // visible item starts just at the viewport start and it does not have its own section item
985− if (topSectionStickPos <= pos) {
1102+ if (topSectionStickPos > pos) {
1103+ showStickySectionItem = true;
1104+ } else if (topSectionStickPos == pos) {
1105+ showStickySectionItem = !item->m_sectionItem;
1106+ } else {
1107+ showStickySectionItem = false;
1108+ }
1109+ if (!showStickySectionItem) {
986 QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
1110 QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
987 if (item->m_sectionItem) {
1111 if (item->m_sectionItem) {
988 // This seems it should happen since why would we cull the top section
1112 // This seems it should happen since why would we cull the top section
@@ -992,8 +1116,22 @@ void ListViewWithPageHeader::layout()
992 QQuickItemPrivate::get(item->m_sectionItem)->setCulled(false);
1116 QQuickItemPrivate::get(item->m_sectionItem)->setCulled(false);
993 }
1117 }
994 } else {
1118 } else {
1119+ // Update the top sticky section header
1120+ const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
1121+ QQmlContext *context = QQmlEngine::contextForObject(m_topSectionItem)->parentContext();
1122+ context->setContextProperty(QLatin1String("section"), section);
1123+
995 QQuickItemPrivate::get(m_topSectionItem)->setCulled(false);
1124 QQuickItemPrivate::get(m_topSectionItem)->setCulled(false);
996 m_topSectionItem->setY(topSectionStickPos);
1125 m_topSectionItem->setY(topSectionStickPos);
1126+ int delegateIndex = modelIndex;
1127+ // Look for the first index with this section text
1128+ while (delegateIndex > 0) {
1129+ const QString prevSection = m_delegateModel->stringValue(delegateIndex - 1, m_sectionProperty);
1130+ if (prevSection != section)
1131+ break;
1132+ delegateIndex--;
1133+ }
1134+ context->setContextProperty(QLatin1String("delegateIndex"), delegateIndex);
997 if (item->m_sectionItem) {
1135 if (item->m_sectionItem) {
998 QQuickItemPrivate::get(item->m_sectionItem)->setCulled(true);
1136 QQuickItemPrivate::get(item->m_sectionItem)->setCulled(true);
999 }
1137 }
plugins/ListViewWithPageHeader/listviewwithpageheader.h+27−3
@@ -24,9 +24,14 @@
24#pragma GCC diagnostic pop
24#pragma GCC diagnostic pop
25
25
26class QAbstractItemModel;
26class QAbstractItemModel;
27−class QQuickChangeSet;
28class QQuickNumberAnimation;
27class QQuickNumberAnimation;
28+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
29+class QQuickChangeSet;
29class QQuickVisualDataModel;
30class QQuickVisualDataModel;
31+#else
32+class QQmlChangeSet;
33+class QQmlDelegateModel;
34+#endif
30
35
31
36
32/**
37/**
@@ -84,6 +89,11 @@ public:
84 Q_INVOKABLE void positionAtBeginning();
89 Q_INVOKABLE void positionAtBeginning();
85 Q_INVOKABLE void showHeader();
90 Q_INVOKABLE void showHeader();
86
91
92+ // The index has to be created for this to try to do something
93+ // Created items are those visible and the precached ones
94+ // Returns if the item existed or not
95+ Q_INVOKABLE bool maximizeVisibleArea(int modelIndex);
96+
87Q_SIGNALS:
97Q_SIGNALS:
88 void modelChanged();
98 void modelChanged();
89 void delegateChanged();
99 void delegateChanged();
@@ -100,11 +110,19 @@ protected:
100 void updatePolish();
110 void updatePolish();
101
111
102private Q_SLOTS:
112private Q_SLOTS:
113+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
103 void itemCreated(int modelIndex, QQuickItem *item);
114 void itemCreated(int modelIndex, QQuickItem *item);
115+#else
116+ void itemCreated(int modelIndex, QObject *object);
117+#endif
104 void onContentHeightChanged();
118 void onContentHeightChanged();
105 void onContentWidthChanged();
119 void onContentWidthChanged();
106 void onHeightChanged();
120 void onHeightChanged();
121+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
107 void onModelUpdated(const QQuickChangeSet &changeSet, bool reset);
122 void onModelUpdated(const QQuickChangeSet &changeSet, bool reset);
123+#else
124+ void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
125+#endif
108 void onShowHeaderAnimationFinished();
126 void onShowHeaderAnimationFinished();
109
127
110private:
128private:
@@ -139,9 +157,13 @@ private:
139 void reallyReleaseItem(ListItem *item);
157 void reallyReleaseItem(ListItem *item);
140 void updateWatchedRoles();
158 void updateWatchedRoles();
141 QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
159 QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
142− QQuickItem *getSectionItem(const QString &sectionText);
160+ QQuickItem *getSectionItem(int modelIndex, const QString &sectionText);
143
161
162+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
144 QQuickVisualDataModel *m_delegateModel;
163 QQuickVisualDataModel *m_delegateModel;
164+#else
165+ QQmlDelegateModel *m_delegateModel;
166+#endif
145
167
146 // Index we are waiting because we requested it asynchronously
168 // Index we are waiting because we requested it asynchronously
147 int m_asyncRequestedIndex;
169 int m_asyncRequestedIndex;
@@ -165,7 +187,9 @@ private:
165 qreal m_previousContentY;
187 qreal m_previousContentY;
166 qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
188 qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
167 // i.e. it's being shown after dragging down in the middle of the list
189 // i.e. it's being shown after dragging down in the middle of the list
190+ enum ContentYAnimationType { ContentYAnimationShowHeader, ContentYAnimationMaximizeVisibleArea };
191+ ContentYAnimationType contentYAnimationType;
168− QQuickNumberAnimation *m_headerShowAnimation;
192+ QQuickNumberAnimation *m_contentYAnimation;
169
193
170 QQmlComponent *m_sectionDelegate;
194 QQmlComponent *m_sectionDelegate;
171 QString m_sectionProperty;
195 QString m_sectionProperty;
plugins/Powerd/CMakeLists.txtnew file+13
@@ -0,0 +1,13 @@
1+include(Plugins)
2+
3+add_definitions(-DSM_BUSNAME=systemBus)
4+
5+add_library(Powerd-qml MODULE
6+ plugin.cpp
7+ Powerd.cpp
8+ )
9+
10+qt5_use_modules(Powerd-qml DBus Qml)
11+
12+export_qmlfiles(Powerd Powerd)
13+export_qmlplugin(Powerd 0.1 Powerd TARGETS Powerd-qml)
plugins/Powerd/Powerd.cppnew file+36
@@ -0,0 +1,36 @@
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+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "Powerd.h"
20+
21+Powerd::Powerd(QObject* parent)
22+ : QObject(parent),
23+ powerd(NULL)
24+{
25+ powerd = new QDBusInterface("com.canonical.powerd",
26+ "/com/canonical/powerd",
27+ "com.canonical.powerd",
28+ QDBusConnection::SM_BUSNAME(), this);
29+
30+ powerd->connection().connect("com.canonical.powerd",
31+ "/com/canonical/powerd",
32+ "com.canonical.powerd",
33+ "SysPowerStateChange",
34+ this,
35+ SIGNAL(powerStateChange(int)));
36+}
plugins/Powerd/Powerd.hnew file+40
@@ -0,0 +1,40 @@
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: Gerry Boland <gerry.boland@canonical.com>
17+ * Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#ifndef UNITY_POWERD_H
21+#define UNITY_POWERD_H
22+
23+#include <QtCore/QObject>
24+#include <QtDBus/QDBusInterface>
25+
26+class Powerd: public QObject
27+{
28+ Q_OBJECT
29+
30+public:
31+ explicit Powerd(QObject *parent = 0);
32+
33+Q_SIGNALS:
34+ void powerStateChange(int state);
35+
36+private:
37+ QDBusInterface *powerd;
38+};
39+
40+#endif
plugins/Powerd/plugin.cppnew file+36
@@ -0,0 +1,36 @@
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: Gerry Boland <gerry.boland@canonical.com>
17+ * Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "plugin.h"
21+#include "Powerd.h"
22+
23+#include <QtQml/QtQml>
24+
25+static QObject *powerd_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
26+{
27+ Q_UNUSED(engine)
28+ Q_UNUSED(scriptEngine)
29+ return new Powerd();
30+}
31+
32+void PowerdPlugin::registerTypes(const char *uri)
33+{
34+ Q_ASSERT(uri == QLatin1String("Powerd"));
35+ qmlRegisterSingletonType<Powerd>(uri, 0, 1, "Powerd", powerd_provider);
36+}
plugins/Powerd/plugin.hnew file+35
@@ -0,0 +1,35 @@
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: Gerry Boland <gerry.boland@canonical.com>
17+ * Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#ifndef POWER_PLUGIN_H
21+#define POWER_PLUGIN_H
22+
23+#include <QtQml/QQmlEngine>
24+#include <QtQml/QQmlExtensionPlugin>
25+
26+class PowerdPlugin : public QQmlExtensionPlugin
27+{
28+ Q_OBJECT
29+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
30+
31+public:
32+ void registerTypes(const char *uri);
33+};
34+
35+#endif
plugins/Powerd/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Powerd
2+plugin Powerd-qml
3+typeinfo plugin.qmltypes
plugins/Unity/CMakeLists.txt+1−1
@@ -5,7 +5,7 @@ add_subdirectory(Indicators)
5
5
6# Dependencies
6# Dependencies
7include(FindPkgConfig)
7include(FindPkgConfig)
8−pkg_check_modules(QTDEE REQUIRED libdee-qt5)
8+pkg_check_modules(QTDEE REQUIRED libdee-qt5>=3.2)
9pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0)
9pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0)
10
10
11include_directories(
11include_directories(
plugins/Unity/Indicators/CMakeLists.txt+1
@@ -24,6 +24,7 @@ set(IndicatorsQML_SOURCES
24 indicatorsmanager.cpp
24 indicatorsmanager.cpp
25 indicatorsmodel.cpp
25 indicatorsmodel.cpp
26 menucontentactivator.cpp
26 menucontentactivator.cpp
27+ modelprinter.cpp
27 plugin.cpp
28 plugin.cpp
28)
29)
29add_definitions(-DUNITYINDICATORS_LIBRARY)
30add_definitions(-DUNITYINDICATORS_LIBRARY)
plugins/Unity/Indicators/flatmenuproxymodel.cpp+10−7
@@ -55,31 +55,34 @@ void FlatMenuProxyModel::setSourceModel(QAbstractItemModel *source)
55 if (source) {
55 if (source) {
56
56
57 // FIXME - not working correctly with dynamic inserts/removes
57 // FIXME - not working correctly with dynamic inserts/removes
58+ // FIXME 2 - We're using Queud connections as a workaround to QTBUG-32859
59+ // The signals from qmenumodel are coming straight off the glib event loop,
60+ // which is not supported and has the effect of listview delegates not to be deleted.
58
61
59 connect(source,
62 connect(source,
60 SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
63 SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
61− SLOT(onModelAboutToBeReset()));
64+ SLOT(onModelAboutToBeReset()), Qt::QueuedConnection);
62 connect(source,
65 connect(source,
63 SIGNAL(rowsInserted(QModelIndex,int,int)),
66 SIGNAL(rowsInserted(QModelIndex,int,int)),
64− SLOT(onModelReset()));
67+ SLOT(onModelReset()), Qt::QueuedConnection);
65
68
66 connect(source,
69 connect(source,
67 SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
70 SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
68− SLOT(onModelAboutToBeReset()));
71+ SLOT(onModelAboutToBeReset()), Qt::QueuedConnection);
69 connect(source,
72 connect(source,
70 SIGNAL(rowsRemoved(QModelIndex,int,int)),
73 SIGNAL(rowsRemoved(QModelIndex,int,int)),
71− SLOT(onModelReset()));
74+ SLOT(onModelReset()), Qt::QueuedConnection);
72
75
73 connect(source,
76 connect(source,
74 SIGNAL(modelAboutToBeReset()),
77 SIGNAL(modelAboutToBeReset()),
75− SLOT(onModelAboutToBeReset()));
78+ SLOT(onModelAboutToBeReset()), Qt::QueuedConnection);
76 connect(source,
79 connect(source,
77 SIGNAL(modelReset()),
80 SIGNAL(modelReset()),
78− SLOT(onModelReset()));
81+ SLOT(onModelReset()), Qt::QueuedConnection);
79
82
80 connect(source,
83 connect(source,
81 SIGNAL(statusChanged(DBusEnums::ConnectionStatus)),
84 SIGNAL(statusChanged(DBusEnums::ConnectionStatus)),
82− SIGNAL(statusChanged()));
85+ SIGNAL(statusChanged()), Qt::QueuedConnection);
83
86
84 // initiliaze rowCount
87 // initiliaze rowCount
85 QModelIndex lastItem = source->index(source->rowCount() - 1, 0);
88 QModelIndex lastItem = source->index(source->rowCount() - 1, 0);
plugins/Unity/Indicators/modelprinter.cppnew file+114
@@ -0,0 +1,114 @@
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+// self
21+#include "modelprinter.h"
22+
23+// Qt
24+#include <QTextStream>
25+
26+ModelPrinter::ModelPrinter(QObject *parent)
27+ : QObject(parent)
28+ , m_model(NULL)
29+{
30+}
31+
32+void ModelPrinter::setSourceModel(QAbstractItemModel * sourceModel)
33+{
34+ if (m_model != NULL) {
35+ disconnect(m_model);
36+ }
37+ if (m_model != sourceModel) {
38+ m_model = sourceModel;
39+ Q_EMIT modelChanged();
40+ Q_EMIT textChanged();
41+ }
42+ if (m_model != NULL) {
43+ connect(m_model, SIGNAL(modelReset()), this, SIGNAL(textChanged()));
44+ connect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(textChanged()));
45+ connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(textChanged()));
46+ }
47+}
48+
49+QAbstractItemModel* ModelPrinter::sourceModel() const
50+{
51+ return m_model;
52+}
53+
54+QString ModelPrinter::text(const QModelIndex& index) const
55+{
56+ return recurseString(index, 0);
57+}
58+
59+QString tabify(int level) { QString str;
60+ for (int i = 0; i < level; i++) {
61+ str += " ";
62+ }
63+ return str;
64+}
65+
66+QString ModelPrinter::recurseString(const QModelIndex& index, int level) const
67+{
68+ if (!m_model)
69+ return "";
70+
71+ QString str;
72+ QTextStream stream(&str);
73+
74+ QHash<int, QByteArray> roleNames = m_model->roleNames();
75+ QList<int> roles = roleNames.keys();
76+ qSort(roles);
77+ Q_FOREACH(int role, roles) {
78+ QVariant vData = m_model->data(index, role);
79+ if (vData.canConvert(QMetaType::QVariantMap)) {
80+ QMapIterator<QString, QVariant> iter(vData.toMap());
81+ while (iter.hasNext()) {
82+ iter.next();
83+ stream << tabify(level)
84+ << roleNames[role]
85+ << "."
86+ << iter.key()
87+ << ": "
88+ << iter.value().toString()
89+ << endl;
90+ }
91+ }
92+ else {
93+ stream << tabify(level)
94+ << roleNames[role]
95+ << ": "
96+ << vData.toString()
97+ << endl;
98+ }
99+ }
100+
101+ int rowCount = m_model->rowCount(index);
102+ stream << tabify(level)
103+ << "child count"
104+ << ": "
105+ << rowCount
106+ << endl
107+ << endl;
108+
109+ for (int i = 0; i < rowCount; i++) {
110+ QModelIndex child = m_model->index(i, 0, index);
111+ str += recurseString(child, level+1);
112+ }
113+ return str;
114+}
plugins/Unity/Indicators/modelprinter.hnew file+50
@@ -0,0 +1,50 @@
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+#ifndef MODELPRINTER_H
21+#define MODELPRINTER_H
22+
23+#include <QSortFilterProxyModel>
24+
25+// This class acts as a namespace only, with the addition that its enums
26+// are registered to be exposed on the QML side.
27+class ModelPrinter : public QObject
28+{
29+ Q_OBJECT
30+
31+ Q_PROPERTY(QAbstractItemModel* model READ sourceModel WRITE setSourceModel NOTIFY modelChanged)
32+ Q_PROPERTY(QString text READ text NOTIFY textChanged)
33+public:
34+ ModelPrinter(QObject* parent=0);
35+
36+ void setSourceModel(QAbstractItemModel* sourceModel);
37+ QAbstractItemModel* sourceModel() const;
38+
39+ Q_INVOKABLE QString text(const QModelIndex& index = QModelIndex()) const;
40+
41+Q_SIGNALS:
42+ void modelChanged();
43+ void textChanged();
44+
45+private:
46+ QString recurseString(const QModelIndex& index, int level) const;
47+ QAbstractItemModel* m_model;
48+};
49+
50+#endif // MODELPRINTER_H
plugins/Unity/Indicators/plugin.cpp+2
@@ -28,6 +28,7 @@
28#include "indicatorsmodel.h"
28#include "indicatorsmodel.h"
29#include "indicators.h"
29#include "indicators.h"
30#include "menucontentactivator.h"
30#include "menucontentactivator.h"
31+#include "modelprinter.h"
31
32
32void IndicatorsPlugin::registerTypes(const char *uri)
33void IndicatorsPlugin::registerTypes(const char *uri)
33{
34{
@@ -36,6 +37,7 @@ void IndicatorsPlugin::registerTypes(const char *uri)
36 qmlRegisterType<IndicatorsManager>(uri, 0, 1, "IndicatorsManager");
37 qmlRegisterType<IndicatorsManager>(uri, 0, 1, "IndicatorsManager");
37 qmlRegisterType<FlatMenuProxyModel>(uri, 0, 1, "FlatMenuProxyModel");
38 qmlRegisterType<FlatMenuProxyModel>(uri, 0, 1, "FlatMenuProxyModel");
38 qmlRegisterType<IndicatorsModel>(uri, 0, 1, "IndicatorsModel");
39 qmlRegisterType<IndicatorsModel>(uri, 0, 1, "IndicatorsModel");
40+ qmlRegisterType<ModelPrinter>(uri, 0, 1, "ModelPrinter");
39 qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
41 qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
40
42
41 qmlRegisterUncreatableType<MenuContentState>(uri, 0, 1, "MenuContentState", "Can't create MenuContentState class");
43 qmlRegisterUncreatableType<MenuContentState>(uri, 0, 1, "MenuContentState", "Can't create MenuContentState class");
plugins/Unity/categories.cpp+6−3
@@ -34,7 +34,7 @@ enum CategoryColumn {
34Categories::Categories(QObject* parent)
34Categories::Categories(QObject* parent)
35 : DeeListModel(parent)
35 : DeeListModel(parent)
36{
36{
37− m_roles[Categories::RoleId] = "id";
37+ m_roles[Categories::RoleCategoryId] = "categoryId";
38 m_roles[Categories::RoleName] = "name";
38 m_roles[Categories::RoleName] = "name";
39 m_roles[Categories::RoleIcon] = "icon";
39 m_roles[Categories::RoleIcon] = "icon";
40 m_roles[Categories::RoleRenderer] = "renderer";
40 m_roles[Categories::RoleRenderer] = "renderer";
@@ -42,6 +42,7 @@ Categories::Categories(QObject* parent)
42 m_roles[Categories::RoleHints] = "hints";
42 m_roles[Categories::RoleHints] = "hints";
43 m_roles[Categories::RoleResults] = "results";
43 m_roles[Categories::RoleResults] = "results";
44 m_roles[Categories::RoleCount] = "count";
44 m_roles[Categories::RoleCount] = "count";
45+ m_roles[Categories::RoleCategoryIndex] = "categoryIndex";
45
46
46 // TODO This should not be needed but accumulatting the count changes
47 // TODO This should not be needed but accumulatting the count changes
47 // makes the visualization more stable and also makes crashes on fast
48 // makes the visualization more stable and also makes crashes on fast
@@ -130,8 +131,8 @@ Categories::data(const QModelIndex& index, int role) const
130 }
131 }
131
132
132 switch (role) {
133 switch (role) {
133− case RoleId:
134+ case RoleCategoryId:
134− return QVariant::fromValue(index.row());
135+ return DeeListModel::data(index, CategoryColumn::ID);
135 case RoleName:
136 case RoleName:
136 return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
137 return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
137 case RoleIcon:
138 case RoleIcon:
@@ -149,6 +150,8 @@ Categories::data(const QModelIndex& index, int role) const
149 return QVariant::fromValue(getResults(index.row()));
150 return QVariant::fromValue(getResults(index.row()));
150 case RoleCount:
151 case RoleCount:
151 return QVariant::fromValue(getResults(index.row())->rowCount());
152 return QVariant::fromValue(getResults(index.row())->rowCount());
153+ case RoleCategoryIndex:
154+ return QVariant::fromValue(index.row());
152 default:
155 default:
153 return QVariant();
156 return QVariant();
154 }
157 }
plugins/Unity/categories.h+3−2
@@ -42,14 +42,15 @@ public:
42 explicit Categories(QObject* parent = 0);
42 explicit Categories(QObject* parent = 0);
43
43
44 enum Roles {
44 enum Roles {
45− RoleId,
45+ RoleCategoryId,
46 RoleName,
46 RoleName,
47 RoleIcon,
47 RoleIcon,
48 RoleRenderer,
48 RoleRenderer,
49 RoleContentType,
49 RoleContentType,
50 RoleHints,
50 RoleHints,
51 RoleResults,
51 RoleResults,
52− RoleCount
52+ RoleCount,
53+ RoleCategoryIndex
53 };
54 };
54
55
55 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
56 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
plugins/Unity/previewinfohint.cpp+2−2
@@ -17,9 +17,9 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
18 */
19
19
20+#include <deelistmodel.h>
20// local
21// local
21#include "previewinfohint.h"
22#include "previewinfohint.h"
22−#include "variantutils.h"
23
23
24PreviewInfoHint::PreviewInfoHint(QObject *parent):
24PreviewInfoHint::PreviewInfoHint(QObject *parent):
25 QObject(parent),
25 QObject(parent),
@@ -61,7 +61,7 @@ QString PreviewInfoHint::iconHint() const
61QVariant PreviewInfoHint::value() const
61QVariant PreviewInfoHint::value() const
62{
62{
63 if (m_unityInfoHint) {
63 if (m_unityInfoHint) {
64− return QVariantFromGVariant(m_unityInfoHint->value);
64+ return DeeListModel::VariantForData(m_unityInfoHint->value);
65 }
65 }
66 return QVariant();
66 return QVariant();
67}
67}
plugins/Unity/scope.h−3
@@ -29,9 +29,6 @@
29#include <UnityCore/Scope.h>
29#include <UnityCore/Scope.h>
30#include <UnityCore/Results.h>
30#include <UnityCore/Results.h>
31
31
32−// dee-qt
33−#include "deelistmodel.h"
34−
35#include "categories.h"
32#include "categories.h"
36
33
37class Preview;
34class Preview;
plugins/Unity/variantutils.cpp+2−118
@@ -17,131 +17,15 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
18 */
19
19
20+#include <deelistmodel.h>
20#include "variantutils.h"
21#include "variantutils.h"
21
22
22−/* Returns floating ref */
23−GVariant* GVariantFromQVariant(const QVariant &var)
24−{
25− GVariant *gv = nullptr;
26−
27− switch (var.type()) {
28− case QVariant::String:
29− gv = g_variant_new_string(var.toString().toUtf8());
30− break;
31− case QVariant::UInt:
32− gv = g_variant_new_uint32(var.toUInt());
33− break;
34− case QVariant::Int:
35− gv = g_variant_new_int32(var.toInt());
36− break;
37− case QVariant::LongLong:
38− gv = g_variant_new_int64(var.toLongLong());
39− break;
40− case QVariant::ULongLong:
41− gv = g_variant_new_uint64(var.toULongLong());
42− break;
43− case QVariant::Double:
44− gv = g_variant_new_double(var.toDouble());
45− break;
46− case QVariant::Bool:
47− gv = g_variant_new_boolean(var.toBool());
48− break;
49− case QVariant::Hash: {
50− const auto hash = var.toHash();
51− GVariant **children = new GVariant*[hash.size()];
52− int cnt = 0;
53− QHash<QString, QVariant>::const_iterator it = hash.constBegin();
54− while (it != hash.constEnd()) {
55− GVariant *key = g_variant_new_string(it.key().toUtf8());
56− children[cnt++] = g_variant_new_dict_entry(key, g_variant_new_variant(GVariantFromQVariant(it.value())));
57− ++it;
58− }
59− gv = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, hash.size());
60− delete [] children;
61− break;
62− }
63− default:
64− break;
65− }
66− return gv;
67−}
68−
69−// implementation of this conversion taken from libdee-qt private utility function.
70−QVariant QVariantFromGVariant(GVariant *value)
71−{
72− /* We need to special-case a{sv} here as G_VARIANT_CLASS_ARRAY handles simple arrays;
73− we need to create QVariantHash, not a list */
74− if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARDICT)) {
75− const gsize nChildren = g_variant_n_children(value);
76− QVariantHash hash;
77− for (gsize i = 0; i < nChildren; ++i)
78− {
79− GVariant* dict_entry = g_variant_get_child_value(value, i);
80−
81− gchar* dict_key;
82− GVariant *dict_var;
83− g_variant_get(dict_entry, "{&sv}", &dict_key, &dict_var);
84− hash.insert(QString::fromUtf8(dict_key), QVariantFromGVariant(dict_var));
85− g_variant_unref(dict_var);
86− g_variant_unref(dict_entry);
87− }
88− return hash;
89− }
90−
91− switch (g_variant_classify(value)) {
92− case G_VARIANT_CLASS_BOOLEAN:
93− return QVariant((bool) g_variant_get_boolean(value));
94− case G_VARIANT_CLASS_BYTE:
95− return QVariant((uchar) g_variant_get_byte(value));
96− case G_VARIANT_CLASS_INT16:
97− return QVariant((qint16) g_variant_get_int16(value));
98− case G_VARIANT_CLASS_UINT16:
99− return QVariant((quint16) g_variant_get_uint16(value));
100− case G_VARIANT_CLASS_INT32:
101− return QVariant((qint32) g_variant_get_int32(value));
102− case G_VARIANT_CLASS_UINT32:
103− return QVariant((quint32) g_variant_get_uint32(value));
104− case G_VARIANT_CLASS_INT64:
105− return QVariant((qint64) g_variant_get_int64(value));
106− case G_VARIANT_CLASS_UINT64:
107− return QVariant((quint64) g_variant_get_uint64(value));
108− case G_VARIANT_CLASS_DOUBLE:
109− return QVariant(g_variant_get_double(value));
110− case G_VARIANT_CLASS_STRING:
111− return QVariant(QString::fromUtf8(g_variant_get_string(value, NULL)));
112− case G_VARIANT_CLASS_ARRAY:
113− case G_VARIANT_CLASS_TUPLE:
114− {
115− const gsize nChildren = g_variant_n_children(value);
116− QList<QVariant> array;
117− for (gsize i = 0; i < nChildren; ++i)
118− {
119− GVariant* gvariant = g_variant_get_child_value(value, i);
120− array << QVariantFromGVariant(gvariant);
121− g_variant_unref(gvariant);
122− }
123− return array;
124− }
125− default:
126− /* Fallback on an empty QVariant.
127− FIXME: Missing conversion of following GVariant types:
128− - G_VARIANT_CLASS_HANDLE
129− - G_VARIANT_CLASS_OBJECT_PATH
130− - G_VARIANT_CLASS_SIGNATURE
131− - G_VARIANT_CLASS_VARIANT
132− - G_VARIANT_CLASS_MAYBE
133− - G_VARIANT_CLASS_DICT_ENTRY
134− */
135− return QVariant();
136− }
137−}
138−
139unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val)
23unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val)
140{
24{
141 unity::glib::HintsMap hintsMap;
25 unity::glib::HintsMap hintsMap;
142 QHash<QString, QVariant>::const_iterator it = val.constBegin();
26 QHash<QString, QVariant>::const_iterator it = val.constBegin();
143 while (it != val.constEnd()) {
27 while (it != val.constEnd()) {
144− hintsMap[it.key().toStdString()] = GVariantFromQVariant(it.value());
28+ hintsMap[it.key().toStdString()] = DeeListModel::DataFromVariant(it.value());
145 ++it;
29 ++it;
146 }
30 }
147 return hintsMap;
31 return hintsMap;
plugins/Unity/variantutils.h−2
@@ -26,8 +26,6 @@
26// libunity-core
26// libunity-core
27#include <UnityCore/Variant.h>
27#include <UnityCore/Variant.h>
28
28
29−GVariant* GVariantFromQVariant(const QVariant &value);
30−QVariant QVariantFromGVariant(GVariant *value);
31unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val);
29unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val);
32unity::glib::HintsMap convertToHintsMap(const QVariant &var);
30unity::glib::HintsMap convertToHintsMap(const QVariant &var);
33
31
po/ar.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/az.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/bg.po+2−2
@@ -15,8 +15,8 @@ msgstr ""
15"MIME-Version: 1.0\n"
15"MIME-Version: 1.0\n"
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
19−"X-Generator: Launchpad (build 16696)\n"
19+"X-Generator: Launchpad (build 16723)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
po/ca.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/de.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/el.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/en_AU.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/en_GB.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/eo.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/es.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/fi.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/fo.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/fr.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/gl.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/he.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/hr.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/hu.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/hy.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/id.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/it.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/ja.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/kn.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/ko.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/ky.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/lv.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/my.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/nb.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/nl.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/pl.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/pt_BR.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/ro.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/ru.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/si.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/sl.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/sr.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/sv.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/te.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/tr.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/ug.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/uk.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-22 06:19+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/zh_CN.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/zh_TW.po+2−2
@@ -14,8 +14,8 @@ msgstr ""
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−"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
17+"X-Launchpad-Export-Date: 2013-08-08 05:15+0000\n"
18−"X-Generator: Launchpad (build 16696)\n"
18+"X-Generator: Launchpad (build 16723)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
run_on_device+2−2
@@ -27,8 +27,8 @@ usage() {
27 echo " -k, --keylock Enable a Keyboard lock screen when running"
27 echo " -k, --keylock Enable a Keyboard lock screen when running"
28 echo ""
28 echo ""
29 echo "IMPORTANT:"
29 echo "IMPORTANT:"
30− echo " * Make sure to have the networking and PPAs setup on the device beforehand (phablet-deploy-networking && phablet-ppa-fetch)."
30+ echo " * Make sure to have networking setup on the device beforehand."
31− echo " * Execute that script from a directory containing a branch the shell code."
31+ echo " * Execute that script from a directory containing unity8 code."
32 exit 1
32 exit 1
33}
33}
34
34
tests/autopilot/unity8/indicators_client/tests/test_battery.py+11−5
@@ -26,7 +26,7 @@ class TestDisplayMenus(IndicatorsTestCase):
26 self.pointing_device.move_to_object(self.main_window.get_battery_menu())
26 self.pointing_device.move_to_object(self.main_window.get_battery_menu())
27 self.pointing_device.click()
27 self.pointing_device.click()
28
28
29− fn_loader = lambda: self.app.select_single("IndicatorsPage/QQuickLoader", objectName="page_loader");
29+ fn_loader = lambda: self.app.select_single("IndicatorsPage/QQuickLoader", objectName="pageLoader");
30 self.assertThat(fn_loader, Eventually(NotEquals(None)));
30 self.assertThat(fn_loader, Eventually(NotEquals(None)));
31 page_loader = fn_loader();
31 page_loader = fn_loader();
32 self.assertThat(page_loader.progress, Eventually(Equals(1.0)))
32 self.assertThat(page_loader.progress, Eventually(Equals(1.0)))
@@ -70,7 +70,11 @@ class TestDisplayMenus(IndicatorsTestCase):
70
70
71 # wait for the switch menu item
71 # wait for the switch menu item
72 fn_auto_brightness = lambda: self.app.select_single("SwitchMenuItem", objectName="auto-brightness");
72 fn_auto_brightness = lambda: self.app.select_single("SwitchMenuItem", objectName="auto-brightness");
73+ # FIXME: this should go away when we switch to indicator-power
74+ try:
73− self.assertThat(fn_auto_brightness, Eventually(NotEquals(None)));
75+ self.assertThat(fn_auto_brightness, Eventually(NotEquals(None)));
76+ except AssertionError:
77+ self.skipTest("WARNING: test skipped due to missing indicator-battery")
74 auto_brightness = fn_auto_brightness();
78 auto_brightness = fn_auto_brightness();
75
79
76 old_ab_value = auto_brightness.checked
80 old_ab_value = auto_brightness.checked
@@ -83,10 +87,12 @@ class TestDisplayMenus(IndicatorsTestCase):
83 def test_brightness_slider(self):
87 def test_brightness_slider(self):
84 """Test the auto-bright switch"""
88 """Test the auto-bright switch"""
85
89
86− if self.input_device_class is Touch:
87− self.skipTest("Dragging is broken with Touch input (LP: #1203808).")
88 fn_brightness_menu = lambda: self.app.select_single("SliderMenuItem", objectName="brightness");
90 fn_brightness_menu = lambda: self.app.select_single("SliderMenuItem", objectName="brightness");
91+ # FIXME: this should go away when we switch to indicator-power
92+ try:
89− self.assertThat(fn_brightness_menu, Eventually(NotEquals(None)));
93+ self.assertThat(fn_brightness_menu, Eventually(NotEquals(None)));
94+ except AssertionError:
95+ self.skipTest("WARNING: test skipped due to missing indicator-battery")
90 brightness_menu = fn_brightness_menu();
96 brightness_menu = fn_brightness_menu();
91
97
92 old_ab_value = brightness_menu.value
98 old_ab_value = brightness_menu.value
tests/autopilot/unity8/shell/__init__.py+1−27
@@ -21,9 +21,6 @@
21
21
22from functools import wraps
22from functools import wraps
23import logging
23import logging
24−import os.path
25−
26−from unity8 import get_mocks_library_path, get_default_extra_mock_libraries
27
24
28
25
29logger = logging.getLogger(__name__)
26logger = logging.getLogger(__name__)
@@ -34,31 +31,8 @@ def with_lightdm_mock(mock_type):
34 def with_lightdm_mock_internal(fn):
31 def with_lightdm_mock_internal(fn):
35 @wraps(fn)
32 @wraps(fn)
36 def wrapper(*args, **kwargs):
33 def wrapper(*args, **kwargs):
37− logger.info("Setting up LightDM mock type '%s'", mock_type)
38− new_ld_library_path = "%s:%s" % (
39− get_default_extra_mock_libraries(),
40− _get_ld_library_path(mock_type)
41− )
42− logger.info("New library path: %s", new_ld_library_path)
43 tests_self = args[0]
34 tests_self = args[0]
44− tests_self.patch_environment(
35+ tests_self.patch_lightdm_mock(mock_type)
45− 'LD_LIBRARY_PATH',
46− new_ld_library_path
47− )
48 return fn(*args, **kwargs)
36 return fn(*args, **kwargs)
49 return wrapper
37 return wrapper
50 return with_lightdm_mock_internal
38 return with_lightdm_mock_internal
51−
52−
53−def _get_ld_library_path(mock_type):
54− lib_path = get_mocks_library_path()
55− new_ld_library_path = os.path.abspath(
56− os.path.join(lib_path, "LightDM", mock_type)
57− )
58−
59− if not os.path.exists(new_ld_library_path):
60− raise RuntimeError(
61− "LightDM mock '%s' does not exist at path '%s'."
62− % (mock_type, new_ld_library_path)
63− )
64− return new_ld_library_path
tests/autopilot/unity8/shell/emulators/greeter.py+4−1
@@ -25,7 +25,7 @@ class Greeter(UnityEmulatorBase):
25
25
26 """An emulator that understands the greeter screen."""
26 """An emulator that understands the greeter screen."""
27
27
28− def unlock(self):
28+ def swipe(self):
29 """Swipe the greeter screen away."""
29 """Swipe the greeter screen away."""
30 self.created.wait_for(True)
30 self.created.wait_for(True)
31 touch = Touch.create()
31 touch = Touch.create()
@@ -38,3 +38,6 @@ class Greeter(UnityEmulatorBase):
38 touch.drag(start_x, start_y, stop_x, stop_y)
38 touch.drag(start_x, start_y, stop_x, stop_y)
39
39
40 self.created.wait_for(False)
40 self.created.wait_for(False)
41+
42+ def get_prompt(self):
43+ return self.select_single("TextField", objectName="passwordInput")
tests/autopilot/unity8/shell/emulators/hud.py+4−7
@@ -38,13 +38,10 @@ class Hud(UnityEmulatorBase):
38 window = self.get_root_instance().select_single('QQuickView')
38 window = self.get_root_instance().select_single('QQuickView')
39 hud_show_button = window.select_single("HudButton")
39 hud_show_button = window.select_single("HudButton")
40
40
41− start_x = int(window.x + (window.width / 2))
41+ swipe_coords = self.get_button_swipe_coords(window, hud_show_button)
42− end_x = start_x
43− start_y = window.y + window.height
44− end_y = int(hud_show_button.y + (hud_show_button.height/2))
45
42
46− touch.press(start_x, start_y)
43+ touch.press(swipe_coords.start_x, swipe_coords.start_y)
47− touch._finger_move(end_x, end_y)
44+ touch._finger_move(swipe_coords.end_x, swipe_coords.end_y)
48 try:
45 try:
49 hud_show_button.opacity.wait_for(1.0)
46 hud_show_button.opacity.wait_for(1.0)
50 touch.release()
47 touch.release()
@@ -78,6 +75,6 @@ class Hud(UnityEmulatorBase):
78 start_x = int(main_view.x + (main_view.width / 2))
75 start_x = int(main_view.x + (main_view.width / 2))
79 end_x = start_x
76 end_x = start_x
80 start_y = main_view.y + (main_view.height - 3)
77 start_y = main_view.y + (main_view.height - 3)
81− end_y = int(hud_show_button.y + (hud_show_button.height/2))
78+ end_y = main_view.y + int(hud_show_button.y + (hud_show_button.height/2))
82
79
83 return SwipeCoords(start_x, end_x, start_y, end_y)
80 return SwipeCoords(start_x, end_x, start_y, end_y)
tests/autopilot/unity8/shell/emulators/main_window.py+1−1
@@ -89,4 +89,4 @@ class MainWindow(object):
89 return self.app.select_single("Lockscreen")
89 return self.app.select_single("Lockscreen")
90
90
91 def get_pinentryField(self):
91 def get_pinentryField(self):
92− return self.app.select_single("TextField", objectName="pinentryField")
92+ return self.app.select_single(objectName="pinentryField")
tests/autopilot/unity8/shell/tests/__init__.py+53−1
@@ -19,6 +19,11 @@
19
19
20"""unity autopilot tests."""
20"""unity autopilot tests."""
21
21
22+try:
23+ from gi.repository import Gio
24+except ImportError:
25+ Gio = None
26+
22from autopilot.platform import model
27from autopilot.platform import model
23from autopilot.testcase import AutopilotTestCase
28from autopilot.testcase import AutopilotTestCase
24from autopilot.matchers import Eventually
29from autopilot.matchers import Eventually
@@ -28,7 +33,12 @@ import logging
28import os.path
33import os.path
29from testtools.matchers import Equals, NotEquals
34from testtools.matchers import Equals, NotEquals
30
35
36+from unity8 import (
37+ get_lib_path,
38+ get_binary_path,
31−from unity8 import get_lib_path, get_binary_path, get_mocks_library_path
39+ get_mocks_library_path,
40+ get_default_extra_mock_libraries,
41+)
32from unity8.shell.emulators import UnityEmulatorBase
42from unity8.shell.emulators import UnityEmulatorBase
33from unity8.shell.emulators.dash import Dash
43from unity8.shell.emulators.dash import Dash
34from unity8.shell.emulators.main_window import MainWindow
44from unity8.shell.emulators.main_window import MainWindow
@@ -36,6 +46,10 @@ from unity8.shell.emulators.main_window import MainWindow
36
46
37logger = logging.getLogger(__name__)
47logger = logging.getLogger(__name__)
38
48
49+UNITYSHELL_GSETTINGS_SCHEMA = "org.compiz.unityshell"
50+UNITYSHELL_GSETTINGS_PATH = "/org/compiz/profiles/unity/plugins/unityshell/"
51+UNITYSHELL_LAUNCHER_KEY = "launcher-hide-mode"
52+UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
39
53
40def _get_device_emulation_scenarios():
54def _get_device_emulation_scenarios():
41 if model() == 'Desktop':
55 if model() == 'Desktop':
@@ -64,10 +78,22 @@ class UnityTestCase(AutopilotTestCase):
64
78
65 def setUp(self):
79 def setUp(self):
66 super(UnityTestCase, self).setUp()
80 super(UnityTestCase, self).setUp()
81+ if Gio is not None and UNITYSHELL_GSETTINGS_SCHEMA in Gio.Settings.list_relocatable_schemas():
82+ # Hide Unity launcher
83+ self._unityshell_schema = Gio.Settings.new_with_path(UNITYSHELL_GSETTINGS_SCHEMA, UNITYSHELL_GSETTINGS_PATH)
84+ self._launcher_hide_mode = self._unityshell_schema.get_int(UNITYSHELL_LAUNCHER_KEY)
85+ self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, UNITYSHELL_LAUNCHER_MODE)
86+ self.addCleanup(self._reset_launcher)
87+
67 self._proxy = None
88 self._proxy = None
89+ self._lightdm_mock_type = None
68 self.touch = Touch.create()
90 self.touch = Touch.create()
69 self._setup_display_details()
91 self._setup_display_details()
70
92
93+ def _reset_launcher(self):
94+ """Reset Unity launcher hide mode"""
95+ self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, self._launcher_hide_mode)
96+
71 def _setup_display_details(self):
97 def _setup_display_details(self):
72 scale_divisor = self._determine_geometry()
98 scale_divisor = self._determine_geometry()
73 self._setup_grid_size(scale_divisor)
99 self._setup_grid_size(scale_divisor)
@@ -133,6 +159,8 @@ class UnityTestCase(AutopilotTestCase):
133 binary_path
159 binary_path
134 )
160 )
135
161
162+ if self._lightdm_mock_type is None:
163+ self.patch_lightdm_mock()
136 self._setup_extra_mock_environment_patch()
164 self._setup_extra_mock_environment_patch()
137
165
138 app_proxy = self.launch_test_application(
166 app_proxy = self.launch_test_application(
@@ -150,6 +178,30 @@ class UnityTestCase(AutopilotTestCase):
150
178
151 return app_proxy
179 return app_proxy
152
180
181+ def patch_lightdm_mock(self, mock_type='single'):
182+ self._lightdm_mock_type = mock_type
183+ logger.info("Setting up LightDM mock type '%s'", mock_type)
184+ new_ld_library_path = "%s:%s" % (
185+ get_default_extra_mock_libraries(),
186+ self._get_lightdm_mock_path(mock_type)
187+ )
188+ logger.info("New library path: %s", new_ld_library_path)
189+
190+ self.patch_environment('LD_LIBRARY_PATH', new_ld_library_path)
191+
192+ def _get_lightdm_mock_path(self, mock_type):
193+ lib_path = get_mocks_library_path()
194+ lightdm_mock_path = os.path.abspath(
195+ os.path.join(lib_path, "LightDM", mock_type)
196+ )
197+
198+ if not os.path.exists(lightdm_mock_path):
199+ raise RuntimeError(
200+ "LightDM mock '%s' does not exist at path '%s'."
201+ % (mock_type, lightdm_mock_path)
202+ )
203+ return lightdm_mock_path
204+
153 def _setup_extra_mock_environment_patch(self):
205 def _setup_extra_mock_environment_patch(self):
154 mocks_library_path = get_mocks_library_path()
206 mocks_library_path = get_mocks_library_path()
155 self.patch_environment('QML2_IMPORT_PATH', mocks_library_path)
207 self.patch_environment('QML2_IMPORT_PATH', mocks_library_path)
tests/autopilot/unity8/shell/tests/test_hud.py+5−10
@@ -32,13 +32,12 @@ class TestHud(UnityTestCase):
32
32
33 scenarios = _get_device_emulation_scenarios()
33 scenarios = _get_device_emulation_scenarios()
34
34
35− @with_lightdm_mock("single")
36 def test_show_hud_button_appears(self):
35 def test_show_hud_button_appears(self):
37 """Swiping up while an app is active must show the 'show hud' button.
36 """Swiping up while an app is active must show the 'show hud' button.
38
37
39 """
38 """
40 self.launch_unity()
39 self.launch_unity()
41− self.main_window.get_greeter().unlock()
40+ self.main_window.get_greeter().swipe()
42 window = self.main_window.get_qml_view()
41 window = self.main_window.get_qml_view()
43 hud_show_button = self.main_window.get_hud_show_button()
42 hud_show_button = self.main_window.get_hud_show_button()
44 hud = self.main_window.get_hud()
43 hud = self.main_window.get_hud()
@@ -54,13 +53,12 @@ class TestHud(UnityTestCase):
54 self.touch._finger_move(swipe_coords.end_x, swipe_coords.end_y)
53 self.touch._finger_move(swipe_coords.end_x, swipe_coords.end_y)
55 self.assertThat(hud_show_button.opacity, Eventually(Equals(1.0)))
54 self.assertThat(hud_show_button.opacity, Eventually(Equals(1.0)))
56
55
57− @with_lightdm_mock("single")
58 def test_show_hud_appears(self):
56 def test_show_hud_appears(self):
59 """Releasing the touch on the 'show hud' button must display the hud.
57 """Releasing the touch on the 'show hud' button must display the hud.
60
58
61 """
59 """
62 self.launch_unity()
60 self.launch_unity()
63− self.main_window.get_greeter().unlock()
61+ self.main_window.get_greeter().swipe()
64 window = self.main_window.get_qml_view()
62 window = self.main_window.get_qml_view()
65 hud_show_button = self.main_window.get_hud_show_button()
63 hud_show_button = self.main_window.get_hud_show_button()
66 hud = self.main_window.get_hud()
64 hud = self.main_window.get_hud()
@@ -80,11 +78,10 @@ class TestHud(UnityTestCase):
80 self.touch.release()
78 self.touch.release()
81 self.assertThat(hud.shown, Eventually(Equals(True)))
79 self.assertThat(hud.shown, Eventually(Equals(True)))
82
80
83− @with_lightdm_mock("single")
84 def test_hide_hud_click(self):
81 def test_hide_hud_click(self):
85 """Tapping the close button of the Hud must dismiss it."""
82 """Tapping the close button of the Hud must dismiss it."""
86 self.launch_unity()
83 self.launch_unity()
87− self.main_window.get_greeter().unlock()
84+ self.main_window.get_greeter().swipe()
88 hud = self.main_window.get_hud()
85 hud = self.main_window.get_hud()
89
86
90 self._launch_test_app_from_app_screen()
87 self._launch_test_app_from_app_screen()
@@ -94,14 +91,13 @@ class TestHud(UnityTestCase):
94 self.touch.tap(x, y)
91 self.touch.tap(x, y)
95 self.assertThat(hud.shown, Eventually(Equals(False)))
92 self.assertThat(hud.shown, Eventually(Equals(False)))
96
93
97− @with_lightdm_mock("single")
98 def test_hide_hud_dragging(self):
94 def test_hide_hud_dragging(self):
99 """Once open the Hud must close if the upper bar is dragged and
95 """Once open the Hud must close if the upper bar is dragged and
100 released downward.
96 released downward.
101
97
102 """
98 """
103 self.launch_unity()
99 self.launch_unity()
104− self.main_window.get_greeter().unlock()
100+ self.main_window.get_greeter().swipe()
105 hud = self.main_window.get_hud()
101 hud = self.main_window.get_hud()
106 window = self.main_window.get_qml_view()
102 window = self.main_window.get_qml_view()
107
103
@@ -115,11 +111,10 @@ class TestHud(UnityTestCase):
115 self.touch.drag(start_x, start_y, end_x, end_y)
111 self.touch.drag(start_x, start_y, end_x, end_y)
116 self.assertThat(hud.shown, Eventually(Equals(False)))
112 self.assertThat(hud.shown, Eventually(Equals(False)))
117
113
118− @with_lightdm_mock("single")
119 def test_launcher_hides_hud(self):
114 def test_launcher_hides_hud(self):
120 """Opening the Launcher while the Hud is active must close the Hud."""
115 """Opening the Launcher while the Hud is active must close the Hud."""
121 self.launch_unity()
116 self.launch_unity()
122− self.main_window.get_greeter().unlock()
117+ self.main_window.get_greeter().swipe()
123 hud = self.main_window.get_hud()
118 hud = self.main_window.get_hud()
124 launcher = self.main_window.get_launcher()
119 launcher = self.main_window.get_launcher()
125
120
tests/autopilot/unity8/shell/tests/test_lock_screen.py+58−28
@@ -40,54 +40,68 @@ class TestLockscreen(UnityTestCase):
40 """Must be able to unlock the PIN entry lock screen."""
40 """Must be able to unlock the PIN entry lock screen."""
41 self.launch_unity()
41 self.launch_unity()
42 greeter = self.main_window.get_greeter()
42 greeter = self.main_window.get_greeter()
43− greeter.unlock()
44
43
44+ if greeter.narrowMode:
45+ greeter.swipe()
45− lockscreen = self._wait_for_lockscreen()
46+ lockscreen = self._wait_for_lockscreen()
46− self._enter_pincode("1234")
47+ self._enter_pincode("1234")
48+ self.assertThat(lockscreen.shown, Eventually(Equals(False)))
49+ else:
50+ self._enter_prompt_passphrase("1234")
51+ self.assertThat(greeter.shown, Eventually(Equals(False)))
47
52
48− self.assertThat(lockscreen.shown, Eventually(Equals(False)))
49−
50− @skipUnless(model() == 'Desktop', "Broken passphrase entry on UInput (LP: #1203788).")
51 @with_lightdm_mock("single-passphrase")
53 @with_lightdm_mock("single-passphrase")
52 def test_can_unlock_passphrase_screen(self):
54 def test_can_unlock_passphrase_screen(self):
53 """Must be able to unlock the passphrase entry screen."""
55 """Must be able to unlock the passphrase entry screen."""
54 self.launch_unity()
56 self.launch_unity()
55 greeter = self.main_window.get_greeter()
57 greeter = self.main_window.get_greeter()
56− greeter.unlock()
57−
58− lockscreen = self._wait_for_lockscreen()
59− self._enter_passphrase("password")
60
58
59+ if greeter.narrowMode:
60+ greeter.swipe()
61+ lockscreen = self._wait_for_lockscreen()
62+ self._enter_pin_passphrase("password")
61− self.assertThat(lockscreen.shown, Eventually(Equals(False)))
63+ self.assertThat(lockscreen.shown, Eventually(Equals(False)))
64+ else:
65+ self._enter_prompt_passphrase("password")
66+ self.assertThat(greeter.shown, Eventually(Equals(False)))
62
67
63 @with_lightdm_mock("single-pin")
68 @with_lightdm_mock("single-pin")
64 def test_pin_screen_wrong_code(self):
69 def test_pin_screen_wrong_code(self):
65 """Entering the wrong pin code must not dismiss the lock screen."""
70 """Entering the wrong pin code must not dismiss the lock screen."""
66 self.launch_unity()
71 self.launch_unity()
67 greeter = self.main_window.get_greeter()
72 greeter = self.main_window.get_greeter()
68− greeter.unlock()
69−
70− lockscreen = self._wait_for_lockscreen()
71− self._enter_pincode("4321")
72
73
74+ if greeter.narrowMode:
75+ greeter.swipe()
76+ lockscreen = self._wait_for_lockscreen()
77+ self._enter_pincode("4321")
73− pinentryField = self.main_window.get_pinentryField()
78+ pinentryField = self.main_window.get_pinentryField()
74− self.assertThat(pinentryField.text, Eventually(Equals("")))
79+ self.assertThat(pinentryField.text, Eventually(Equals("")))
80+ self.assertThat(lockscreen.shown, Eventually(Equals(True)))
81+ else:
82+ self._enter_prompt_passphrase("4231")
83+ prompt = self.main_window.get_greeter().get_prompt()
84+ self.assertThat(prompt.text, Eventually(Equals("")))
75− self.assertThat(lockscreen.shown, Eventually(Equals(True)))
85+ self.assertThat(greeter.shown, Eventually(Equals(True)))
76
86
77− @skipUnless(model() == 'Desktop', "Broken passphrase entry on UInput (LP: #1203788).")
78 @with_lightdm_mock("single-passphrase")
87 @with_lightdm_mock("single-passphrase")
79 def test_passphrase_screen_wrong_password(self):
88 def test_passphrase_screen_wrong_password(self):
80 """Entering the wrong password must not dismiss the lock screen."""
89 """Entering the wrong password must not dismiss the lock screen."""
81 self.launch_unity()
90 self.launch_unity()
82 greeter = self.main_window.get_greeter()
91 greeter = self.main_window.get_greeter()
83− greeter.unlock()
84
92
93+ if greeter.narrowMode:
94+ greeter.swipe()
85− lockscreen = self._wait_for_lockscreen()
95+ lockscreen = self._wait_for_lockscreen()
86− self._enter_passphrase("foobar")
96+ self._enter_pin_passphrase("foobar")
87−
88− pinentryField = self.main_window.get_pinentryField()
97+ pinentryField = self.main_window.get_pinentryField()
89− self.assertThat(pinentryField.text, Eventually(Equals("")))
98+ self.assertThat(pinentryField.text, Eventually(Equals("")))
99+ self.assertThat(lockscreen.shown, Eventually(Equals(True)))
100+ else:
101+ self._enter_prompt_passphrase("foobar")
102+ prompt = self.main_window.get_greeter().get_prompt()
103+ self.assertThat(prompt.text, Eventually(Equals("")))
90− self.assertThat(lockscreen.shown, Eventually(Equals(True)))
104+ self.assertThat(greeter.shown, Eventually(Equals(True)))
91
105
92 def _wait_for_lockscreen(self):
106 def _wait_for_lockscreen(self):
93 """Wait for the lock screen to load, and return it."""
107 """Wait for the lock screen to load, and return it."""
@@ -116,9 +130,9 @@ class TestLockscreen(UnityTestCase):
116 )
130 )
117 self.touch.tap_object(self.main_window.get_pinPadButton(int(num)))
131 self.touch.tap_object(self.main_window.get_pinPadButton(int(num)))
118
132
119− def _enter_passphrase(self, passphrase):
133+ def _enter_pin_passphrase(self, passphrase):
120 """Enter the password specified in 'passphrase' into the password entry
134 """Enter the password specified in 'passphrase' into the password entry
121− field.
135+ field of the pin lock screen.
122
136
123 :param passphrase: The string you want to enter.
137 :param passphrase: The string you want to enter.
124 :raises: TypeError if passphrase is not a string.
138 :raises: TypeError if passphrase is not a string.
@@ -131,3 +145,19 @@ class TestLockscreen(UnityTestCase):
131 self.touch.tap_object(pinentryField)
145 self.touch.tap_object(pinentryField)
132 self.keyboard.type(passphrase)
146 self.keyboard.type(passphrase)
133 self.keyboard.type("\n")
147 self.keyboard.type("\n")
148+
149+ def _enter_prompt_passphrase(self, passphrase):
150+ """Enter the password specified in 'passphrase' into the password entry
151+ field of the main user list's prompt.
152+
153+ :param passphrase: The string you want to enter.
154+ :raises: TypeError if passphrase is not a string.
155+
156+ """
157+ if not isinstance(passphrase, basestring):
158+ raise TypeError("'passphrase' parameter must be a string.")
159+
160+ prompt = self.main_window.get_greeter().get_prompt()
161+ self.touch.tap_object(prompt)
162+ self.keyboard.type(passphrase)
163+ self.keyboard.type("\n")
tests/mocks/CMakeLists.txt+1
@@ -1,5 +1,6 @@
1add_subdirectory(libusermetrics)
1add_subdirectory(libusermetrics)
2add_subdirectory(LightDM)
2add_subdirectory(LightDM)
3+add_subdirectory(QMenuModel)
3add_subdirectory(Ubuntu)
4add_subdirectory(Ubuntu)
4add_subdirectory(Unity)
5add_subdirectory(Unity)
5add_subdirectory(HudClient)
6add_subdirectory(HudClient)
tests/mocks/LightDM/single/GreeterPrivate.cpp+2−4
@@ -34,10 +34,8 @@ void GreeterPrivate::handleAuthenticate()
34{
34{
35 Q_Q(Greeter);
35 Q_Q(Greeter);
36
36
37− if (authenticationUser == "one") {
38− authenticated = true;
37+ authenticated = true;
39− Q_EMIT q->authenticationComplete();
38+ Q_EMIT q->authenticationComplete();
40− }
41}
39}
42
40
43void GreeterPrivate::handleRespond(QString const &response)
41void GreeterPrivate::handleRespond(QString const &response)
tests/mocks/QMenuModel/CMakeLists.txtnew file+11
@@ -0,0 +1,11 @@
1+file(GLOB QMLFILES
2+ *.qml
3+ *.js
4+ qmldir
5+)
6+
7+# copy files into build directory for shadow builds
8+add_custom_target(QMenuModelQmlFiles ALL
9+ COMMAND cp ${QMLFILES} ${CMAKE_CURRENT_BINARY_DIR}
10+ DEPENDS ${QMLFILES}
11+)
tests/mocks/QMenuModel/QDBusActionGroup.qmlnew file+27
@@ -0,0 +1,27 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Daniel d'Andrada <daniel.dandrada@canonical.com>
6+ *
7+ * 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
9+ * the Free Software Foundation; version 3.
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+import QtQuick 2.0
21+
22+QtObject {
23+ property int busType
24+ property string busName
25+ property string objectPath
26+ function start() {}
27+}
tests/mocks/QMenuModel/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module QMenuModel
2+QDBusActionGroup 0.1 QDBusActionGroup.qml
tests/mocks/Ubuntu/Application/ApplicationManager.cpp+6−2
@@ -37,8 +37,6 @@ ApplicationManager::ApplicationManager(QObject *parent)
37 , m_sideStage(0)
37 , m_sideStage(0)
38{
38{
39 buildListOfAvailableApplications();
39 buildListOfAvailableApplications();
40− createMainStageComponent();
41− createSideStageComponent();
42}
40}
43
41
44ApplicationManager::~ApplicationManager()
42ApplicationManager::~ApplicationManager()
@@ -403,6 +401,9 @@ void ApplicationManager::createMainStageComponent()
403
401
404void ApplicationManager::createMainStage()
402void ApplicationManager::createMainStage()
405{
403{
404+ if (!m_mainStageComponent)
405+ createMainStageComponent();
406+
406 // The assumptions I make here really should hold.
407 // The assumptions I make here really should hold.
407 QQuickView *quickView =
408 QQuickView *quickView =
408 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
409 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
@@ -437,6 +438,9 @@ void ApplicationManager::createSideStageComponent()
437
438
438void ApplicationManager::createSideStage()
439void ApplicationManager::createSideStage()
439{
440{
441+ if (!m_sideStageComponent)
442+ createSideStageComponent();
443+
440 // The assumptions I make here really should hold.
444 // The assumptions I make here really should hold.
441 QQuickView *quickView =
445 QQuickView *quickView =
442 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
446 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
tests/mocks/Ubuntu/Application/ApplicationManager.h+4
@@ -46,6 +46,8 @@ class ApplicationManager : public QObject {
46 Q_PROPERTY(ApplicationInfo* sideStageFocusedApplication READ sideStageFocusedApplication
46 Q_PROPERTY(ApplicationInfo* sideStageFocusedApplication READ sideStageFocusedApplication
47 NOTIFY sideStageFocusedApplicationChanged)
47 NOTIFY sideStageFocusedApplicationChanged)
48
48
49+ Q_PROPERTY(bool fake READ fake CONSTANT)
50+
49 public:
51 public:
50 ApplicationManager(QObject *parent = NULL);
52 ApplicationManager(QObject *parent = NULL);
51 virtual ~ApplicationManager();
53 virtual ~ApplicationManager();
@@ -80,6 +82,8 @@ class ApplicationManager : public QObject {
80 ApplicationInfo* mainStageFocusedApplication() const;
82 ApplicationInfo* mainStageFocusedApplication() const;
81 ApplicationInfo* sideStageFocusedApplication() const;
83 ApplicationInfo* sideStageFocusedApplication() const;
82
84
85+ bool fake() { return true; }
86+
83 Q_INVOKABLE void focusApplication(int handle);
87 Q_INVOKABLE void focusApplication(int handle);
84 Q_INVOKABLE void unfocusCurrentApplication(StageHint stageHint);
88 Q_INVOKABLE void unfocusCurrentApplication(StageHint stageHint);
85 Q_INVOKABLE ApplicationInfo* startProcess(QString desktopFile,
89 Q_INVOKABLE ApplicationInfo* startProcess(QString desktopFile,
tests/mocks/Unity/CMakeLists.txt+1
@@ -44,3 +44,4 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
44 )
44 )
45
45
46add_subdirectory(Launcher)
46add_subdirectory(Launcher)
47+add_subdirectory(Notifications)
tests/mocks/Unity/Indicators/qml/fake_menu_page1.qml−8
@@ -32,13 +32,5 @@ Indicators.FakeMenuPage {
32 horizontalCenter: parent.horizontalCenter
32 horizontalCenter: parent.horizontalCenter
33 verticalCenter: parent.verticalCenter
33 verticalCenter: parent.verticalCenter
34 }
34 }
35−
36− NumberAnimation on rotation {
37− id: rotation_animation
38− from: 0
39− to: 360
40− duration: 5000
41− loops: Animation.Infinite
42− }
43 }
35 }
44}
36}
tests/mocks/Unity/Indicators/qml/fake_menu_page2.qml−8
@@ -32,13 +32,5 @@ Indicators.FakeMenuPage {
32 horizontalCenter: parent.horizontalCenter
32 horizontalCenter: parent.horizontalCenter
33 verticalCenter: parent.verticalCenter
33 verticalCenter: parent.verticalCenter
34 }
34 }
35−
36− NumberAnimation on rotation {
37− id: rotation_animation
38− from: 0
39− to: 360
40− duration: 5000
41− loops: Animation.Infinite
42− }
43 }
35 }
44}
36}
tests/mocks/Unity/Indicators/qml/fake_menu_page3.qml−8
@@ -32,13 +32,5 @@ Indicators.FakeMenuPage {
32 horizontalCenter: parent.horizontalCenter
32 horizontalCenter: parent.horizontalCenter
33 verticalCenter: parent.verticalCenter
33 verticalCenter: parent.verticalCenter
34 }
34 }
35−
36− NumberAnimation on rotation {
37− id: rotation_animation
38− from: 0
39− to: 360
40− duration: 5000
41− loops: Animation.Infinite
42− }
43 }
35 }
44}
36}
tests/mocks/Unity/Indicators/qml/fake_menu_page4.qml−8
@@ -32,13 +32,5 @@ Indicators.FakeMenuPage {
32 horizontalCenter: parent.horizontalCenter
32 horizontalCenter: parent.horizontalCenter
33 verticalCenter: parent.verticalCenter
33 verticalCenter: parent.verticalCenter
34 }
34 }
35−
36− NumberAnimation on rotation {
37− id: rotation_animation
38− from: 0
39− to: 360
40− duration: 5000
41− loops: Animation.Infinite
42− }
43 }
35 }
44}
36}
tests/mocks/Unity/Indicators/qml/fake_menu_page5.qml−8
@@ -32,13 +32,5 @@ Indicators.FakeMenuPage {
32 horizontalCenter: parent.horizontalCenter
32 horizontalCenter: parent.horizontalCenter
33 verticalCenter: parent.verticalCenter
33 verticalCenter: parent.verticalCenter
34 }
34 }
35−
36− NumberAnimation on rotation {
37− id: rotation_animation
38− from: 0
39− to: 360
40− duration: 5000
41− loops: Animation.Infinite
42− }
43 }
35 }
44}
36}
tests/mocks/Unity/Notifications/CMakeLists.txtnew file+11
@@ -0,0 +1,11 @@
1+file(GLOB QMLFILES
2+ *.qml
3+ *.js
4+ qmldir
5+)
6+
7+# copy files into build directory for shadow builds
8+add_custom_target(NotificationsQmlFiles ALL
9+ COMMAND cp ${QMLFILES} ${CMAKE_CURRENT_BINARY_DIR}
10+ DEPENDS ${QMLFILES}
11+)
tests/mocks/Unity/fake_categories.cpp+5−2
@@ -32,10 +32,11 @@ Categories::Categories(QObject* parent)
32 m_roles[Categories::RoleName] = "name";
32 m_roles[Categories::RoleName] = "name";
33 m_roles[Categories::RoleIcon] = "icon";
33 m_roles[Categories::RoleIcon] = "icon";
34 m_roles[Categories::RoleRenderer] = "renderer";
34 m_roles[Categories::RoleRenderer] = "renderer";
35− m_roles[Categories::RoleContentType] = "content_type";
35+ m_roles[Categories::RoleContentType] = "contentType";
36 m_roles[Categories::RoleHints] = "hints";
36 m_roles[Categories::RoleHints] = "hints";
37 m_roles[Categories::RoleResults] = "results";
37 m_roles[Categories::RoleResults] = "results";
38 m_roles[Categories::RoleCount] = "count";
38 m_roles[Categories::RoleCount] = "count";
39+ m_roles[Categories::RoleCategoryIndex] = "categoryIndex";
39
40
40 // TODO This should not be needed but accumulatting the count changes
41 // TODO This should not be needed but accumulatting the count changes
41 // makes the visualization more stable and also makes crashes on fast
42 // makes the visualization more stable and also makes crashes on fast
@@ -154,7 +155,7 @@ Categories::data(const QModelIndex& index, int role) const
154
155
155 switch (role) {
156 switch (role) {
156 case RoleId:
157 case RoleId:
157− return QVariant::fromValue(index.row());
158+ return DeeListModel::data(index, 0); //ID
158 case RoleName:
159 case RoleName:
159 return DeeListModel::data(index, 1); //DISPLAY_NAME
160 return DeeListModel::data(index, 1); //DISPLAY_NAME
160 case RoleIcon:
161 case RoleIcon:
@@ -172,6 +173,8 @@ Categories::data(const QModelIndex& index, int role) const
172 return QVariant::fromValue(getFilter(index.row()));
173 return QVariant::fromValue(getFilter(index.row()));
173 case RoleCount:
174 case RoleCount:
174 return QVariant::fromValue(getFilter(index.row())->rowCount());
175 return QVariant::fromValue(getFilter(index.row())->rowCount());
176+ case RoleCategoryIndex:
177+ return QVariant::fromValue(index.row());
175 default:
178 default:
176 return QVariant();
179 return QVariant();
177 }
180 }
tests/mocks/Unity/fake_categories.h+2−1
@@ -41,7 +41,8 @@ public:
41 RoleContentType,
41 RoleContentType,
42 RoleHints,
42 RoleHints,
43 RoleResults,
43 RoleResults,
44− RoleCount
44+ RoleCount,
45+ RoleCategoryIndex
45 };
46 };
46
47
47 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
48 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
tests/mocks/Unity/fake_scopes.cpp+2−2
@@ -52,8 +52,8 @@ void Scopes::updateScopes()
52 clear();
52 clear();
53 addScope(new Scope("MockScope1", "People", true, this));
53 addScope(new Scope("MockScope1", "People", true, this));
54 addScope(new Scope("MockScope2", "Music", false, this));
54 addScope(new Scope("MockScope2", "Music", false, this));
55− addScope(new Scope("MockScope3", "Home", true, this));
55+ addScope(new Scope("home.scope", "Home", true, this));
56− addScope(new Scope("MockScope4", "Applications", true, this));
56+ addScope(new Scope("applications.scope", "Applications", true, this));
57 addScope(new Scope("MockScope5", "Videos", true, this));
57 addScope(new Scope("MockScope5", "Videos", true, this));
58
58
59 if (!m_loaded) {
59 if (!m_loaded) {
tests/plugins/ListViewWithPageHeader/CMakeLists.txt+6−1
@@ -1,7 +1,12 @@
1# There's no cmake var for v8 include path :-/
1# There's no cmake var for v8 include path :-/
2# so create one
2# so create one
3LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
3LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
4+if(${Qt5Core_VERSION_STRING} VERSION_LESS "5.1.0")
4−SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
5+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
6+else()
7+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
8+endif()
9+
5
10
6include_directories(
11include_directories(
7 ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
12 ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+237−3
@@ -22,7 +22,11 @@
22#include <QtTestGui>
22#include <QtTestGui>
23#pragma GCC diagnostic push
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-pedantic"
24#pragma GCC diagnostic ignored "-pedantic"
25+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
25#include <private/qquicklistmodel_p.h>
26#include <private/qquicklistmodel_p.h>
27+#else
28+#include <private/qqmllistmodel_p.h>
29+#endif
26#include <private/qquickanimation_p.h>
30#include <private/qquickanimation_p.h>
27#include <private/qquickitem_p.h>
31#include <private/qquickitem_p.h>
28#pragma GCC diagnostic pop
32#pragma GCC diagnostic pop
@@ -115,7 +119,11 @@ private Q_SLOTS:
115 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
119 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
116 view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test.qml"));
120 view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test.qml"));
117 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
121 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
122+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
118 model = view->rootObject()->findChild<QQuickListModel*>();
123 model = view->rootObject()->findChild<QQuickListModel*>();
124+#else
125+ model = view->rootObject()->findChild<QQmlListModel*>();
126+#endif
119 otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
127 otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
120 QVERIFY(lvwph);
128 QVERIFY(lvwph);
121 QVERIFY(model);
129 QVERIFY(model);
@@ -1237,7 +1245,7 @@ private Q_SLOTS:
1237
1245
1238 lvwph->showHeader();
1246 lvwph->showHeader();
1239
1247
1240− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1248+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1241 QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1249 QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1242 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1250 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1243 verifyItem(0, -375., 150., true);
1251 verifyItem(0, -375., 150., true);
@@ -1293,7 +1301,7 @@ private Q_SLOTS:
1293
1301
1294 lvwph->showHeader();
1302 lvwph->showHeader();
1295
1303
1296− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1304+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1297 QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1305 QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1298 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1306 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1299 verifyItem(0, -20., 150., false);
1307 verifyItem(0, -20., 150., false);
@@ -1331,7 +1339,7 @@ private Q_SLOTS:
1331
1339
1332 lvwph->showHeader();
1340 lvwph->showHeader();
1333
1341
1334− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1342+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1335 QTRY_VERIFY (lvwph->isAtYEnd());
1343 QTRY_VERIFY (lvwph->isAtYEnd());
1336 }
1344 }
1337
1345
@@ -1382,10 +1390,236 @@ private Q_SLOTS:
1382 lvwph->showHeader();
1390 lvwph->showHeader();
1383 }
1391 }
1384
1392
1393+ void testCullOnBottomEdge()
1394+ {
1395+ changeContentY(200);
1396+
1397+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1398+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1399+ verifyItem(0, -150., 150., true);
1400+ verifyItem(1, 0., 200., false);
1401+ verifyItem(2, 200., 350., false);
1402+ verifyItem(3, 550., 350., true);
1403+ QCOMPARE(lvwph->m_minYExtent, 0.);
1404+ QCOMPARE(lvwph->m_clipItem->y(), 200.);
1405+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1406+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1407+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1408+ QCOMPARE(lvwph->contentY(), 200.);
1409+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1410+ }
1411+
1412+ void testMaximizeVisibleArea()
1413+ {
1414+ bool res = lvwph->maximizeVisibleArea(2);
1415+ QVERIFY(res);
1416+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1417+
1418+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1419+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1420+ verifyItem(0, -158., 150., true);
1421+ verifyItem(1, -8., 200., false);
1422+ verifyItem(2, 192, 350., false);
1423+ verifyItem(3, 542, 350., true);
1424+ QCOMPARE(lvwph->m_minYExtent, 0.);
1425+ QCOMPARE(lvwph->m_clipItem->y(), 208.);
1426+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1427+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1428+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1429+ QCOMPARE(lvwph->contentY(), 208.);
1430+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1431+ }
1432+
1433+ void testMaximizeVisibleAreaVisibleItems()
1434+ {
1435+ bool res = lvwph->maximizeVisibleArea(0);
1436+ QVERIFY(res);
1437+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1438+
1439+ verifyInitialTopPosition();
1440+
1441+ res = lvwph->maximizeVisibleArea(1);
1442+ QVERIFY(res);
1443+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1444+
1445+ verifyInitialTopPosition();
1446+ }
1447+
1448+ void testMaximizeVisibleAreaInvalidIndexes()
1449+ {
1450+ bool res = lvwph->maximizeVisibleArea(-1);
1451+ QVERIFY(!res);
1452+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1453+
1454+ verifyInitialTopPosition();
1455+
1456+ res = lvwph->maximizeVisibleArea(1000);
1457+ QVERIFY(!res);
1458+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1459+
1460+ verifyInitialTopPosition();
1461+
1462+ res = lvwph->maximizeVisibleArea(4);
1463+ QVERIFY(!res);
1464+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1465+
1466+ verifyInitialTopPosition();
1467+ }
1468+
1469+ void testMaximizeVisibleAreaBigElement()
1470+ {
1471+ model->setProperty(2, "size", 4000);
1472+ bool res = lvwph->maximizeVisibleArea(2);
1473+ QVERIFY(res);
1474+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1475+
1476+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1477+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1478+ verifyItem(0, -350., 150., true);
1479+ verifyItem(1, -200., 200., true);
1480+ verifyItem(2, 0, 4000., false);
1481+ QCOMPARE(lvwph->m_minYExtent, 0.);
1482+ QCOMPARE(lvwph->m_clipItem->y(), 400.);
1483+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1484+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1485+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1486+ QCOMPARE(lvwph->contentY(), 400.);
1487+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1488+ }
1489+
1490+ void testMaximizeVisibleAreaScrollDown()
1491+ {
1492+ changeContentY(250);
1493+ bool res = lvwph->maximizeVisibleArea(1);
1494+ QVERIFY(res);
1495+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1496+
1497+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1498+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1499+ verifyItem(0, -150., 150., true);
1500+ verifyItem(1, 0., 200., false);
1501+ verifyItem(2, 200, 350., false);
1502+ verifyItem(3, 550, 350., true);
1503+ QCOMPARE(lvwph->m_minYExtent, 0.);
1504+ QCOMPARE(lvwph->m_clipItem->y(), 200.);
1505+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1506+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1507+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1508+ QCOMPARE(lvwph->contentY(), 200.);
1509+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1510+ }
1511+
1512+ void testMaximizeVisibleAreaScrollDownBigElement()
1513+ {
1514+ model->setProperty(1, "size", 1000);
1515+ changeContentY(1150);
1516+ bool res = lvwph->maximizeVisibleArea(1);
1517+ QVERIFY(res);
1518+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1519+
1520+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 2);
1521+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1522+ verifyItem(0, -458., 1000., false);
1523+ verifyItem(1, 542., 350., true);
1524+ QCOMPARE(lvwph->m_minYExtent, 362.5);
1525+ QCOMPARE(lvwph->m_clipItem->y(), 658.);
1526+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1527+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1528+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1529+ QCOMPARE(lvwph->contentY(), 658.);
1530+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1531+ }
1532+
1533+ void testMaximizeVisibleAreaBigElementInTheMiddle()
1534+ {
1535+ model->setProperty(1, "size", 1000);
1536+ changeContentY(650);
1537+
1538+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 2);
1539+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1540+ verifyItem(0, -450., 1000., false);
1541+ verifyItem(1, 550., 350., true);
1542+ QCOMPARE(lvwph->m_minYExtent, 525.);
1543+ QCOMPARE(lvwph->m_clipItem->y(), 650.);
1544+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1545+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1546+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1547+ QCOMPARE(lvwph->contentY(), 650.);
1548+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1549+
1550+ bool res = lvwph->maximizeVisibleArea(1);
1551+ QVERIFY(res);
1552+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1553+
1554+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 2);
1555+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1556+ verifyItem(0, -450., 1000., false);
1557+ verifyItem(1, 550., 350., true);
1558+ QCOMPARE(lvwph->m_minYExtent, 525.);
1559+ QCOMPARE(lvwph->m_clipItem->y(), 650.);
1560+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1561+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1562+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1563+ QCOMPARE(lvwph->contentY(), 650.);
1564+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1565+ }
1566+
1567+ void testMaximizeVisibleAreaTopWithHalfPageHeader()
1568+ {
1569+ changeContentY(430);
1570+ changeContentY(-30);
1571+
1572+ bool res = lvwph->maximizeVisibleArea(1);
1573+ QVERIFY(res);
1574+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1575+
1576+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1577+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1578+ verifyItem(0, -150., 150., true);
1579+ verifyItem(1, 0., 200., false);
1580+ verifyItem(2, 200, 350., false);
1581+ verifyItem(3, 550, 350., true);
1582+ QCOMPARE(lvwph->m_minYExtent, 0.);
1583+ QCOMPARE(lvwph->m_clipItem->y(), 200.);
1584+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1585+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1586+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1587+ QCOMPARE(lvwph->contentY(), 200.);
1588+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1589+ }
1590+
1591+ void testMaximizeVisibleAreaBottomWithHalfPageHeader()
1592+ {
1593+ changeContentY(430);
1594+ changeContentY(-30);
1595+
1596+ bool res = lvwph->maximizeVisibleArea(3);
1597+ QVERIFY(res);
1598+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1599+
1600+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1601+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1602+ verifyItem(0, -358., 200., true);
1603+ verifyItem(1, -158., 350., false);
1604+ verifyItem(2, 192, 350., false);
1605+ verifyItem(3, 542, 350., true);
1606+ QCOMPARE(lvwph->m_minYExtent, 162.5);
1607+ QCOMPARE(lvwph->m_clipItem->y(), 558.);
1608+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1609+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1610+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1611+ QCOMPARE(lvwph->contentY(), 558.);
1612+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1613+ }
1614+
1385private:
1615private:
1386 QQuickView *view;
1616 QQuickView *view;
1387 ListViewWithPageHeader *lvwph;
1617 ListViewWithPageHeader *lvwph;
1618+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1388 QQuickListModel *model;
1619 QQuickListModel *model;
1620+#else
1621+ QQmlListModel *model;
1622+#endif
1389 QQmlComponent *otherDelegate;
1623 QQmlComponent *otherDelegate;
1390};
1624};
1391
1625
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cpp+408−5
@@ -22,7 +22,11 @@
22#include <QtTestGui>
22#include <QtTestGui>
23#pragma GCC diagnostic push
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-pedantic"
24#pragma GCC diagnostic ignored "-pedantic"
25+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
25#include <private/qquicklistmodel_p.h>
26#include <private/qquicklistmodel_p.h>
27+#else
28+#include <private/qqmllistmodel_p.h>
29+#endif
26#include <private/qquickanimation_p.h>
30#include <private/qquickanimation_p.h>
27#include <private/qquickitem_p.h>
31#include <private/qquickitem_p.h>
28#pragma GCC diagnostic pop
32#pragma GCC diagnostic pop
@@ -41,6 +45,7 @@ private:
41 QCOMPARE(section(lvwph->m_visibleItems[visibleIndex]->m_sectionItem), sectionHeader);
45 QCOMPARE(section(lvwph->m_visibleItems[visibleIndex]->m_sectionItem), sectionHeader);
42 if (!sectionHeader.isNull()) {
46 if (!sectionHeader.isNull()) {
43 QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->m_sectionItem)->culled, sectionHeaderCulled);
47 QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->m_sectionItem)->culled, sectionHeaderCulled);
48+ QCOMPARE(sectionDelegateIndex(lvwph->m_visibleItems[visibleIndex]->m_sectionItem), lvwph->m_firstVisibleIndex + visibleIndex);
44 }
49 }
45 }
50 }
46
51
@@ -112,6 +117,11 @@ private:
112 return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("section")).toString() : QString();
117 return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("section")).toString() : QString();
113 }
118 }
114
119
120+ int sectionDelegateIndex(QQuickItem *item)
121+ {
122+ return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("delegateIndex")).toInt() : -1;
123+ }
124+
115private Q_SLOTS:
125private Q_SLOTS:
116
126
117 void initTestCase()
127 void initTestCase()
@@ -124,7 +134,11 @@ private Q_SLOTS:
124 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
134 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
125 view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test_section.qml"));
135 view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test_section.qml"));
126 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
136 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
137+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
127 model = view->rootObject()->findChild<QQuickListModel*>();
138 model = view->rootObject()->findChild<QQuickListModel*>();
139+#else
140+ model = view->rootObject()->findChild<QQmlListModel*>();
141+#endif
128 otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
142 otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
129 QVERIFY(lvwph);
143 QVERIFY(lvwph);
130 QVERIFY(model);
144 QVERIFY(model);
@@ -212,6 +226,7 @@ private Q_SLOTS:
212 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
226 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
213 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
227 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
214 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
228 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
229+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
215 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
230 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
216 }
231 }
217
232
@@ -233,6 +248,7 @@ private Q_SLOTS:
233 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
248 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
234 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
249 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
235 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
250 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
251+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
236 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
252 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
237 }
253 }
238
254
@@ -254,6 +270,7 @@ private Q_SLOTS:
254 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
270 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
255 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
271 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
256 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
272 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
273+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 0);
257 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
274 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
258
275
259 changeContentY(-30);
276 changeContentY(-30);
@@ -272,6 +289,7 @@ private Q_SLOTS:
272 QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
289 QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
273 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
290 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
274 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
291 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
292+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 0);
275 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
293 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
276 }
294 }
277
295
@@ -327,6 +345,7 @@ private Q_SLOTS:
327 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
345 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
328 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
346 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
329 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
347 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
348+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
330 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
349 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
331
350
332 lvwph->positionAtBeginning();
351 lvwph->positionAtBeginning();
@@ -352,6 +371,7 @@ private Q_SLOTS:
352 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
371 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
353 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
372 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
354 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
373 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
374+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
355 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
375 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
356
376
357 lvwph->positionAtBeginning();
377 lvwph->positionAtBeginning();
@@ -396,6 +416,7 @@ private Q_SLOTS:
396 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
416 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
397 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
417 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
398 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
418 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
419+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
399 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
420 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
400
421
401 model->setProperty(0, "size", 400);
422 model->setProperty(0, "size", 400);
@@ -415,6 +436,7 @@ private Q_SLOTS:
415 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
436 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
416 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
437 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
417 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
438 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
439+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
418 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
440 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
419
441
420 scrollToTop();
442 scrollToTop();
@@ -468,6 +490,7 @@ private Q_SLOTS:
468 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
490 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
469 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
491 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
470 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
492 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
493+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
471 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
494 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
472
495
473 model->setProperty(0, "size", 400);
496 model->setProperty(0, "size", 400);
@@ -487,6 +510,7 @@ private Q_SLOTS:
487 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
510 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
488 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
511 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
489 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
512 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
513+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
490 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
514 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
491
515
492 scrollToTop();
516 scrollToTop();
@@ -523,6 +547,7 @@ private Q_SLOTS:
523 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
547 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
524 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
548 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
525 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
549 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
550+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
526 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
551 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
527
552
528 changeContentY(-30);
553 changeContentY(-30);
@@ -540,6 +565,7 @@ private Q_SLOTS:
540 QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
565 QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
541 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
566 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
542 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
567 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
568+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
543 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
569 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
544
570
545 changeContentY(30);
571 changeContentY(30);
@@ -557,6 +583,7 @@ private Q_SLOTS:
557 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
583 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
558 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
584 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
559 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
585 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
586+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
560 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
587 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
561
588
562 changeContentY(-30);
589 changeContentY(-30);
@@ -574,6 +601,7 @@ private Q_SLOTS:
574 QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
601 QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
575 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
602 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
576 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
603 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
604+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
577 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
605 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
578 }
606 }
579
607
@@ -594,6 +622,7 @@ private Q_SLOTS:
594 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
622 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
595 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
623 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
596 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
624 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
625+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
597 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
626 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
598
627
599 lvwph->setDelegate(otherDelegate);
628 lvwph->setDelegate(otherDelegate);
@@ -652,6 +681,7 @@ private Q_SLOTS:
652 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
681 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
653 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
682 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
654 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
683 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
684+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
655 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
685 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
656
686
657 scrollToTop();
687 scrollToTop();
@@ -690,6 +720,7 @@ private Q_SLOTS:
690 QTRY_VERIFY(lvwph->isAtYEnd());
720 QTRY_VERIFY(lvwph->isAtYEnd());
691 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
721 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
692 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
722 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
723+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
693 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
724 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
694
725
695 scrollToTop();
726 scrollToTop();
@@ -726,6 +757,7 @@ private Q_SLOTS:
726 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
757 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
727 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
758 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
728 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
759 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
760+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 0);
729 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
761 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
730 }
762 }
731
763
@@ -810,6 +842,7 @@ private Q_SLOTS:
810 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
842 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
811 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
843 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
812 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
844 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
845+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
813 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
846 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
814
847
815 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
848 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
@@ -830,6 +863,7 @@ private Q_SLOTS:
830 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
863 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
831 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
864 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
832 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
865 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
866+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 4);
833 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
867 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
834
868
835 scrollToTop();
869 scrollToTop();
@@ -870,6 +904,7 @@ private Q_SLOTS:
870 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
904 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
871 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
905 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
872 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
906 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
907+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 0);
873 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
908 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
874
909
875 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 3), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
910 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 3), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
@@ -890,6 +925,7 @@ private Q_SLOTS:
890 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
925 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
891 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
926 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
892 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
927 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
928+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 0);
893 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
929 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
894 }
930 }
895
931
@@ -912,6 +948,7 @@ private Q_SLOTS:
912 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
948 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
913 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
949 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
914 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
950 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
951+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
915 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
952 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
916
953
917 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
954 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
@@ -932,6 +969,7 @@ private Q_SLOTS:
932 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
969 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
933 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
970 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
934 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
971 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
972+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 4);
935 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
973 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
936 }
974 }
937
975
@@ -954,6 +992,7 @@ private Q_SLOTS:
954 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
992 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
955 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
993 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
956 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
994 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
995+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
957 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
996 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
958
997
959 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
998 QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
@@ -974,6 +1013,7 @@ private Q_SLOTS:
974 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1013 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
975 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1014 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
976 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1015 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1016+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
977 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1017 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
978
1018
979 scrollToTop();
1019 scrollToTop();
@@ -1021,6 +1061,7 @@ private Q_SLOTS:
1021 QVERIFY(!lvwph->isAtYEnd());
1061 QVERIFY(!lvwph->isAtYEnd());
1022 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1062 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1023 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1063 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1064+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
1024 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1065 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1025
1066
1026 scrollToBottom();
1067 scrollToBottom();
@@ -1041,6 +1082,7 @@ private Q_SLOTS:
1041 QVERIFY(lvwph->isAtYEnd());
1082 QVERIFY(lvwph->isAtYEnd());
1042 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1083 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1043 QCOMPARE(section(lvwph->m_topSectionItem), QString("Lazy"));
1084 QCOMPARE(section(lvwph->m_topSectionItem), QString("Lazy"));
1085+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 5);
1044 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1086 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1045 }
1087 }
1046
1088
@@ -1094,6 +1136,7 @@ private Q_SLOTS:
1094 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1136 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1095 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1137 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1096 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1138 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1139+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 13);
1097 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1140 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1098
1141
1099 changeContentY(-1700);
1142 changeContentY(-1700);
@@ -1118,6 +1161,7 @@ private Q_SLOTS:
1118 QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1161 QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1119 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1162 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1120 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1163 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1164+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 4);
1121 QCOMPARE(lvwph->m_topSectionItem->y(), -23.);
1165 QCOMPARE(lvwph->m_topSectionItem->y(), -23.);
1122 }
1166 }
1123
1167
@@ -1179,6 +1223,7 @@ private Q_SLOTS:
1179 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1223 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1180 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1224 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1181 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1225 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1226+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
1182 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1227 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1183 }
1228 }
1184
1229
@@ -1202,6 +1247,7 @@ private Q_SLOTS:
1202 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1247 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1203 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1248 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1204 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1249 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1250+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
1205 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1251 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1206 }
1252 }
1207
1253
@@ -1224,6 +1270,7 @@ private Q_SLOTS:
1224 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1270 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1225 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1271 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1226 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1272 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1273+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
1227 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1274 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1228
1275
1229 QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 1), Q_ARG(QVariant, 1));
1276 QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 1), Q_ARG(QVariant, 1));
@@ -1243,6 +1290,7 @@ private Q_SLOTS:
1243 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1290 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1244 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1291 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1245 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1292 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1293+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
1246 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1294 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1247 }
1295 }
1248
1296
@@ -1265,6 +1313,7 @@ private Q_SLOTS:
1265 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1313 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1266 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1314 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1267 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1315 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1316+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
1268 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1317 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1269
1318
1270 QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 3), Q_ARG(QVariant, 1));
1319 QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 3), Q_ARG(QVariant, 1));
@@ -1284,6 +1333,7 @@ private Q_SLOTS:
1284 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1333 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1285 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1334 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1286 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1335 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1336+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
1287 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1337 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1288 }
1338 }
1289
1339
@@ -1363,6 +1413,7 @@ private Q_SLOTS:
1363 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1413 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1364 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1414 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1365 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1415 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1416+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 3);
1366 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1417 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1367
1418
1368 QMetaObject::invokeMethod(model, "moveItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 5), Q_ARG(QVariant, 1));
1419 QMetaObject::invokeMethod(model, "moveItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 5), Q_ARG(QVariant, 1));
@@ -1383,6 +1434,7 @@ private Q_SLOTS:
1383 QVERIFY(!lvwph->isAtYEnd());
1434 QVERIFY(!lvwph->isAtYEnd());
1384 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1435 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1385 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1436 QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1437+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
1386 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1438 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1387 }
1439 }
1388
1440
@@ -1406,6 +1458,7 @@ private Q_SLOTS:
1406 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1458 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1407 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1459 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1408 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1460 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1461+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
1409 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1462 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1410
1463
1411 model->setProperty(1, "size", 100);
1464 model->setProperty(1, "size", 100);
@@ -1426,6 +1479,7 @@ private Q_SLOTS:
1426 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1479 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1427 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1480 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1428 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1481 QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1482+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
1429 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1483 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1430 }
1484 }
1431
1485
@@ -1447,12 +1501,12 @@ private Q_SLOTS:
1447 QCOMPARE(lvwph->m_headerItem->y(), 0.);
1501 QCOMPARE(lvwph->m_headerItem->y(), 0.);
1448 QCOMPARE(lvwph->m_headerItem->height(), 50.);
1502 QCOMPARE(lvwph->m_headerItem->height(), 50.);
1449 QCOMPARE(lvwph->contentY(), 20.);
1503 QCOMPARE(lvwph->contentY(), 20.);
1450− QCOMPARE(lvwph->m_headerItemShownHeight, 0.);;
1504+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1451 QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1505 QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1452
1506
1453 lvwph->showHeader();
1507 lvwph->showHeader();
1454
1508
1455− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1509+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1456 QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1510 QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1457 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1511 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1458 verifyItem(0, -20., 190., false, "Agressive", true);
1512 verifyItem(0, -20., 190., false, "Agressive", true);
@@ -1467,6 +1521,7 @@ private Q_SLOTS:
1467 QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1521 QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1468 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1522 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1469 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
1523 QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
1524+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 0);
1470 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1525 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1471
1526
1472 scrollToTop();
1527 scrollToTop();
@@ -1502,14 +1557,15 @@ private Q_SLOTS:
1502 QCOMPARE(lvwph->m_headerItem->y(), 0.);
1557 QCOMPARE(lvwph->m_headerItem->y(), 0.);
1503 QCOMPARE(lvwph->m_headerItem->height(), 50.);
1558 QCOMPARE(lvwph->m_headerItem->height(), 50.);
1504 QCOMPARE(lvwph->contentY(), 375.);
1559 QCOMPARE(lvwph->contentY(), 375.);
1505− QCOMPARE(lvwph->m_headerItemShownHeight, 0.);;
1560+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1506 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1561 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1507 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1562 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1563+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
1508 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1564 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1509
1565
1510 lvwph->showHeader();
1566 lvwph->showHeader();
1511
1567
1512− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1568+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1513 QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1569 QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1514 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1570 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1515 verifyItem(0, -375., 190., true, "Agressive", true);
1571 verifyItem(0, -375., 190., true, "Agressive", true);
@@ -1525,6 +1581,7 @@ private Q_SLOTS:
1525 QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1581 QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1526 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1582 QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1527 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1583 QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1584+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
1528 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1585 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1529
1586
1530 scrollToTop();
1587 scrollToTop();
@@ -1550,7 +1607,7 @@ private Q_SLOTS:
1550
1607
1551 lvwph->showHeader();
1608 lvwph->showHeader();
1552
1609
1553− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1610+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1554 QTRY_VERIFY (lvwph->isAtYEnd());
1611 QTRY_VERIFY (lvwph->isAtYEnd());
1555 }
1612 }
1556
1613
@@ -1634,10 +1691,356 @@ private Q_SLOTS:
1634 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1691 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1635 }
1692 }
1636
1693
1694+ void testCullOnBottomEdge()
1695+ {
1696+ changeContentY(240);
1697+
1698+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1699+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1700+ verifyItem(0, -190., 190., true, "Agressive", true);
1701+ verifyItem(1, 0., 240., false, "Regular", false);
1702+ verifyItem(2, 240., 390., false, "Mild", false);
1703+ verifyItem(3, 630., 390., true, "Bold", true);
1704+ QCOMPARE(lvwph->m_minYExtent, 0.);
1705+ QCOMPARE(lvwph->m_clipItem->y(), 240.);
1706+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1707+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1708+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1709+ QCOMPARE(lvwph->contentY(), 240.);
1710+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1711+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1712+ }
1713+
1714+ void testSectionItemCullOnFirstSectionItemTopEdge()
1715+ {
1716+ changeContentY(50);
1717+
1718+ verifyItem(0, 0., 190., false, "Agressive", false);
1719+ verifyItem(1, 190., 240., false, "Regular", false);
1720+ verifyItem(2, 430., 390., false, "Mild", false);
1721+ QCOMPARE(lvwph->m_minYExtent, 0.);
1722+ QCOMPARE(lvwph->m_clipItem->y(), 50.);
1723+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1724+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1725+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1726+ QCOMPARE(lvwph->contentY(), 50.);
1727+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1728+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1729+ }
1730+
1731+ void testSectionItemCullOnSecondSectionItemTopEdge()
1732+ {
1733+ 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+
1736+ changeContentY(140);
1737+
1738+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1739+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1740+ verifyItem(0, -90., 90., true, "Agressive", true);
1741+ verifyItem(1, 0., 50., false, QString(), false);
1742+ verifyItem(2, 50., 150., false, QString(), false);
1743+ verifyItem(3, 200., 240., false, "Regular", false);
1744+ verifyItem(4, 440., 390., false, "Mild", false);
1745+ QCOMPARE(lvwph->m_minYExtent, 0.);
1746+ QCOMPARE(lvwph->m_clipItem->y(), 140.);
1747+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1748+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1749+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1750+ QCOMPARE(lvwph->contentY(), 140.);
1751+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1752+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1753+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
1754+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 0);
1755+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1756+ }
1757+
1758+ void testMaximizeVisibleArea()
1759+ {
1760+ bool res = lvwph->maximizeVisibleArea(2);
1761+ QVERIFY(res);
1762+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1763+
1764+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1765+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1766+ verifyItem(0, -278., 190., true, "Agressive", true);
1767+ verifyItem(1, -88., 240., false, "Regular", true);
1768+ verifyItem(2, 152, 390., false, "Mild", false);
1769+ verifyItem(3, 542, 390., true, "Bold", true);
1770+ QCOMPARE(lvwph->m_minYExtent, 0.);
1771+ QCOMPARE(lvwph->m_clipItem->y(), 328.);
1772+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1773+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1774+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1775+ QCOMPARE(lvwph->contentY(), 328.);
1776+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1777+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1778+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1779+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
1780+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1781+ }
1782+
1783+ void testMaximizeVisibleAreaVisibleItems()
1784+ {
1785+ bool res = lvwph->maximizeVisibleArea(0);
1786+ QVERIFY(res);
1787+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1788+
1789+ verifyInitialTopPosition();
1790+
1791+ res = lvwph->maximizeVisibleArea(1);
1792+ QVERIFY(res);
1793+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1794+
1795+ verifyInitialTopPosition();
1796+ }
1797+
1798+ void testMaximizeVisibleAreaInvalidIndexes()
1799+ {
1800+ bool res = lvwph->maximizeVisibleArea(-1);
1801+ QVERIFY(!res);
1802+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1803+
1804+ verifyInitialTopPosition();
1805+
1806+ res = lvwph->maximizeVisibleArea(1000);
1807+ QVERIFY(!res);
1808+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1809+
1810+ verifyInitialTopPosition();
1811+
1812+ res = lvwph->maximizeVisibleArea(3);
1813+ QVERIFY(!res);
1814+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1815+
1816+ verifyInitialTopPosition();
1817+ }
1818+
1819+ void testMaximizeVisibleAreaBigElement()
1820+ {
1821+ model->setProperty(2, "size", 4000);
1822+ verifyItem(2, 480, 4040., false, "Mild", false);
1823+
1824+ bool res = lvwph->maximizeVisibleArea(2);
1825+ QVERIFY(res);
1826+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1827+
1828+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1829+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1830+ verifyItem(0, -430., 190., true, "Agressive", true);
1831+ verifyItem(1, -240., 240., true, "Regular", true);
1832+ verifyItem(2, 0, 4040., false, "Mild", false);
1833+ QCOMPARE(lvwph->m_minYExtent, 0.);
1834+ QCOMPARE(lvwph->m_clipItem->y(), 480.);
1835+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1836+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1837+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1838+ QCOMPARE(lvwph->contentY(), 480.);
1839+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1840+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1841+ }
1842+
1843+ void testMaximizeVisibleAreaScrollDown()
1844+ {
1845+ changeContentY(350);
1846+ bool res = lvwph->maximizeVisibleArea(1);
1847+ QVERIFY(res);
1848+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1849+
1850+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1851+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1852+ verifyItem(0, -190., 190., true, "Agressive", true);
1853+ verifyItem(1, 0., 240., false, "Regular", false);
1854+ verifyItem(2, 240, 390., false, "Mild", false);
1855+ verifyItem(3, 630, 390., true, "Bold", true);
1856+ QCOMPARE(lvwph->m_minYExtent, 0.);
1857+ QCOMPARE(lvwph->m_clipItem->y(), 240.);
1858+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1859+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1860+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1861+ QCOMPARE(lvwph->contentY(), 240.);
1862+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1863+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1864+ }
1865+
1866+ void testMaximizeVisibleAreaScrollDownBigElement()
1867+ {
1868+ model->setProperty(1, "size", 1000);
1869+ changeContentY(1150);
1870+ bool res = lvwph->maximizeVisibleArea(1);
1871+ QVERIFY(res);
1872+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1873+
1874+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 2);
1875+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1876+ verifyItem(0, -498., 1040., false, "Regular", true);
1877+ verifyItem(1, 542., 390., true, "Mild", true);
1878+ QCOMPARE(lvwph->m_minYExtent, 1250/3.);
1879+ QCOMPARE(lvwph->m_clipItem->y(), 738.);
1880+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1881+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1882+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1883+ QCOMPARE(lvwph->contentY(), 738.);
1884+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1885+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1886+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1887+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
1888+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1889+ }
1890+
1891+ void testMaximizeVisibleAreaBigElementInTheMiddle()
1892+ {
1893+ model->setProperty(1, "size", 1000);
1894+ changeContentY(650);
1895+
1896+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 2);
1897+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1898+ verifyItem(0, -410., 1040., false, "Regular", true);
1899+ verifyItem(1, 630., 390., true, "Mild", true);
1900+ QCOMPARE(lvwph->m_minYExtent, 525.);
1901+ QCOMPARE(lvwph->m_clipItem->y(), 650.);
1902+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1903+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1904+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1905+ QCOMPARE(lvwph->contentY(), 650.);
1906+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1907+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1908+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1909+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
1910+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1911+
1912+ bool res = lvwph->maximizeVisibleArea(1);
1913+ QVERIFY(res);
1914+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1915+
1916+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 2);
1917+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1918+ verifyItem(0, -410., 1040., false, "Regular", true);
1919+ verifyItem(1, 630., 390., true, "Mild", true);
1920+ QCOMPARE(lvwph->m_minYExtent, 525.);
1921+ QCOMPARE(lvwph->m_clipItem->y(), 650.);
1922+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1923+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1924+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1925+ QCOMPARE(lvwph->contentY(), 650.);
1926+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1927+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1928+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1929+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 1);
1930+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1931+ }
1932+
1933+ void testMaximizeVisibleAreaTopWithHalfPageHeader()
1934+ {
1935+ changeContentY(430);
1936+ changeContentY(-30);
1937+
1938+ bool res = lvwph->maximizeVisibleArea(1);
1939+ QVERIFY(res);
1940+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1941+
1942+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1943+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1944+ verifyItem(0, -190., 190., true, "Agressive", true);
1945+ verifyItem(1, 0., 240., false, "Regular", false);
1946+ verifyItem(2, 240, 390., false, "Mild", false);
1947+ verifyItem(3, 630, 390., true, "Bold", true);
1948+ QCOMPARE(lvwph->m_minYExtent, 0.);
1949+ QCOMPARE(lvwph->m_clipItem->y(), 240.);
1950+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1951+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1952+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1953+ QCOMPARE(lvwph->contentY(), 240.);
1954+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1955+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1956+ }
1957+
1958+ void testMaximizeVisibleAreaBottomWithHalfPageHeader()
1959+ {
1960+ changeContentY(430);
1961+ changeContentY(-30);
1962+
1963+ bool res = lvwph->maximizeVisibleArea(3);
1964+ QVERIFY(res);
1965+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1966+
1967+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1968+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1969+ verifyItem(0, -478., 240., true, "Regular", true);
1970+ verifyItem(1, -238., 390., false, "Mild", true);
1971+ verifyItem(2, 152, 390., false, "Bold", false);
1972+ verifyItem(3, 542, 350., true, QString(), true);
1973+ QCOMPARE(lvwph->m_minYExtent, 152.5);
1974+ QCOMPARE(lvwph->m_clipItem->y(), 718.);
1975+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1976+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1977+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1978+ QCOMPARE(lvwph->contentY(), 718.);
1979+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1980+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1981+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1982+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 2);
1983+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1984+ }
1985+
1986+ void testMaximizeVisibleAreaTopSecondSectionItemStickySection()
1987+ {
1988+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
1989+ changeContentY(250);
1990+ bool res = lvwph->maximizeVisibleArea(1);
1991+ QVERIFY(res);
1992+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1993+
1994+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1995+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1996+ verifyItem(0, -100., 140., false, "Agressive", true);
1997+ verifyItem(1, 40., 150., false, QString(), true);
1998+ verifyItem(2, 190, 240., false, "Regular", false);
1999+ verifyItem(3, 430, 390., false, "Mild", false);
2000+ QCOMPARE(lvwph->m_minYExtent, 0.);
2001+ QCOMPARE(lvwph->m_clipItem->y(), 150.);
2002+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2003+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
2004+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
2005+ QCOMPARE(lvwph->contentY(), 150.);
2006+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2007+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2008+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
2009+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 0);
2010+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
2011+
2012+ changeContentY(20);
2013+ res = lvwph->maximizeVisibleArea(1);
2014+ QVERIFY(res);
2015+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
2016+
2017+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
2018+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
2019+ verifyItem(0, -100., 140., false, "Agressive", true);
2020+ verifyItem(1, 40., 150., false, QString(), true);
2021+ verifyItem(2, 190, 240., false, "Regular", false);
2022+ verifyItem(3, 430, 390., false, "Mild", false);
2023+ QCOMPARE(lvwph->m_minYExtent, 0.);
2024+ QCOMPARE(lvwph->m_clipItem->y(), 150.);
2025+ QCOMPARE(lvwph->m_clipItem->clip(), false);
2026+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
2027+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
2028+ QCOMPARE(lvwph->contentY(), 150.);
2029+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
2030+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
2031+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
2032+ QCOMPARE(sectionDelegateIndex(lvwph->m_topSectionItem), 0);
2033+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
2034+ }
2035+
1637private:
2036private:
1638 QQuickView *view;
2037 QQuickView *view;
1639 ListViewWithPageHeader *lvwph;
2038 ListViewWithPageHeader *lvwph;
2039+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1640 QQuickListModel *model;
2040 QQuickListModel *model;
2041+#else
2042+ QQmlListModel *model;
2043+#endif
1641 QQmlComponent *otherDelegate;
2044 QQmlComponent *otherDelegate;
1642};
2045};
1643
2046
tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp+1−1
@@ -134,5 +134,5 @@ private Q_SLOTS:
134 }
134 }
135};
135};
136
136
137−QTEST_MAIN(IndicatorsManagerTest)
137+QTEST_GUILESS_MAIN(IndicatorsManagerTest)
138#include "indicatorsmanagertest.moc"
138#include "indicatorsmanagertest.moc"
tests/plugins/Unity/Indicators/indicatorsmodeltest.cpp+1−1
@@ -97,6 +97,6 @@ private Q_SLOTS:
97 }
97 }
98};
98};
99
99
100−QTEST_MAIN(IndicatorsModelTest)
100+QTEST_GUILESS_MAIN(IndicatorsModelTest)
101
101
102#include "indicatorsmodeltest.moc"
102#include "indicatorsmodeltest.moc"
tests/plugins/Unity/Indicators/menucontentactivatortest.cpp+1−1
@@ -299,5 +299,5 @@ private:
299 QList<int> m_deltas;
299 QList<int> m_deltas;
300};
300};
301
301
302−QTEST_MAIN(MenuConentActivatorTest)
302+QTEST_GUILESS_MAIN(MenuConentActivatorTest)
303#include "menucontentactivatortest.moc"
303#include "menucontentactivatortest.moc"
tests/plugins/Utils/qlimitproxymodeltest.cpp+1−1
@@ -481,6 +481,6 @@ private Q_SLOTS:
481 }
481 }
482};
482};
483
483
484−QTEST_MAIN(QLimitProxyModelTest)
484+QTEST_GUILESS_MAIN(QLimitProxyModelTest)
485
485
486#include "qlimitproxymodeltest.moc"
486#include "qlimitproxymodeltest.moc"
tests/plugins/Utils/qsortfilterproxymodeltest.cpp+1−1
@@ -285,6 +285,6 @@ private Q_SLOTS:
285 }
285 }
286};
286};
287
287
288−QTEST_MAIN(QSortFilterProxyModelTest)
288+QTEST_GUILESS_MAIN(QSortFilterProxyModelTest)
289
289
290#include "qsortfilterproxymodeltest.moc"
290#include "qsortfilterproxymodeltest.moc"
tests/qmltests/CMakeLists.txt+3
@@ -25,6 +25,9 @@ add_qml_test(utils/Unity/Test UnityTest)
25set(qmltest_DEFAULT_TARGETS qmluitests)
25set(qmltest_DEFAULT_TARGETS qmluitests)
26set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
26set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
27set(qmltest_DEFAULT_PROPERTIES "")
27set(qmltest_DEFAULT_PROPERTIES "")
28+
29+add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
30+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
28add_manual_qml_test(Components DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
31add_manual_qml_test(Components DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
29add_qml_test(Components DraggingArea)
32add_qml_test(Components DraggingArea)
30add_qml_test(Components FilterGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
33add_qml_test(Components FilterGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
tests/qmltests/Components/tst_Stage.qml+1
@@ -161,6 +161,7 @@ Rectangle {
161 applicationManager: fakeAppManager
161 applicationManager: fakeAppManager
162 rightEdgeDraggingAreaWidth: units.gu(2)
162 rightEdgeDraggingAreaWidth: units.gu(2)
163 fullyShown: true
163 fullyShown: true
164+ fullyHidden: false
164 newApplicationScreenshot: FakeApplicationScreenshot {
165 newApplicationScreenshot: FakeApplicationScreenshot {
165 id: newAppScreenshot
166 id: newAppScreenshot
166 parent: stage
167 parent: stage
tests/qmltests/Dash/tst_Dash.qml+4−4
@@ -38,8 +38,8 @@ Item {
38 scopeDelegateMapping: {
38 scopeDelegateMapping: {
39 "MockScope1": "../tests/qmltests/Dash/qml/fake_scopeView1.qml",
39 "MockScope1": "../tests/qmltests/Dash/qml/fake_scopeView1.qml",
40 "MockScope2": "../tests/qmltests/Dash/qml/fake_scopeView2.qml",
40 "MockScope2": "../tests/qmltests/Dash/qml/fake_scopeView2.qml",
41− "MockScope3": "../tests/qmltests/Dash/qml/fake_scopeView3.qml",
41+ "home.scope": "../tests/qmltests/Dash/qml/fake_scopeView3.qml",
42− "MockScope4": "../tests/qmltests/Dash/qml/fake_scopeView4.qml"
42+ "applications.scope": "../tests/qmltests/Dash/qml/fake_scopeView4.qml"
43 }
43 }
44 genericScope: "../tests/qmltests/Dash/qml/fake_generic_scopeView.qml"
44 genericScope: "../tests/qmltests/Dash/qml/fake_generic_scopeView.qml"
45 }
45 }
@@ -69,8 +69,8 @@ Item {
69 return [
69 return [
70 { tag: "MockScope1", visualIndex: 0, shouldBeVisible: true },
70 { tag: "MockScope1", visualIndex: 0, shouldBeVisible: true },
71 { tag: "MockScope2", visualIndex: -1, shouldBeVisible: false },
71 { tag: "MockScope2", visualIndex: -1, shouldBeVisible: false },
72− { tag: "MockScope3", visualIndex: 1, shouldBeVisible: true },
72+ { tag: "home.scope", visualIndex: 1, shouldBeVisible: true },
73− { tag: "MockScope4", visualIndex: 2, shouldBeVisible: true },
73+ { tag: "applications.scope", visualIndex: 2, shouldBeVisible: true },
74 { tag: "MockScope5", visualIndex: 3, shouldBeVisible: true },
74 { tag: "MockScope5", visualIndex: 3, shouldBeVisible: true },
75 ]
75 ]
76 }
76 }
tests/qmltests/Dash/tst_DashContent.qml+12−12
@@ -31,8 +31,8 @@ Item {
31 property var scopeStatus: {
31 property var scopeStatus: {
32 'MockScope1': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
32 'MockScope1': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
33 'MockScope2': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
33 'MockScope2': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
34− 'MockScope3': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
34+ 'home.scope': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
35− 'MockScope4': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
35+ 'applications.scope': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
36 'MockScope5': { 'movementStarted': 0, 'positionedAtBeginning': 0 }
36 'MockScope5': { 'movementStarted': 0, 'positionedAtBeginning': 0 }
37 }
37 }
38
38
@@ -55,8 +55,8 @@ Item {
55 scopeDelegateMapping: {
55 scopeDelegateMapping: {
56 "MockScope1": "../tests/qmltests/Dash/qml/fake_scopeView1.qml",
56 "MockScope1": "../tests/qmltests/Dash/qml/fake_scopeView1.qml",
57 "MockScope2": "../tests/qmltests/Dash/qml/fake_scopeView2.qml",
57 "MockScope2": "../tests/qmltests/Dash/qml/fake_scopeView2.qml",
58− "MockScope3": "../tests/qmltests/Dash/qml/fake_scopeView3.qml",
58+ "home.scope": "../tests/qmltests/Dash/qml/fake_scopeView3.qml",
59− "MockScope4": "../tests/qmltests/Dash/qml/fake_scopeView4.qml"
59+ "applications.scope": "../tests/qmltests/Dash/qml/fake_scopeView4.qml"
60 }
60 }
61 genericScope: "../tests/qmltests/Dash/qml/fake_generic_scopeView.qml"
61 genericScope: "../tests/qmltests/Dash/qml/fake_generic_scopeView.qml"
62 }
62 }
@@ -68,11 +68,11 @@ Item {
68 scopeStatus["MockScope2"].movementStarted = 0;
68 scopeStatus["MockScope2"].movementStarted = 0;
69 scopeStatus["MockScope2"].positionedAtBeginning = 0;
69 scopeStatus["MockScope2"].positionedAtBeginning = 0;
70
70
71− scopeStatus["MockScope3"].movementStarted = 0;
71+ scopeStatus["home.scope"].movementStarted = 0;
72− scopeStatus["MockScope3"].positionedAtBeginning = 0;
72+ scopeStatus["home.scope"].positionedAtBeginning = 0;
73
73
74− scopeStatus["MockScope4"].movementStarted = 0;
74+ scopeStatus["applications.scope"].movementStarted = 0;
75− scopeStatus["MockScope4"].positionedAtBeginning = 0;
75+ scopeStatus["applications.scope"].positionedAtBeginning = 0;
76
76
77 scopeStatus["MockScope5"].movementStarted = 0;
77 scopeStatus["MockScope5"].movementStarted = 0;
78 scopeStatus["MockScope5"].positionedAtBeginning = 0;
78 scopeStatus["MockScope5"].positionedAtBeginning = 0;
@@ -127,8 +127,8 @@ Item {
127 compare(movementStartedSpy.count, 1, "DashContent should have emitted movementStarted signal when content list did.");
127 compare(movementStartedSpy.count, 1, "DashContent should have emitted movementStarted signal when content list did.");
128 compare(scopeStatus["MockScope1"].movementStarted, 1, "MockScope1 should have emitted movementStarted signal when content list did.");
128 compare(scopeStatus["MockScope1"].movementStarted, 1, "MockScope1 should have emitted movementStarted signal when content list did.");
129 compare(scopeStatus["MockScope2"].movementStarted, 1, "MockScope2 should have emitted movementStarted signal when content list did.");
129 compare(scopeStatus["MockScope2"].movementStarted, 1, "MockScope2 should have emitted movementStarted signal when content list did.");
130− compare(scopeStatus["MockScope3"].movementStarted, 1, "MockScope3 should have emitted movementStarted signal when content list did.");
130+ compare(scopeStatus["home.scope"].movementStarted, 1, "home.scope should have emitted movementStarted signal when content list did.");
131− compare(scopeStatus["MockScope4"].movementStarted, 1, "MockScope4 should have emitted movementStarted signal when content list did.");
131+ compare(scopeStatus["applications.scope"].movementStarted, 1, "applications.scope should have emitted movementStarted signal when content list did.");
132 compare(scopeStatus["MockScope5"].movementStarted, 1, "MockScope5 should have emitted movementStarted signal when content list did.");
132 compare(scopeStatus["MockScope5"].movementStarted, 1, "MockScope5 should have emitted movementStarted signal when content list did.");
133 }
133 }
134
134
@@ -140,8 +140,8 @@ Item {
140 dashContent.positionedAtBeginning();
140 dashContent.positionedAtBeginning();
141 compare(scopeStatus["MockScope1"].positionedAtBeginning, 1, "MockScope1 should have emitted positionedAtBeginning signal when DashContent did.");
141 compare(scopeStatus["MockScope1"].positionedAtBeginning, 1, "MockScope1 should have emitted positionedAtBeginning signal when DashContent did.");
142 compare(scopeStatus["MockScope2"].positionedAtBeginning, 1, "MockScope2 should have emitted positionedAtBeginning signal when DashContent did.");
142 compare(scopeStatus["MockScope2"].positionedAtBeginning, 1, "MockScope2 should have emitted positionedAtBeginning signal when DashContent did.");
143− compare(scopeStatus["MockScope3"].positionedAtBeginning, 1, "MockScope3 should have emitted positionedAtBeginning signal when DashContent did.");
143+ compare(scopeStatus["home.scope"].positionedAtBeginning, 1, "home.scope should have emitted positionedAtBeginning signal when DashContent did.");
144− compare(scopeStatus["MockScope4"].positionedAtBeginning, 1, "MockScope4 should have emitted positionedAtBeginning signal when DashContent did.");
144+ compare(scopeStatus["applications.scope"].positionedAtBeginning, 1, "applications.scope should have emitted positionedAtBeginning signal when DashContent did.");
145 compare(scopeStatus["MockScope5"].positionedAtBeginning, 1, "MockScope5 should have emitted positionedAtBeginning signal when DashContent did.");
145 compare(scopeStatus["MockScope5"].positionedAtBeginning, 1, "MockScope5 should have emitted positionedAtBeginning signal when DashContent did.");
146 }
146 }
147
147
tests/qmltests/Dash/tst_FilterGrids.qml+1−1
@@ -118,7 +118,7 @@ Rectangle {
118 gridLoader.source = "../../../Dash/" + data.component;
118 gridLoader.source = "../../../Dash/" + data.component;
119
119
120 // Wait until the FilterGrid is loaded by the loader
120 // Wait until the FilterGrid is loaded by the loader
121− tryCompare(gridLoader, "status", Loader.Ready, "Loader couldn't load " + data.component);
121+ tryCompare(gridLoader, "status", Loader.Ready);
122
122
123 // Wait until the GridView inside the model has finished rendering
123 // Wait until the GridView inside the model has finished rendering
124 var gridView = findChild(gridLoader, "responsiveGridViewGrid");
124 var gridView = findChild(gridLoader, "responsiveGridViewGrid");
tests/qmltests/Greeter/tst_Lockscreen.qml+1
@@ -186,6 +186,7 @@ Rectangle {
186 function test_unlock(data) {
186 function test_unlock(data) {
187 unlockedCheckBox.checked = false
187 unlockedCheckBox.checked = false
188 LightDM.Greeter.authenticate(data.username)
188 LightDM.Greeter.authenticate(data.username)
189+ waitForRendering(lockscreen)
189
190
190 var inputField = findChild(lockscreen, "pinentryField")
191 var inputField = findChild(lockscreen, "pinentryField")
191 if (data.alphanumeric) {
192 if (data.alphanumeric) {
tests/qmltests/Panel/tst_IndicatorItem.qml+10−16
@@ -34,34 +34,28 @@ Rectangle {
34 UT.UnityTestCase {
34 UT.UnityTestCase {
35 name: "IndicatorItem"
35 name: "IndicatorItem"
36
36
37− function init_test() {
38− }
39−
40 function test_dimmed() {
37 function test_dimmed() {
41− init_test()
42−
43− indicatorItem.dimmed = true
38+ indicatorItem.dimmed = false;
44− compare(indicatorItem.opacity > 0, true, "IndicatorItem opacity should not be 0")
39+ tryCompareFunction(function(){return indicatorItem.opacity}, 1.0);
40+ indicatorItem.dimmed = true;
45− compare(indicatorItem.opacity < 1, true, "IndicatorItem opacity should not be 1")
41+ tryCompareFunction(function(){return indicatorItem.opacity < 1.0}, true);
46 }
42 }
47
43
48 function test_highlight() {
44 function test_highlight() {
49− var itemHighlight = findChild(indicatorItem, "highlight")
45+ var itemHighlight = findChild(indicatorItem, "highlight");
50− verify(itemHighlight != undefined)
46+ verify(itemHighlight != undefined);
51
47
52 indicatorItem.highlighted = true;
48 indicatorItem.highlighted = true;
53− compare(itemHighlight.visible, true, "Indicator should be highlighted")
49+ compare(itemHighlight.visible, true, "Indicator should be highlighted");
54
50
55 indicatorItem.highlighted = false;
51 indicatorItem.highlighted = false;
56− compare(itemHighlight.visible, false, "Indicator should not be highlighted")
52+ compare(itemHighlight.visible, false, "Indicator should not be highlighted");
57 }
53 }
58
54
59 function test_empty() {
55 function test_empty() {
60− init_test()
61−
62− compare(indicatorItem.visible, false, "IndicatorItem should not be visible.")
56+ compare(indicatorItem.visible, false, "IndicatorItem should not be visible.");
63 indicatorItem.widgetSource = "qrc:/tests/indciators/qml/fake_menu_widget1.qml";
57 indicatorItem.widgetSource = "qrc:/tests/indciators/qml/fake_menu_widget1.qml";
64− tryCompare(indicatorItem, "visible", true)
58+ tryCompare(indicatorItem, "visible", true);
65 }
59 }
66 }
60 }
67}
61}
tests/qmltests/Panel/tst_IndicatorRow.qml+21−21
@@ -61,13 +61,13 @@ Item {
61
61
62 function test_set_current_item() {
62 function test_set_current_item() {
63 init_test();
63 init_test();
64− indicatorRow.setItem(0);
64+ indicatorRow.setCurrentItem(0);
65 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu1", "Incorrect item at position 0");
65 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu1", "Incorrect item at position 0");
66
66
67− indicatorRow.setItem(1);
67+ indicatorRow.setCurrentItem(1);
68 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu2", "Incorrect item at position 1");
68 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu2", "Incorrect item at position 1");
69
69
70− indicatorRow.setItem(2);
70+ indicatorRow.setCurrentItem(2);
71 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu3", "Incorrect item at position 2");
71 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu3", "Incorrect item at position 2");
72 }
72 }
73 }
73 }
@@ -83,13 +83,13 @@ Item {
83 function test_current_item_commit() {
83 function test_current_item_commit() {
84 init_test();
84 init_test();
85
85
86− indicatorRow.setItem(1);
86+ indicatorRow.setCurrentItem(1);
87 indicatorRow.state = "commit";
87 indicatorRow.state = "commit";
88− tryCompare(get_indicator_item_at(0), "y", -indicatorRow.height);
88+ tryCompare(get_indicator_item_at(0), "opacity", 0.0);
89− tryCompare(get_indicator_item_at(1), "y", 0);
89+ tryCompare(get_indicator_item_at(1), "opacity", 1.0);
90− tryCompare(get_indicator_item_at(2), "y", -indicatorRow.height);
90+ tryCompare(get_indicator_item_at(2), "opacity", 0.0);
91− tryCompare(get_indicator_item_at(3), "y", -indicatorRow.height);
91+ tryCompare(get_indicator_item_at(3), "opacity", 0.0);
92− tryCompare(get_indicator_item_at(4), "y", -indicatorRow.height);
92+ tryCompare(get_indicator_item_at(4), "opacity", 0.0);
93
93
94 }
94 }
95 }
95 }
@@ -106,7 +106,7 @@ Item {
106 init_test();
106 init_test();
107
107
108 indicatorRow.state = "initial";
108 indicatorRow.state = "initial";
109− indicatorRow.setItem(0);
109+ indicatorRow.setCurrentItem(0);
110
110
111 compare(indicatorRow.currentItem.highlighted, false, "Indicator should not highlight when in initial state");
111 compare(indicatorRow.currentItem.highlighted, false, "Indicator should not highlight when in initial state");
112 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in initial state");
112 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in initial state");
@@ -119,9 +119,9 @@ Item {
119 init_test();
119 init_test();
120
120
121 indicatorRow.state = "hint";
121 indicatorRow.state = "hint";
122− indicatorRow.setItem(0);
122+ indicatorRow.setCurrentItem(0);
123
123
124− compare(indicatorRow.currentItem.highlighted, false, "Indicator should not highlight when in hint state");
124+ compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in hint state");
125 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in hint state");
125 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in hint state");
126 compare(get_indicator_item_at(2).highlighted, false, "Other indicators should not highlight when in hint state");
126 compare(get_indicator_item_at(2).highlighted, false, "Other indicators should not highlight when in hint state");
127 compare(get_indicator_item_at(3).highlighted, false, "Other indicators should not highlight when in hint state");
127 compare(get_indicator_item_at(3).highlighted, false, "Other indicators should not highlight when in hint state");
@@ -132,7 +132,7 @@ Item {
132 init_test();
132 init_test();
133
133
134 indicatorRow.state = "reveal";
134 indicatorRow.state = "reveal";
135− indicatorRow.setItem(0);
135+ indicatorRow.setCurrentItem(0);
136
136
137 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in reveal state");
137 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in reveal state");
138 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in commit state");
138 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in commit state");
@@ -145,7 +145,7 @@ Item {
145 init_test();
145 init_test();
146
146
147 indicatorRow.state = "commit";
147 indicatorRow.state = "commit";
148− indicatorRow.setItem(0);
148+ indicatorRow.setCurrentItem(0);
149
149
150 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in commit state");
150 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in commit state");
151 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in commit state");
151 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in commit state");
@@ -158,7 +158,7 @@ Item {
158 init_test();
158 init_test();
159
159
160 indicatorRow.state = "locked";
160 indicatorRow.state = "locked";
161− indicatorRow.setItem(0);
161+ indicatorRow.setCurrentItem(0);
162
162
163 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in locked state");
163 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in locked state");
164 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in locked state");
164 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in locked state");
@@ -180,7 +180,7 @@ Item {
180 init_test();
180 init_test();
181
181
182 indicatorRow.state = "initial";
182 indicatorRow.state = "initial";
183− indicatorRow.setItem(0);
183+ indicatorRow.setCurrentItem(0);
184
184
185 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in intiial state");
185 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in intiial state");
186 compare(get_indicator_item_at(1).dimmed, false, "Other indicators should not dim when in initial state");
186 compare(get_indicator_item_at(1).dimmed, false, "Other indicators should not dim when in initial state");
@@ -193,9 +193,9 @@ Item {
193 init_test();
193 init_test();
194
194
195 indicatorRow.state = "hint";
195 indicatorRow.state = "hint";
196− indicatorRow.setItem(0);
196+ indicatorRow.setCurrentItem(0);
197
197
198− compare(get_indicator_item_at(0).dimmed, true, "Current indicator should dim when in hint state");
198+ compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in hint state");
199 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in hint state");
199 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in hint state");
200 compare(get_indicator_item_at(2).dimmed, true, "Other indicators should dim when in hint state");
200 compare(get_indicator_item_at(2).dimmed, true, "Other indicators should dim when in hint state");
201 compare(get_indicator_item_at(3).dimmed, true, "Other indicators should dim when in hint state");
201 compare(get_indicator_item_at(3).dimmed, true, "Other indicators should dim when in hint state");
@@ -206,7 +206,7 @@ Item {
206 init_test();
206 init_test();
207
207
208 indicatorRow.state = "reveal";
208 indicatorRow.state = "reveal";
209− indicatorRow.setItem(0);
209+ indicatorRow.setCurrentItem(0);
210
210
211 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in reveal state");
211 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in reveal state");
212 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in reveal state");
212 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in reveal state");
@@ -219,7 +219,7 @@ Item {
219 init_test();
219 init_test();
220
220
221 indicatorRow.state = "commit";
221 indicatorRow.state = "commit";
222− indicatorRow.setItem(0);
222+ indicatorRow.setCurrentItem(0);
223
223
224 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in commit state");
224 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in commit state");
225 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in commit state");
225 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in commit state");
@@ -232,7 +232,7 @@ Item {
232 init_test();
232 init_test();
233
233
234 indicatorRow.state = "locked";
234 indicatorRow.state = "locked";
235− indicatorRow.setItem(0);
235+ indicatorRow.setCurrentItem(0);
236
236
237 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in locked state");
237 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in locked state");
238 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in locked state");
238 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in locked state");
tests/qmltests/Panel/tst_MenuContent.qml+4−4
@@ -77,15 +77,15 @@ Item {
77
77
78 function activate_next_content()
78 function activate_next_content()
79 {
79 {
80− if (menuContent.currentIndex == -1)
80+ if (menuContent.currentMenuIndex == -1)
81 activate_content(0);
81 activate_content(0);
82 else
82 else
83− activate_content((menuContent.currentIndex + 1) % indicatorsModel.count)
83+ activate_content((menuContent.currentMenuIndex + 1) % indicatorsModel.count)
84 }
84 }
85
85
86 function activate_content(index)
86 function activate_content(index)
87 {
87 {
88− menuContent.currentIndex = index
88+ menuContent.currentMenuIndex = index
89 }
89 }
90
90
91 function get_test_menu_objecName(index) {
91 function get_test_menu_objecName(index) {
@@ -197,7 +197,7 @@ Item {
197
197
198 for (var i = 0; i < 100; i++) {
198 for (var i = 0; i < 100; i++) {
199 activate_content(i % menu_count);
199 activate_content(i % menu_count);
200− compare(menuContent.currentIndex, i%menu_count);
200+ compare(menuContent.currentMenuIndex, i%menu_count);
201 }
201 }
202 wait(100);
202 wait(100);
203 }
203 }
tests/qmltests/Panel/tst_Panel.qml+83−43
@@ -30,11 +30,11 @@ Item {
30 width: units.gu(40)
30 width: units.gu(40)
31 height: units.gu(80)
31 height: units.gu(80)
32
32
33− property bool search_clicked: false
33+ property bool searchClicked: false
34
34
35 Connections {
35 Connections {
36 target: panel
36 target: panel
37− onSearchClicked: search_clicked = true
37+ onSearchClicked: searchClicked = true
38 }
38 }
39
39
40 Panel {
40 Panel {
@@ -54,27 +54,26 @@ Item {
54
54
55
55
56 function init() {
56 function init() {
57− search_clicked = false;
57+ searchClicked = false;
58 panel.indicators.hide();
58 panel.indicators.hide();
59 tryCompare(panel.indicators.hideAnimation, "running", false);
59 tryCompare(panel.indicators.hideAnimation, "running", false);
60 tryCompare(panel.indicators, "state", "initial");
60 tryCompare(panel.indicators, "state", "initial");
61 }
61 }
62
62
63 function get_indicator_item(index) {
63 function get_indicator_item(index) {
64− var row_repeater = findChild(panel.indicators, "rowRepeater");
64+ var rowRepeater = findChild(panel.indicators, "rowRepeater");
65− verify(row_repeater != undefined);
65+ verify(rowRepeater != undefined);
66− return row_repeater.itemAt(index);
66+ return rowRepeater.itemAt(index);
67 }
67 }
68
68
69 function get_indicator_item_position(index) {
69 function get_indicator_item_position(index) {
70+ var indicatorRow = findChild(panel.indicators, "indicatorRow");
71+ verify(indicatorRow != undefined);
70
72
71− var indicator_row = findChild(panel.indicators, "indicatorRow");
72− verify(indicator_row != undefined);
73−
74− var indicator_item = get_indicator_item(index);
73+ var indicatorItem = get_indicator_item(index);
75− verify(indicator_item != undefined);
74+ verify(indicatorItem != undefined);
76
75
77− return panel.mapFromItem(indicator_item, indicator_item.width/2, indicator_item.height/2);
76+ return panel.mapFromItem(indicatorItem, indicatorItem.width/2, indicatorItem.height/2);
78 }
77 }
79
78
80 // Pressing on the indicator panel should activate the indicator hints
79 // Pressing on the indicator panel should activate the indicator hints
@@ -85,9 +84,9 @@ Item {
85 // (switches between normal and fullscreen modes are animated)
84 // (switches between normal and fullscreen modes are animated)
86 tryCompare(panel.indicators, "y", 0);
85 tryCompare(panel.indicators, "y", 0);
87
86
88− var indicator_item_coord = get_indicator_item_position(0);
87+ var indicatorItemCoord = get_indicator_item_position(0);
89
88
90− touchPress(panel, indicator_item_coord.x, panel.panelHeight / 2);
89+ touchPress(panel, indicatorItemCoord.x, panel.panelHeight / 2);
91
90
92 // hint animation should be run, meaning that indicators will move downwards
91 // hint animation should be run, meaning that indicators will move downwards
93 // by hintValue pixels without any drag taking place
92 // by hintValue pixels without any drag taking place
@@ -96,7 +95,7 @@ Item {
96 tryCompare(panel.indicators, "partiallyOpened", true);
95 tryCompare(panel.indicators, "partiallyOpened", true);
97 tryCompare(panel.indicators, "fullyOpened", false);
96 tryCompare(panel.indicators, "fullyOpened", false);
98
97
99− touchRelease(panel, indicator_item_coord.x, panel.panelHeight/2);
98+ touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
100 }
99 }
101
100
102 // Pressing on the top edge of the screen should have no effect if the panel
101 // Pressing on the top edge of the screen should have no effect if the panel
@@ -107,9 +106,9 @@ Item {
107 // (switches between normal and fullscreen modes are animated)
106 // (switches between normal and fullscreen modes are animated)
108 tryCompare(panel.indicators, "y", -panel.panelHeight);
107 tryCompare(panel.indicators, "y", -panel.panelHeight);
109
108
110− var indicator_item_coord = get_indicator_item_position(0);
109+ var indicatorItemCoord = get_indicator_item_position(0);
111
110
112− touchPress(panel, indicator_item_coord.x, panel.panelHeight / 2);
111+ touchPress(panel, indicatorItemCoord.x, panel.panelHeight / 2);
113
112
114 // Give some time for a hint animation to change things, if any
113 // Give some time for a hint animation to change things, if any
115 wait(500);
114 wait(500);
@@ -126,7 +125,7 @@ Item {
126 compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
125 compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
127 " opened when panel is pressed in fullscreenmode");
126 " opened when panel is pressed in fullscreenmode");
128
127
129− touchRelease(panel, indicator_item_coord.x, panel.panelHeight/2);
128+ touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
130 }
129 }
131
130
132 function test_drag_show_data() { return get_window_data(); }
131 function test_drag_show_data() { return get_window_data(); }
@@ -137,14 +136,14 @@ Item {
137 function test_drag_show(data) {
136 function test_drag_show(data) {
138 panel.fullscreenMode = data.fullscreenFlag;
137 panel.fullscreenMode = data.fullscreenFlag;
139
138
140− var indicator_row = findChild(panel.indicators, "indicatorRow");
139+ var indicatorRow = findChild(panel.indicators, "indicatorRow");
141− verify(indicator_row != undefined);
140+ verify(indicatorRow != undefined);
142
141
143− var row_repeater = findChild(panel.indicators, "rowRepeater");
142+ var rowRepeater = findChild(panel.indicators, "rowRepeater");
144− verify(indicator_row != undefined);
143+ verify(indicatorRow != undefined);
145
144
146− var menu_content = findChild(panel.indicators, "menuContent");
145+ var menuContent = findChild(panel.indicators, "menuContent");
147− verify(indicator_row != undefined);
146+ verify(indicatorRow != undefined);
148
147
149 // Wait for the indicators to get into position.
148 // Wait for the indicators to get into position.
150 // (switches between normal and fullscreen modes are animated)
149 // (switches between normal and fullscreen modes are animated)
@@ -155,20 +154,20 @@ Item {
155 }
154 }
156
155
157 // do this for each indicator item
156 // do this for each indicator item
158− for (var i = 0; i < row_repeater.count; i++) {
157+ for (var i = 0; i < rowRepeater.count; i++) {
159
158
160− var indicator_item = get_indicator_item(i);
159+ var indicatorItem = get_indicator_item(i);
161− verify(indicator_item != undefined);
160+ verify(indicatorItem != undefined);
162
161
163− var indicator_item_coord = get_indicator_item_position(i);
162+ var indicatorItemCoord = get_indicator_item_position(i);
164
163
165 touchPress(panel,
164 touchPress(panel,
166− indicator_item_coord.x, panel.panelHeight / 2);
165+ indicatorItemCoord.x, panel.panelHeight / 2);
167
166
168 // 1) Drag the mouse down
167 // 1) Drag the mouse down
169 touchFlick(panel,
168 touchFlick(panel,
170− indicator_item_coord.x, panel.panelHeight / 2,
169+ indicatorItemCoord.x, panel.panelHeight / 2,
171− indicator_item_coord.x, panel.height * 0.8,
170+ indicatorItemCoord.x, panel.height * 0.8,
172 false /* beginTouch */, false /* endTouch */);
171 false /* beginTouch */, false /* endTouch */);
173
172
174 // Indicators height should follow the drag, and therefore increase accordingly.
173 // Indicators height should follow the drag, and therefore increase accordingly.
@@ -177,13 +176,13 @@ Item {
177 function() {return panel.indicators.height >= panel.height * 0.5},
176 function() {return panel.indicators.height >= panel.height * 0.5},
178 true);
177 true);
179
178
180− touchRelease(panel, indicator_item_coord.x, panel.height * 0.8);
179+ touchRelease(panel, indicatorItemCoord.x, panel.height * 0.8);
181
180
182− compare(indicator_row.currentItem, indicator_item,
181+ compare(indicatorRow.currentItem, indicatorItem,
183 "Incorrect item activated at position " + i);
182 "Incorrect item activated at position " + i);
184− compare(menu_content.currentIndex, i, "Menu conetent should be enabled for item at position " + i);
183+ compare(menuContent.currentMenuIndex, i, "Menu conetent should be enabled for item at position " + i);
185
184
186− // init for next indicator_item
185+ // init for next indicatorItem
187 init();
186 init();
188 }
187 }
189 }
188 }
@@ -192,12 +191,12 @@ Item {
192 panel.fullscreenMode = false;
191 panel.fullscreenMode = false;
193 panel.searchVisible = true;
192 panel.searchVisible = true;
194
193
195− var search_indicator = findChild(panel, "search");
194+ var searchIndicator = findChild(panel, "search");
196− verify(search_indicator != undefined);
195+ verify(searchIndicator != undefined);
197
196
198− tap(search_indicator, 1, 1);
197+ tap(searchIndicator, 1, 1);
199
198
200− compare(search_clicked, true,
199+ compare(searchClicked, true,
201 "Tapping search indicator while it was enabled did not emit searchClicked signal");
200 "Tapping search indicator while it was enabled did not emit searchClicked signal");
202 }
201 }
203
202
@@ -205,13 +204,54 @@ Item {
205 panel.fullscreenMode = false;
204 panel.fullscreenMode = false;
206 panel.searchVisible = false;
205 panel.searchVisible = false;
207
206
208− var search_indicator = findChild(panel, "search");
207+ var searchIndicator = findChild(panel, "search");
209− verify(search_indicator != undefined);
208+ verify(searchIndicator != undefined);
210
209
211− tap(search_indicator, 1, 1);
210+ tap(searchIndicator, 1, 1);
212
211
213− compare(search_clicked, false,
212+ compare(searchClicked, false,
214 "Tapping search indicator while it was not visible emitted searchClicked signal");
213 "Tapping search indicator while it was not visible emitted searchClicked signal");
215 }
214 }
215+
216+ // Test the vertical velocity check when flicking the indicators open at an angle.
217+ // If the vertical velocity is above a specific point, we shouldnt change active indicators
218+ // if the x position changes
219+ function test_vertical_velocity_detector() {
220+ panel.fullscreenMode = false;
221+ panel.searchVisible = false;
222+
223+ var indicatorRow = findChild(panel.indicators, "indicatorRow");
224+ verify(indicatorRow != undefined);
225+
226+ var rowRepeater = findChild(panel.indicators, "rowRepeater");
227+ verify(indicatorRow != undefined);
228+
229+ // Get the first indicator
230+ var indicatorItemFirst = get_indicator_item(0);
231+ verify(indicatorItemFirst != undefined);
232+
233+ var indicatorItemCoordFirst = get_indicator_item_position(0);
234+ var indicatorItemCoordNext = get_indicator_item_position(indicatorRow.count - 1);
235+
236+ touchPress(panel,
237+ indicatorItemCoordFirst.x, panel.panelHeight / 2);
238+
239+ // 1) Drag the mouse down to hint a bit
240+ touchFlick(panel,
241+ indicatorItemCoordFirst.x, panel.panelHeight / 2,
242+ indicatorItemCoordFirst.x, panel.panelHeight * 2,
243+ false /* beginTouch */, false /* endTouch */);
244+
245+ tryCompare(indicatorRow, "currentItem", indicatorItemFirst)
246+
247+ // 1) Flick mouse down to bottom
248+ touchFlick(panel,
249+ indicatorItemCoordFirst.x, panel.panelHeight * 2,
250+ indicatorItemCoordNext.x, panel.height,
251+ false /* beginTouch */, true /* endTouch */,
252+ units.gu(10) /* speed */, 30 /* iterations */); // more samples needed for accurate velocity
253+
254+ compare(indicatorRow.currentItem, indicatorItemFirst, "First indicator should still be the current item");
255+ }
216 }
256 }
217}
257}
tests/qmltests/Panel/tst_SearchIndicator.qml+8−10
@@ -41,24 +41,22 @@ Item {
41 when: windowShown
41 when: windowShown
42
42
43 function test_clickedSignal() {
43 function test_clickedSignal() {
44− clickedSpy.clear()
44+ clickedSpy.clear();
45 mouseClick(searchIndicator,
45 mouseClick(searchIndicator,
46 searchIndicator.width / 2, searchIndicator.height / 2);
46 searchIndicator.width / 2, searchIndicator.height / 2);
47− compare(clickedSpy.count, 1)
47+ compare(clickedSpy.count, 1);
48 }
48 }
49
49
50 function test_hideUp() {
50 function test_hideUp() {
51− var container = findChild(searchIndicator, "container")
51+ var container = findChild(searchIndicator, "container");
52− searchIndicator.state = "hiddenUp"
52+ searchIndicator.state = "hidden";
53− tryCompare(container, "opacity", 0)
53+ tryCompare(container, "opacity", 0);
54− tryCompare(container, "y", -container.height)
55 }
54 }
56
55
57 function test_show() {
56 function test_show() {
58− var container = findChild(searchIndicator, "container")
57+ var container = findChild(searchIndicator, "container");
59− searchIndicator.state = "visible"
58+ searchIndicator.state = "visible";
60− tryCompare(container, "opacity", 1)
59+ tryCompare(container, "opacity", 1);
61− tryCompare(container, "y", 0)
62 }
60 }
63 }
61 }
64}
62}
tests/qmltests/tst_Shell.qmlnew file+281
@@ -0,0 +1,281 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Daniel d'Andrada <daniel.dandrada@canonical.com>
6+ *
7+ * 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
9+ * the Free Software Foundation; version 3.
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+import QtQuick 2.0
21+import QtTest 1.0
22+import Ubuntu.Application 0.1
23+import Unity.Test 0.1 as UT
24+
25+import "../.."
26+
27+Item {
28+ width: shell.width
29+ height: shell.height
30+
31+ QtObject {
32+ id: applicationArguments
33+
34+ function hasGeometry() {
35+ return false;
36+ }
37+
38+ function width() {
39+ return 0;
40+ }
41+
42+ function height() {
43+ return 0;
44+ }
45+ }
46+
47+ Shell {
48+ id: shell
49+ }
50+
51+ UT.UnityTestCase {
52+ name: "Shell"
53+ when: windowShown
54+
55+ function initTestCase() {
56+ // swipe away the greeter/lockscreen
57+ var touchX = shell.width - (shell.edgeSize / 2);
58+ var touchY = shell.height / 2;
59+ touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY);
60+
61+ var dash = findChild(shell, "dash");
62+ // wait until the animation has finished
63+ tryCompare(dash, "contentScale", 1.0);
64+ tryCompare(dash, "opacity", 1.0);
65+ }
66+
67+ function cleanup() {
68+ // kill all (fake) running apps
69+ ApplicationManager.mainStageApplications.clear();
70+ ApplicationManager.sideStageApplications.clear();
71+
72+ var dashHome = findChild(shell, "DashHome");
73+ swipeUntilScopeViewIsReached(dashHome);
74+ }
75+
76+ /*
77+ Test the effect of a right-edge drag on the dash in 3 situations:
78+ 1 - when no application has been launched yet
79+ 2 - when there's a minimized application
80+ 3 - after the last running application has been closed/stopped
81+
82+ The behavior of Dash on 3 should be the same as on 1.
83+ */
84+ function test_rightEdgeDrag() {
85+ checkRightEdgeDragWithNoRunningApps();
86+
87+ dragLauncherIntoView();
88+
89+ // Launch an app from the launcher
90+ tapOnAppIconInLauncher();
91+ waitUntilApplicationWindowIsFullyVisible();
92+
93+ // Minimize the application we just launched
94+ swipeFromLeftEdge();
95+
96+ waitForUIToSettle();
97+
98+ checkRightEdgeDragWithMinimizedApp();
99+
100+ // Minimize that application once again
101+ swipeFromLeftEdge();
102+
103+ // kill it
104+ ApplicationManager.mainStageApplications.clear();
105+
106+ waitForUIToSettle();
107+
108+ // Right edge behavior should now be the same as before that app was launched
109+ checkRightEdgeDragWithNoRunningApps();
110+ }
111+
112+ /*
113+ Perform a right-edge drag when the Dash is being show and there are
114+ no running/minimized apps to be restored.
115+
116+ The expected behavior is that an animation should be played to hint the
117+ user that his right-edge drag gesture has been successfully recognized
118+ but there is no application to be brought to foreground.
119+ */
120+ function checkRightEdgeDragWithNoRunningApps() {
121+ var touchX = shell.width - (shell.edgeSize / 2);
122+ var touchY = shell.height / 2;
123+
124+ var dash = findChild(shell, "dash");
125+ // check that dash has normal scale and opacity
126+ compare(dash.contentScale, 1.0);
127+ compare(dash.opacity, 1.0);
128+
129+ touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
130+ true /* beginTouch */, false /* endTouch */);
131+
132+ // check that Dash has been scaled down and had its opacity reduced
133+ tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
134+ tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
135+
136+ touchRelease(shell, shell.width * 0.1, touchY);
137+
138+ // and now everything should have gone back to normal
139+ tryCompare(dash, "contentScale", 1.0);
140+ tryCompare(dash, "opacity", 1.0);
141+ }
142+
143+ /*
144+ Perform a right-edge drag when the Dash is being show and there is
145+ a running/minimized app to be restored.
146+
147+ The expected behavior is that the dash should fade away and ultimately be
148+ made invisible once the gesture is finished as the restored app will now
149+ be on foreground.
150+ */
151+ function checkRightEdgeDragWithMinimizedApp() {
152+ var touchX = shell.width - (shell.edgeSize / 2);
153+ var touchY = shell.height / 2;
154+
155+ var dash = findChild(shell, "dash");
156+ // check that dash has normal scale and opacity
157+ tryCompare(dash, "contentScale", 1.0);
158+ tryCompare(dash, "opacity", 1.0);
159+
160+ touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
161+ true /* beginTouch */, false /* endTouch */);
162+
163+ // check that Dash has been scaled down and had its opacity reduced
164+ tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
165+ tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
166+
167+ touchRelease(shell, shell.width * 0.1, touchY);
168+
169+ // dash should have gone away, now that the app is on foreground
170+ tryCompare(dash, "visible", false);
171+ }
172+
173+ // Wait for the whole UI to settle down
174+ function waitForUIToSettle() {
175+ waitUntilApplicationWindowIsFullyHidden();
176+ var dashContentList = findChild(shell, "dashContentList");
177+ tryCompare(dashContentList, "moving", false);
178+ }
179+
180+ function dragLauncherIntoView() {
181+ var launcherPanel = findChild(shell, "launcherPanel");
182+ verify(launcherPanel.x = - launcherPanel.width);
183+ swipeFromLeftEdge();
184+ tryCompare(launcherPanel, "x", 0);
185+ }
186+
187+ function tapOnAppIconInLauncher() {
188+ var launcherPanel = findChild(shell, "launcherPanel");
189+
190+ // pick the first icon, the one at the bottom.
191+ var appIcon = findChild(launcherPanel, "launcherDelegate0")
192+
193+ // Swipe upwards over the launcher to ensure that this icon
194+ // at the bottom is not folded and faded away.
195+ var touchStartX = launcherPanel.width / 2;
196+ var touchStartY = launcherPanel.height / 2;
197+ touchFlick(launcherPanel, touchStartX, touchStartY, touchStartX, 0);
198+ tryCompare(launcherPanel, "moving", false);
199+
200+ // NB tapping (i.e., using touch events) doesn't activate the icon... go figure...
201+ mouseClick(appIcon, appIcon.width / 2, appIcon.height / 2);
202+ }
203+
204+ function waitUntilApplicationWindowIsFullyVisible() {
205+ var underlay = findChild(shell, "underlay");
206+ tryCompare(underlay, "visible", false);
207+ }
208+
209+ function waitUntilApplicationWindowIsFullyHidden() {
210+ var stages = findChild(shell, "stages");
211+ tryCompare(stages, "fullyHidden", true);
212+ }
213+
214+ function swipeUntilScopeViewIsReached(scopeView) {
215+ while (!itemIsOnScreen(scopeView)) {
216+ if (itemIsToLeftOfScreen(scopeView)) {
217+ swipeRightFromCenter();
218+ } else {
219+ swipeLeftFromCenter();
220+ }
221+ waitUntilItemStopsMoving(scopeView);
222+ }
223+ }
224+
225+ function swipeFromLeftEdge() {
226+ var touchStartX = 2;
227+ var touchStartY = shell.height / 2;
228+ touchFlick(shell, touchStartX, touchStartY, shell.width * 0.75, touchStartY);
229+ }
230+
231+ function swipeLeftFromCenter() {
232+ var touchStartX = shell.width / 2;
233+ var touchStartY = shell.height / 2;
234+ touchFlick(shell, touchStartX, touchStartY, 0, touchStartY);
235+ }
236+
237+ function swipeRightFromCenter() {
238+ var touchStartX = shell.width / 2;
239+ var touchStartY = shell.height / 2;
240+ touchFlick(shell, touchStartX, touchStartY, shell.width, touchStartY);
241+ }
242+
243+ function swipeUpFromCenter() {
244+ var touchStartX = shell.width / 2;
245+ var touchStartY = shell.height / 2;
246+ touchFlick(shell, touchStartX, touchStartY, touchStartX, 0);
247+ }
248+
249+ function itemIsOnScreen(item) {
250+ var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
251+
252+ return itemRectInShell.x >= 0
253+ && itemRectInShell.y >= 0
254+ && itemRectInShell.x + itemRectInShell.width <= shell.width
255+ && itemRectInShell.y + itemRectInShell.height <= shell.height;
256+ }
257+
258+ function itemIsToLeftOfScreen(item) {
259+ var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
260+ return itemRectInShell.x < 0;
261+ }
262+
263+ function waitUntilItemStopsMoving(item) {
264+ var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
265+ var previousX = itemRectInShell.x;
266+ var previousY = itemRectInShell.y;
267+ var isStill = false;
268+
269+ do {
270+ wait(100);
271+ itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
272+ if (itemRectInShell.x == previousX && itemRectInShell.y == previousY) {
273+ isStill = true;
274+ } else {
275+ previousX = itemRectInShell.x;
276+ previousY = itemRectInShell.y;
277+ }
278+ } while (!isStill);
279+ }
280+ }
281+}
tests/utils/modules/Unity/Test/UnityTestCase.qml+32−23
@@ -32,32 +32,34 @@ TestCase {
32 // Qt uses in QQuickViewTestUtil::flick
32 // Qt uses in QQuickViewTestUtil::flick
33 // speed is in pixels/second
33 // speed is in pixels/second
34 function mouseFlick(item, x, y, toX, toY, pressMouse, releaseMouse,
34 function mouseFlick(item, x, y, toX, toY, pressMouse, releaseMouse,
35− speed) {
35+ speed, iterations) {
36 pressMouse = ((pressMouse != null) ? pressMouse : true); // Default to true for pressMouse if not present
36 pressMouse = ((pressMouse != null) ? pressMouse : true); // Default to true for pressMouse if not present
37 releaseMouse = ((releaseMouse != null) ? releaseMouse : true); // Default to true for releaseMouse if not present
37 releaseMouse = ((releaseMouse != null) ? releaseMouse : true); // Default to true for releaseMouse if not present
38
38
39 // set a default speed if not specified
39 // set a default speed if not specified
40 speed = (speed != null) ? speed : units.gu(10);
40 speed = (speed != null) ? speed : units.gu(10);
41
41
42+ // set a default iterations if not specified
43+ iterations = (iterations !== undefined) ? iterations : 5
44+
42 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
45 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
43 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
46 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
44
47
45− var nIterations = 5
46− var timeStep = totalTime / nIterations
48+ var timeStep = totalTime / iterations
47− var diffX = (toX - x) / nIterations
49+ var diffX = (toX - x) / iterations
48− var diffY = (toY - y) / nIterations
50+ var diffY = (toY - y) / iterations
49 if (pressMouse) {
51 if (pressMouse) {
50 fakeDateTime.currentTimeMs += timeStep
52 fakeDateTime.currentTimeMs += timeStep
51 mousePress(item, x, y)
53 mousePress(item, x, y)
52 }
54 }
53− for (var i = 0; i < nIterations; ++i) {
55+ for (var i = 0; i < iterations; ++i) {
54 fakeDateTime.currentTimeMs += timeStep
56 fakeDateTime.currentTimeMs += timeStep
55− if (i === nIterations - 1) {
57+ if (i === iterations - 1) {
56 // Avoid any rounding errors by making the last move be at precisely
58 // Avoid any rounding errors by making the last move be at precisely
57 // the point specified
59 // the point specified
58− mouseMove(item, toX, toY, nIterations / speed)
60+ mouseMove(item, toX, toY, iterations / speed)
59 } else {
61 } else {
60− mouseMove(item, x + (i + 1) * diffX, y + (i + 1) * diffY, nIterations / speed)
62+ mouseMove(item, x + (i + 1) * diffX, y + (i + 1) * diffY, iterations / speed)
61 }
63 }
62 }
64 }
63 if (releaseMouse) {
65 if (releaseMouse) {
@@ -70,11 +72,16 @@ TestCase {
70 // Find an object with the given name recursively, starting
72 // Find an object with the given name recursively, starting
71 // at the given object "obj"
73 // at the given object "obj"
72 function findChild(obj,objectName) {
74 function findChild(obj,objectName) {
75+ var childs = new Array(0);
76+ childs.push(obj)
77+ while (childs.length > 0) {
78+ if (childs[0].objectName == objectName) {
79+ return childs[0]
80+ }
73− for (var i in obj.children) {
81+ for (var i in childs[0].data) {
74− var child = obj.children[i];
82+ childs.push(childs[0].data[i])
75− if (child.objectName === objectName) return child;
83+ }
76− var subChild = findChild(child,objectName);
84+ childs.splice(0, 1);
77− if (subChild !== undefined) return subChild;
78 }
85 }
79 return undefined;
86 return undefined;
80 }
87 }
@@ -186,7 +193,7 @@ TestCase {
186 }
193 }
187
194
188 // speed is in pixels/second
195 // speed is in pixels/second
189− function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed) {
196+ function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
190
197
191 // Default to true for beginTouch if not present
198 // Default to true for beginTouch if not present
192 beginTouch = (beginTouch !== undefined) ? beginTouch : true
199 beginTouch = (beginTouch !== undefined) ? beginTouch : true
@@ -197,13 +204,15 @@ TestCase {
197 // Set a default speed if not specified
204 // Set a default speed if not specified
198 speed = (speed !== undefined) ? speed : units.gu(10)
205 speed = (speed !== undefined) ? speed : units.gu(10)
199
206
207+ // Set a default iterations if not specified
208+ var iterations = (iterations !== undefined) ? iterations : 5
209+
200 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
210 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
201 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
211 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
202
212
203− var nIterations = 5
204− var timeStep = totalTime / nIterations
213+ var timeStep = totalTime / iterations
205− var diffX = (toX - x) / nIterations
214+ var diffX = (toX - x) / iterations
206− var diffY = (toY - y) / nIterations
215+ var diffY = (toY - y) / iterations
207 if (beginTouch) {
216 if (beginTouch) {
208 fakeDateTime.currentTimeMs += timeStep
217 fakeDateTime.currentTimeMs += timeStep
209
218
@@ -211,17 +220,17 @@ TestCase {
211 event.press(0 /* touchId */, x, y)
220 event.press(0 /* touchId */, x, y)
212 event.commit()
221 event.commit()
213 }
222 }
214− for (var i = 0; i < nIterations; ++i) {
223+ for (var i = 0; i < iterations; ++i) {
215 fakeDateTime.currentTimeMs += timeStep
224 fakeDateTime.currentTimeMs += timeStep
216− if (i === nIterations - 1) {
225+ if (i === iterations - 1) {
217 // Avoid any rounding errors by making the last move be at precisely
226 // Avoid any rounding errors by making the last move be at precisely
218 // the point specified
227 // the point specified
219− wait(nIterations / speed)
228+ wait(iterations / speed)
220 var event = touchEvent()
229 var event = touchEvent()
221 event.move(0 /* touchId */, toX, toY)
230 event.move(0 /* touchId */, toX, toY)
222 event.commit()
231 event.commit()
223 } else {
232 } else {
224− wait(nIterations / speed)
233+ wait(iterations / speed)
225 var event = touchEvent()
234 var event = touchEvent()
226 event.move(0 /* touchId */, x + (i + 1) * diffX, y + (i + 1) * diffY)
235 event.move(0 /* touchId */, x + (i + 1) * diffX, y + (i + 1) * diffY)
227 event.commit()
236 event.commit()