File: tst_scrollbar_header.13.qml

package info (click to toggle)
lomiri-ui-toolkit 1.3.5010%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 25,900 kB
  • sloc: cpp: 85,772; python: 5,528; sh: 1,364; javascript: 919; ansic: 573; makefile: 204
file content (315 lines) | stat: -rw-r--r-- 13,775 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/*
 * Copyright 2016 Canonical Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Andrea Bernabei <andrea.bernabei@canonical.com>
 */

import QtQuick 2.4
import QtTest 1.0
import Lomiri.Test 1.0
import Lomiri.Components 1.3
import Lomiri.Components.Styles 1.3
import QtQml.Models 2.1

Item {
    id: main
    width: units.gu(50)
    height: units.gu(100)

    Component {
        id: flickableComp
        Item {
            id: item
            width: units.gu(20)
            height: units.gu(30)
            property alias flickable: freshFlickable
            property alias scrollbar: freshScrollbar
            property alias content: content
            property alias scrollbarAlignment: freshScrollbar.align

            //Don't change this to a ListView, this usecase has to be simple,
            //we don't want the difficulties added by ListView, i.e. delegates
            //size estimation, dynamic contentWidth/Height, etc
            Flickable {
                id: freshFlickable
                anchors.fill: parent
                contentHeight: content.height
                contentWidth: content.width
                clip: true
                Rectangle {
                    id: content
                    width: units.gu(40)
                    //make this much taller than the flickable to avoid timing issues when
                    //detecting if the flickable is flicking in the tests
                    height: units.gu(200)
                    color: "blue"
                }
            }
            Scrollbar {
                id: freshScrollbar
                flickableItem: parent.flickable
            }
        }
    }

    SignalSpy {
        id: signalSpy
    }
    SignalSpy {
        id: anotherSignalSpy
    }

    Flickable {
        anchors.fill: parent
        Column {
            id: column
            Repeater {
                model: layoutsModel
            }
        }
    }

    VisualItemModel {
        id: layoutsModel
        Item {
            width: childrenRect.width
            height: childrenRect.height
            Flickable {
                id: randomFlickable
            }

            //complex PageHeader example taken from the PageHeader tutorial
            //https://developer.lomiri.com/en/blog/2016/02/24/pageheader-tutorial/
            MainView {
                id: mainView_movingHeaderTest
                width: units.gu(50)
                height: units.gu(80)
                clip: true

                property alias page: pageItem
                property alias standardHeader: standardHeaderItem
                property alias editHeader: editHeaderItem

                Page {
                    id: pageItem
                    header: standardHeaderItem

                    Flickable {
                        id: flickable_movingHeaderTest
                        anchors.fill: parent
                        //just make sure the scrollbar is scrollable
                        contentHeight: mainView_movingHeaderTest.height * 2
                        contentWidth: mainView_movingHeaderTest.width * 2
                        Label {
                            text: "Use the icons in the header."
                            visible: standardHeaderItem.visible
                        }
                    }
                    Scrollbar {
                        id: scrollbar_movingHeaderTest
                        flickableItem: flickable_movingHeaderTest
                    }

                    PageHeader {
                        id: standardHeaderItem
                        // hide the header until it is used by the page
                        parent: null
                        title: "Default title"
                        flickable: flickable_movingHeaderTest
                        trailingActionBar.actions: [
                            Action {
                                iconName: "edit"
                                text: "Edit"
                                onTriggered: pageItem.header = editHeaderItem
                            }
                        ]

                        // Workaround Qt not setting null parent as expected.
                        // https://bugreports.qt.io/browse/QTBUG-92446
                        Component.onCompleted: {
                            parent = null;
                        }
                    }
                    PageHeader {
                        id: editHeaderItem
                        // hide the header until it is used by the page
                        parent: null
                        flickable: flickable_movingHeaderTest
                        property Component delegate: Component {
                            AbstractButton {
                                id: button
                                action: modelData
                                width: label.width + units.gu(4)
                                height: parent.height
                                Rectangle {
                                    color: LomiriColors.slate
                                    opacity: 0.1
                                    anchors.fill: parent
                                    visible: button.pressed
                                }
                                Label {
                                    anchors.centerIn: parent
                                    id: label
                                    text: action.text
                                    font.weight: text === "Confirm"
                                                 ? Font.Normal
                                                 : Font.Light
                                }
                            }
                        }
                        leadingActionBar {
                            anchors.leftMargin: 0
                            actions: Action {
                                text: "Cancel"
                                iconName: "close"
                                onTriggered: pageItem.header = standardHeaderItem
                            }
                            delegate: editHeaderItem.delegate
                        }
                        trailingActionBar {
                            anchors.rightMargin: 0
                            actions: Action {
                                text: "Confirm"
                                iconName: "tick"
                                onTriggered: pageItem.header = standardHeaderItem
                            }
                            delegate: editHeaderItem.delegate
                        }
                        extension: Toolbar {
                            anchors {
                                left: parent.left
                                right: parent.right
                                bottom: parent.bottom
                            }
                            trailingActionBar.actions: [
                                Action { iconName: "bookmark-new" },
                                Action { iconName: "add" },
                                Action { iconName: "edit-select-all" },
                                Action { iconName: "edit-copy" },
                                Action { iconName: "select" }
                            ]
                            leadingActionBar.actions: Action {
                                iconName: "delete"
                                text: "delete"
                                onTriggered: print("Delete action triggered")
                            }
                        }

                        // Workaround Qt not setting null parent as expected.
                        // https://bugreports.qt.io/browse/QTBUG-92446
                        Component.onCompleted: {
                            parent = null;
                        }
                    }

                }
            }

        }
    }

    // FIXME: Tests failing with Qt 5.6. See bug #1624337.
    ScrollbarTestCase13 {
        name: "Scrollbar"

        function getMovingHeaderView() {
            var wrapper = movingHeaderHandlingItem.createObject(column)
            verify(wrapper !== null, "Error: dynamic item creation failed.")
            currComponent = wrapper
            return currComponent
        }

        function cleanup() {
            if (currComponent) {
                currComponent.destroy()
                currComponent = null
            }
            gc()
        }

        function checkScrollbarPositionRelativeToPage(scrollbar, page, expectedY, msgPrefix) {
            compare(scrollbar.mapToItem(page, 0, 0).y, expectedY, msgPrefix + ": Scrollbar does not start below the header.")
        }

        function test_handlingOfMovingHeader_data() {
            return [
                        { tag: "Standard header", header: standardHeaderItem },
                        { tag: "Edit header (with extensions)", header: editHeaderItem },
                        //Setting header to null means using the old header, and:
                        //- We don't support this behaviour when using the old header
                        //- There is no API to get the height of the old header, so we can't test it
                        //{ tag: "Null header", header: null }
                    ]
        }
        function test_handlingOfMovingHeader(data) {
            var page = pageItem
            var header = data.header
            page.header = header

            compare(page.header, header, "Handling of moving header: wrong header.")
            compare(scrollbar_movingHeaderTest.__styleInstance.isVertical, true, "Scrollbar is not vertical.")
            compare(scrollbar_movingHeaderTest.__styleInstance.isScrollable, true, "Scrollbar is not scrollable.")

            //don't do the rest of the checks on the null header, just check that it's aligning with the old header implementation
            //(page.head.contents.height)
            if (data.header === null) {
                checkScrollbarPositionRelativeToPage(scrollbar_movingHeaderTest, page, page.head.contents.height, data.tag)
                return
            } else {
                compare(header.flickable, flickable_movingHeaderTest, "Wrong PageHeader flickable.")
                checkScrollbarPositionRelativeToPage(scrollbar_movingHeaderTest, page, page.header.height, data.tag + ", at initialization.")
            }

            var tmpHeaderHeight = header.height
            page.header.height += units.gu(1)
            //make sure the header actually has a different height now
            verify(scrollbar_movingHeaderTest.height !== tmpHeaderHeight, "Header height changed value.")
            checkScrollbarPositionRelativeToPage(scrollbar_movingHeaderTest, page, page.header.height,
                                                 data.tag + ", after changing height")

            //now link the header to a null flickable and check that scrollbar is covered
            //the header (yes, we're checking that it creates bad UX, because we're expecting the
            //developer to set the anchors accordingly so that we don't need to add  inter-components
            //dependencies. The test Page does not handle this on purpose, so the header
            //should cover the scrollbar)
            header.flickable = null
            compare(header.flickable, null, "Wrong PageHeader flickable.")
            checkScrollbarPositionRelativeToPage(scrollbar_movingHeaderTest, page, 0, data.tag)

            //reassign the correct flickable and check again
            header.flickable = flickable_movingHeaderTest
            compare(header.flickable, flickable_movingHeaderTest, "Wrong PageHeader flickable.")
            checkScrollbarPositionRelativeToPage(scrollbar_movingHeaderTest, page, page.header.height, data.tag + ", scrollbar")

            header.visible = false
            compare(header.visible, false, "Header visibility did not change, should have been false.")
            checkScrollbarPositionRelativeToPage(scrollbar_movingHeaderTest, page, 0, data.tag + ", invisible header")

            header.visible = true
            compare(header.visible, true, "Header visibility did not change, should have been true.")
            checkScrollbarPositionRelativeToPage(scrollbar_movingHeaderTest, page, page.header.height, data.tag + ", visible header")

            //even if the header has opacity 0, we should still take it into account. This is a standard in
            //QtQuick, you don't ignore a component just because opacity is 0, as that is also used for animations
            header.opacity = 0.0
            compare(header.opacity, 0.0, "Header opacity did not change, should have been 0.")
            checkScrollbarPositionRelativeToPage(scrollbar_movingHeaderTest, page, page.header.height, data.tag + ", 0.0 header opacity")

            header.opacity = 1.0
            compare(header.opacity, 1.0, "Header opacity did not change, should have been 1.")
            checkScrollbarPositionRelativeToPage(scrollbar_movingHeaderTest, page, page.header.height, data.tag + ", 1.0 header opacity")
        }
    }
}