on xenial help sign in
Merge trunk
commit40c7650fc215c81d3b31c132d9e3c513448d2f85 authorMichal Hruby <michal.mhr@gmail.com> dateMon 1 Jul 2013, 22:32 (13 years ago) parentc3d8114d894886
120 files changed+7849−2899
.bazaar/plugins/makecheck_unity_phablet.py+15−6 .bzrignore+1 Bottombar/Bottombar.qml+1−8 CODING+75−29 Components/Carousel.qml+2 Components/DragHandle.qml+208 Components/EdgeDragArea.qml+36 Components/EdgeDragEvaluator.qml+88 Components/FilterGrid.qml+1−1 Components/ListItems/Base.qml+19−21 Components/ListItems/Header.qml−6 Components/ListItems/ThinDivider.qml−4 Components/ListViewWithPageHeader.qml−189 Components/PageHeader.qml+2−2 Components/Stage.qml+8−10 Components/Tile.qml+1−1 Components/UbuntuShapeForItem.qml+12−56 Components/WrongPasswordAnimation.qml+3−3 Dash/Apps/RunningApplicationTile.qml+1−1 Dash/DashApps.qml+2−3 Dash/DashHome.qml+1−2 Dash/DashMusic.qml+1−2 Dash/DashVideos.qml+2−3 Dash/GenericScopeView.qml+1−1 Dash/Music/AlbumTile.qml+1−1 Dash/ScopeListView.qml+23 Greeter/Greeter.qml+28−2 Greeter/GreeterContent.qml+3−1 Greeter/LoginList.qml−8 Hud/SearchBar.qml−7 Hud/ToolBarIcon.qml+1−1 Launcher/Launcher.qml+9−17 Launcher/LauncherDelegate.qml+202−39 Launcher/LauncherPanel.qml+106−52 Launcher/graphics/home@18.png Shell.qml+42−40 build+2 debian/changelog+24 debian/control+2 debian/unity8.install+1 main.cpp+26−6 paths.h.in+10−3 plugins/CMakeLists.txt+1 plugins/ListViewWithPageHeader/CMakeLists.txt+44 plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+1059 plugins/ListViewWithPageHeader/listviewwithpageheader.h+180 plugins/ListViewWithPageHeader/plugin.cpp+29 plugins/ListViewWithPageHeader/plugin.h+33 plugins/ListViewWithPageHeader/qmldir+2 plugins/Ubuntu/Gestures/AxisVelocityCalculator.cpp+31−16 plugins/Ubuntu/Gestures/AxisVelocityCalculator.h+31−20 plugins/Ubuntu/Gestures/Direction.cpp+5 plugins/Ubuntu/Gestures/Direction.h+1 plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+59−8 plugins/Ubuntu/Gestures/DirectionalDragArea.h+21−3 po/ar.po+37−45 po/az.po+18−44 po/bg.po+24−44 po/ca.po+24−44 po/de.po+38−46 po/el.po+18−44 po/en_AU.po+36−44 po/en_GB.po+38−46 po/eo.po+12−44 po/es.po+36−44 po/fi.po+33−44 po/fo.po+18−44 po/fr.po+71−82 po/gl.po+24−44 po/he.po+18−44 po/hr.po+18−44 po/hu.po+18−44 po/hy.po+24−44 po/id.po+12−44 po/it.po+18−44 po/ja.po+12−44 po/kn.po+18−44 po/ko.po+12−44 po/ky.po+18−44 po/lv.po+18−44 po/my.po+15−44 po/nb.po+18−44 po/nl.po+18−44 po/pl.po+36−44 po/pt_BR.po+18−44 po/ro.po+18−44 po/ru.po+27−44 po/si.po+12−44 po/sl.po+43−69 po/sr.po+18−44 po/sv.po+12−44 po/te.po+12−44 po/th.po+220 po/tr.po+33−44 po/ug.po+36−47 po/uk.po+39−47 po/unity8.pot+4−9 po/zh_CN.po+37−45 po/zh_TW.po+24−44 run_on_device+1−1 tests/plugins/CMakeLists.txt+1 tests/plugins/ListViewWithPageHeader/CMakeLists.txt+31 tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+1311 tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cpp+1567 tests/plugins/ListViewWithPageHeader/test.qml+96 tests/plugins/ListViewWithPageHeader/test_section.qml+106 tests/plugins/Ubuntu/Gestures/tst_AxisVelocityCalculator.cpp+40−28 tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp+99−11 tests/qmltests/CMakeLists.txt+2−1 tests/qmltests/Components/CMakeLists.txt+23 tests/qmltests/Components/tst_DragHandle.cpp+395 tests/qmltests/Components/tst_DragHandle.qml+146 tests/qmltests/Components/tst_DragHandle/HorizontalShowable.qml+100 tests/qmltests/Components/tst_DragHandle/TestButton.qml+41 tests/qmltests/Components/tst_DragHandle/UnityLogo.png tests/qmltests/Components/tst_DragHandle/VerticalShowable.qml+100 tests/qmltests/Components/tst_ListViewWithPageHeader.qml−351 tests/qmltests/Components/tst_Stage.qml+1−2 tests/qmltests/Greeter/tst_Phone.qml+40−1 tests/qmltests/Launcher/tst_Launcher.qml+40
.bazaar/plugins/makecheck_unity_phablet.py+15−6
@@ -23,12 +23,21 @@ def execute_makecheck(local_branch, master_branch, old_revision_number, old_revi
2323
2424 os.chdir(local_path_from_url(master_branch.base))
2525
26− print "Executing 'make check'.."
27− if (subprocess.call("make check", shell=True) != 0):
28− raise errors.BzrError("Unit tests failed, fix them before committing!")
26+ print "Executing 'make -C builddir test'.."
27+ os.environ['CTEST_OUTPUT_ON_FAILURE'] = "1"
28+ if (subprocess.call("make -C builddir test", shell=True) != 0):
2929
30− print "Executing 'make qmluitests'.."
31− if (subprocess.call("make qmluitests", shell=True) != 0):
32− raise errors.BzrError("QML UI tests failed, fix them before committing!")
30+ print("\n\n*** Warning ***\n\nBasic tests failed. This commit will not pass continuous integration.")
31+
32+ branch = local_branch or master_branch
33+ revision = branch.repository.get_revision(future_revision_id)
34+ msg_file = open('message.txt', 'w')
35+ msg_file.write(revision.message)
36+ msg_file.close()
37+
38+ print("\n\nSaved commit message to $SRC_DIR/message.txt.")
39+ print("You can uncommit this revision, fix the tests and reuse your message running:\n\nbzr commit -F message.txt\n\n")
40+ elif os.path.isfile("message.txt"):
41+ os.remove("message.txt")
3342
3443branch.Branch.hooks.install_named_hook('pre_commit', execute_makecheck, 'make check pre-commit')
.bzrignore+1
@@ -7,3 +7,4 @@
77/.cproject
88/.settings
99/.pydevproject
10+message.txt
Bottombar/Bottombar.qml+1−8
@@ -64,7 +64,7 @@ Item {
6464 onShownChanged: bottomBarVisibilityCommunicatorShell.forceHidden = theHud.shown
6565 }
6666
67− DirectionalDragArea {
67+ EdgeDragArea {
6868 id: dragArea
6969 width: parent.width
7070 height: distanceThreshold
@@ -73,13 +73,6 @@ Item {
7373 enabled: !theHud.shown && bottombar.enabled && applicationIsOnForeground
7474 direction: Direction.Upwards
7575
76− // values to be tweaked and later removed from here and set in stone as defaults
77− // once we are confident it's all good.
78− maxDeviation: units.gu(1)
79− wideningAngle: 30
80− distanceThreshold: units.gu(3)
81− minSpeed: units.gu(5)
82−
8376 property int previousStatus: -1
8477 property real touchStartX: -1
8578
CODING+75−29
@@ -1,43 +1,64 @@
11Building Unity 8
22================
33
4+Only Ubuntu 13.10 (saucy) is supported as a developement environment.
5+
46download source
57---------------
6−- the build requires some additional dependencies, so create the parent folder to not pollute your setup
7− $ mkdir ~/unity
8+- create a parent folder to not pollute your setup. so that you can have different unity
9+ branches there (trunk, WIP etc)
10+
11+ $ mkdir ~/unity8
812
913- fetch Unity 8 source
1014 $ sudo apt-get install bzr
11− $ bzr branch lp:unity/8.0 ~/unity/unity8
12− $ cd ~/unity/unity8
15+ $ bzr branch lp:unity8 ~/unity8/trunk
16+ $ cd ~/unity8/trunk
17+
18+install dependencies
19+--------------------
20+If its your first time, install build dependencies
21+
22+$ cd ~/unity8/trunk
23+$ ./build --setup
1324
14−build dependencies
15−------------------
16−If its your first time, download & build deps
17−$ ./build -s
1825 this will:
19− - add ppa:phablet-team/desktop-deps, ppa:canonical-qt5-edgers/qt5-proper, ppa:ubuntu-sdk-team
20− - build and install lp:libunity/phablet, lp:unity/phablet-mods, lp:hud/phablet locally
21− - install build dependencies
26+ - add the following PPA's
27+ - ppa:phablet-team/desktop-deps
28+ - ppa:canonical-qt5-edgers/qt5-proper
29+ - ppa:ubuntu-sdk-team
30+ - install the required dependencies to build, as well as run on the desktop
31+ - it should also install unity-scope-home and unity-lens-application which
32+ are technically "recommends", not strict dependencies
33+
34+Note, once the PPA's are added, the script runs apt-get update, if you have
35+any failures associated with it, the build script will bail out of the setup
36+and fail to install all the required dependencies.
37+
2238
2339build Unity 8
2440-------------
25−$ ./build
2641
27−subsequent updates of the dependencies
28−--------------------------------------
29−$ ./build_unity -u
30−$ ./build_unity
42+$ cd ~/unity8/trunk
43+$ ./build
3144
45+You may also rebuild with the -c for clean, which just deletes the build
46+directory.
3247
3348Running Unity 8 on your desktop
3449===============================
3550
3651run the Unity 8 shell
3752---------------------
38−$ cd ~/unity/unity8
53+$ cd ~/unity8/trunk
3954$ ./run
4055
56+Options can be passed to test the lock screen
57+$ ./run -p OR -k
58+
59+-p is for pin lock, for which the default prompt answer is "1234"
60+-k is for keylock passphrase, for which the default prompt answer is "password"
61+
4162Notes
4263-----
4364- to navigate, utilize the mouse left button as you would your finger
@@ -45,17 +66,29 @@ Notes
4566 put the *.mo files into correct structure. We'll look for a better solution
4667 later.
4768 $ cd builddir; make install
69+- if you wish to populate contacts
70+ $ sudo apt-get install gir1.2-ebook-1.2
71+ $ manage-address-book.py create
72+ this will:
73+ - Create an EDS address book
74+ - Populate the address book with sample data
4875
4976Running Unity 8 on devices
5077==========================
5178- Ubuntu Touch builds are currently only available in 13.10 flavour
52−- supported hardware should match one those listed here https://wiki.ubuntu.com/Touch/Devices#Running_fine
53−- follow the Ubuntu Touch install instructions for your chosen device https://wiki.ubuntu.com/Touch/Install
79+- supported hardware should match one those listed here
80+ https://wiki.ubuntu.com/Touch/Devices#Running_fine
81+- follow the Ubuntu Touch install instructions for your chosen device
82+ https://wiki.ubuntu.com/Touch/Install
5483- make sure your device is connected to a WiFi network
55−- also make sure you have your SSH key in ~/.ssh/id_rsa.pub (or install one on the device yourself)
56−
57−$ cd ~/unity/unity8
58−$ ./run_on_device -s
84+- If you haven’t already or if you’ve just freshly flashed your device
85+ make sure you run phablet-network-setup which will allow package updates to
86+ the device
87+- also make sure you have your SSH key in ~/.ssh/id_rsa.pub (or install one
88+ on the device yourself)
89+
90+$ cd ~/unity/trunk
91+$ ./run_on_device --setup
5992 this will:
6093 - install your public SSH key on the device
6194 - add ppa:canonical-qt5-edgers/qt5-proper and ppa:phablet-team
@@ -67,19 +100,27 @@ $ ./run_on_device
67100 - build on the device
68101 - replace the running shell
69102
103+Options can be passed to test the lock screen
104+$ ./run_on_device -p OR -k
105+
106+-p is for pin lock, for which the default prompt answer is "1234"
107+-k is for keylock passphrase, for which the default prompt answer is "password"
108+
70109Notes
71110-----
72111- using adb over TCP has some advantages, Google will be of help here
73112 - TL;DR: `adb tcpip 5555; adb connect $your_device_ip`
74113 - you can persist the above via `adb shell setprop persist.adb.tcp.port 5555`
75114 - it's unsafe - anyone can connect to your device
76− - with TCP the Nexus 10 doesn't drop the adb connection when locking the screen
77−- exporting ANDROID_SERIAL=$your_device_serial or ANDROID_SERIAL=$your_device_ip:5555
78− will make adb not complain about multiple devices
115+ - with TCP the Nexus 10 doesn't drop the adb connection when locking
116+ the screen
117+- exporting ANDROID_SERIAL=$your_device_serial or
118+ ANDROID_SERIAL=$your_device_ip:5555 will make adb not complain about
119+ multiple devices
79120- you can export TARGET_IP=$your_device_ip TARGET_SSH_PORT=22 for run_on_device
80121 to not use adb forwarding - useful if you use multiple devices
81−- using Ninja (package ninja-build - run_on_device -s installs this now) will improve
82− build times (especially in the nothing-to-build case)
122+- using Ninja (package ninja-build - run_on_device -s installs this now)
123+ will improve build times (especially in the nothing-to-build case)
83124
84125
85126Coding guidelines
@@ -90,4 +131,9 @@ https://launchpad.net/canonical-client-development-guidelines
90131
91132Development Environment
92133=======================
93−QtCreator (available via the Software Center) is the best IDE to hack on Unity 8.
134+QtCreator (available via the Software Center) is the best IDE to hack on
135+Unity 8.
136+
137+If using VIM, make sure you install some syntax highlighting for QML, like
138+https://github.com/peterhoeg/vim-qml
139+
Components/Carousel.qml+2
@@ -24,6 +24,8 @@ import "carousel.js" as CarouselJS
2424Item {
2525 id: carousel
2626
27+ clip: true // Don't leak horizontally to other dashes
28+
2729 /// The component to be used as delegate. This component has to be derived from BaseCarouselDelegate
2830 property Component itemComponent
2931 /// Model for the Carousel, which has to be a model usable by a ListView
Components/DragHandle.qmlnew file+208
@@ -0,0 +1,208 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
20+import "Math.js" as MathLocal
21+
22+/*
23+ Put a DragHandle inside a Showable to enable the user to drag it from that handle.
24+ Main use case is to drag fullscreen Showables into the screen or off the screen.
25+
26+ This example shows a DragHandle placed on the right corner of a Showable, used
27+ to slide it away, off the screen.
28+
29+ Showable {
30+ x: 0
31+ y: 0
32+ width: ... // screen width
33+ height: ... // screen height
34+ shown: true
35+ ...
36+ DragHandle {
37+ anchors.right: parent.right
38+ anchors.top: parent.top
39+ anchors.bottom: parent.bottom
40+ width: units.gu(2)
41+
42+ direction: DirectionalDragArea::Leftwards
43+ }
44+ }
45+
46+ */
47+EdgeDragArea {
48+ id: dragArea
49+ objectName: "dragHandle"
50+
51+ property bool stretch: false
52+
53+ property alias autoCompleteDragThreshold: dragEvaluator.dragThreshold
54+
55+ // How far you can drag
56+ property real maxTotalDragDistance: {
57+ if (stretch) {
58+ 0; // not enough context information to set a sensible default
59+ } else {
60+ Direction.isHorizontal(direction) ? parent.width : parent.height;
61+ }
62+ }
63+
64+ property real hintDisplacement: 0
65+ SmoothedAnimation {
66+ id: hintingAnimation
67+ target: hintingAnimation
68+ property: "targetValue"
69+ duration: 150
70+ velocity: -1
71+ to: Direction.isPositive(direction) ? d.startValue + hintDisplacement
72+ : d.startValue - hintDisplacement
73+ property real targetValue
74+ onTargetValueChanged: {
75+ if (!running) {
76+ return;
77+ }
78+
79+ if (Direction.isPositive(direction)) {
80+ if (parent[d.targetProp] < targetValue) {
81+ parent[d.targetProp] = targetValue;
82+ }
83+ } else {
84+ if (parent[d.targetProp] > targetValue) {
85+ parent[d.targetProp] = targetValue;
86+ }
87+ }
88+ }
89+ }
90+
91+ // Private stuff
92+ QtObject {
93+ id: d
94+ property var previousStatus: undefined
95+ property real startValue
96+ property real minValue: Direction.isPositive(direction) ? startValue
97+ : startValue - maxTotalDragDistance
98+ property real maxValue: Direction.isPositive(direction) ? startValue + maxTotalDragDistance
99+ : startValue
100+
101+ property var dragParent: dragArea.parent
102+
103+ // The property of DragHandle's parent that will be modified
104+ property string targetProp: {
105+ if (stretch) {
106+ Direction.isHorizontal(direction) ? "width" : "height";
107+ } else {
108+ Direction.isHorizontal(direction) ? "x" : "y";
109+ }
110+ }
111+
112+ function limitMovement(step) {
113+ var targetValue = MathLocal.clamp(dragParent[targetProp] + step, minValue, maxValue);
114+ var step = targetValue - dragParent[targetProp];
115+
116+ if (hintDisplacement == 0) {
117+ return step;
118+ }
119+
120+ // we should not go behind hintingAnimation's current value
121+ if (Direction.isPositive(direction)) {
122+ if (dragParent[targetProp] + step < hintingAnimation.targetValue) {
123+ step = hintingAnimation.targetValue - dragParent[targetProp];
124+ }
125+ } else {
126+ if (dragParent[targetProp] + step > hintingAnimation.targetValue) {
127+ step = hintingAnimation.targetValue - dragParent[targetProp];
128+ }
129+ }
130+
131+ return step;
132+ }
133+
134+ function onFinishedRecognizedGesture() {
135+ if (dragEvaluator.shouldAutoComplete()) {
136+ completeDrag();
137+ } else {
138+ rollbackDrag();
139+ }
140+ }
141+
142+ function completeDrag() {
143+ if (dragParent.shown) {
144+ dragParent.hide();
145+ } else {
146+ dragParent.show();
147+ }
148+ }
149+
150+ function rollbackDrag() {
151+ if (dragParent.shown) {
152+ dragParent.show();
153+ } else {
154+ dragParent.hide();
155+ }
156+ }
157+ }
158+
159+ property alias edgeDragEvaluator: dragEvaluator
160+
161+ EdgeDragEvaluator {
162+ objectName: "edgeDragEvaluator"
163+ id: dragEvaluator
164+ trackedPosition: sceneDistance
165+ maxDragDistance: maxTotalDragDistance
166+ direction: dragArea.direction
167+ }
168+
169+ onDistanceChanged: {
170+ if (status === DirectionalDragArea.Recognized) {
171+ // don't go the whole distance in order to smooth out the movement
172+ var step = distance * 0.3;
173+
174+ step = d.limitMovement(step);
175+
176+ parent[d.targetProp] += step;
177+ }
178+ }
179+
180+ onDraggingChanged: {
181+ if (dragging) {
182+ if (hintDisplacement > 0) {
183+ hintingAnimation.targetValue = d.startValue;
184+ hintingAnimation.start();
185+ }
186+ } else {
187+ hintingAnimation.stop();
188+ }
189+ }
190+
191+ onStatusChanged: {
192+ if (status === DirectionalDragArea.WaitingForTouch) {
193+ if (d.previousStatus === DirectionalDragArea.Recognized) {
194+ d.onFinishedRecognizedGesture();
195+ }
196+ d.startValue = parent[d.targetProp];
197+ }
198+
199+ if (d.previousStatus === DirectionalDragArea.WaitingForTouch ||
200+ d.previousStatus === undefined) {
201+ dragEvaluator.reset();
202+ d.startValue = parent[d.targetProp];
203+ }
204+
205+ d.previousStatus = status;
206+ }
207+
208+}
Components/EdgeDragArea.qmlnew 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+
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
20+
21+/*
22+ A DirectionalDragArea wrapper that provides some well-chosen defaults
23+ for its gesture recognition parameters.
24+*/
25+DirectionalDragArea {
26+
27+ // TODO: Re-evaluate those or even the recognition heuristics itself once
28+ // we have gesture cancelling/forwarding in place.
29+ //
30+ // The idea here is that it's better having lax rules than false negatives.
31+ // False negatives are very frustrating to the user.
32+ maxDeviation: units.gu(3)
33+ wideningAngle: 50
34+ distanceThreshold: units.gu(1.5)
35+ minSpeed: units.gu(0) // some people were getting false negatives with it enabled.
36+}
Components/EdgeDragEvaluator.qmlnew file+88
@@ -0,0 +1,88 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
20+
21+/*
22+ Evaluates end velocity (velocity at the moment the gesture ends) and travelled
23+ distance (delta between finger down and finger up positions) to determine
24+ whether the drag should continue by itself towards completion (auto-complete)
25+ after the finger has left the touchscreen.
26+ */
27+AxisVelocityCalculator {
28+
29+ // How far the drag can go, or should go to achieve completion.
30+ property real maxDragDistance
31+
32+ // Ending a drag at any point before this threshold will need some positive velocity
33+ // (i.e., towards the set direction) to get auto-completion (e.g. to get show()
34+ // called for a hidden Showable) and ending a drag at any point after this
35+ // threshold will need some negative velocity to avoid auto-completion.
36+ property real dragThreshold: maxDragDistance / 2
37+
38+ property real minDragDistance: maxDragDistance * 0.1
39+
40+ // Speed needed to get auto-completion for an hypothetical flick of length zero.
41+ //
42+ // This requirement is gradually reduced as flicks gets longer until it reaches
43+ // a value of zero for flicks of dragThreshold lenght.
44+ //
45+ // in pixels per second
46+ property real speedThreshold: units.gu(70)
47+
48+ property int direction
49+
50+ property real velocity
51+ property real minVelocity
52+
53+ // Returns whether the drag should continue by itself until completed.
54+ function shouldAutoComplete() {
55+ var deltaPos = trackedPosition - __startPosition;
56+ if (Math.abs(deltaPos) < minDragDistance) {
57+ velocity = 0;
58+ minVelocity = 0;
59+ return false;
60+ }
61+
62+ minVelocity = __calculateMinimumVelocityForAutoCompletion(deltaPos);
63+ velocity = calculate();
64+
65+ if (Direction.isPositive(direction) && (velocity >= minVelocity)
66+ || !Direction.isPositive(direction) && (velocity <= minVelocity)) {
67+ return true;
68+ } else {
69+ return false;
70+ }
71+ }
72+
73+ property real __startPosition
74+
75+ // speedThreshold in pixels per millisecond
76+ property real __speedThresholdMs: speedThreshold / 1000.0
77+
78+ // Minimum velocity when a drag total distance is zero
79+ property real __v0: Direction.isPositive(direction) ? __speedThresholdMs : - __speedThresholdMs
80+
81+ function __calculateMinimumVelocityForAutoCompletion(distance) {
82+ return __v0 - ((__speedThresholdMs / dragThreshold) * distance);
83+ }
84+
85+ function reset() {
86+ __startPosition = trackedPosition;
87+ }
88+}
Components/FilterGrid.qml+1−1
@@ -108,7 +108,7 @@ Item {
108108
109109 anchors.fill: parent
110110 radius: "small"
111− borderSource: ItemStyle.style.borderPressed
111+ borderSource: "radius_pressed.sci"
112112 opacity: button.pressed ? 1.0 : 0.0
113113 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
114114 }
Components/ListItems/Base.qml+19−21
@@ -54,35 +54,33 @@ AbstractButton {
5454 */
5555 function __showDivider() {
5656 // if we're not in ListView, always show a thin dividing line at the bottom
57− if (ListView.view !== null) {
58−
59− // if we're last item in ListView don't show divider
60− if (index === ListView.view.model.count - 1) return false;
57+ var model = null;
58+ if (typeof ListViewWithPageHeader !== 'undefined') {
59+ if (typeof ListViewWithPageHeader.model !== 'undefined') {
60+ model = ListViewWithPageHeader.model;
61+ }
62+ } else if (ListView.view !== null) {
63+ model = ListView.view.model;
6164 }
65+ // if we're last item in ListView don't show divider
66+ if (model && index === model.count - 1) return false;
67+
6268 return true;
6369 }
6470
65− property bool __clippingRequired: ListView.view !== null
66− && ListView.view.section.labelPositioning & ViewSection.CurrentLabelAtStart
67−
68− property real __yPositionRelativeToListView: ListView.view ? y - ListView.view.contentY : y
71+ /* Relevant really only for ListViewWithPageHeader case: specify how many pixels we can overlap with the section header */
72+ readonly property int allowedOverlap: units.dp(1)
6973
7074 property real __heightToClip: {
7175 // Check this is in position where clipping is needed
72− if (__clippingRequired && __yPositionRelativeToListView <= __sectionDelegateHeight
73− && __yPositionRelativeToListView > -height) {
74− return Math.min(__sectionDelegateHeight - __yPositionRelativeToListView, height);
75− } else {
76− return 0;
77− }
78− }
79−
80− property int __sectionDelegateHeight: {
81− if (__clippingRequired && ListView.view.hasOwnProperty("__sectionDelegateHeight")) {
82− return ListView.view.__sectionDelegateHeight;
83− } else {
84− return 0;
76+ if (typeof ListViewWithPageHeader !== 'undefined') {
77+ if (typeof heightToClip !== 'undefined') {
78+ if (heightToClip >= allowedOverlap) {
79+ return heightToClip - allowedOverlap;
80+ }
81+ }
8582 }
83+ return 0;
8684 }
8785
8886 /*!
Components/ListItems/Header.qml−6
@@ -25,12 +25,6 @@ Item {
2525 */
2626 property alias text: label.text
2727
28− /* When this header is used in a ListViewWithPageHeader with CurrentLabelAtStart mode, to stop
29− the list's delegates contents being visible through this header, they clip themselves
30− depending on their position. However to allow delegates underlap the bottom X pixels of this
31− header (so delegate appears through ThinDivider say) we set an offset property here. */
32− readonly property int bottomBorderAllowedOverlap: bottomBorder.allowedBottomOverlap
33−
3428 height: units.gu(4.5)
3529
3630 Item {
Components/ListItems/ThinDivider.qml−4
@@ -23,9 +23,5 @@ Image {
2323 }
2424 height: (visible) ? units.dp(2) : 0
2525
26− /* Relevant really only for ListViewWithPageHeader with Base delegates: should this image
27− be overlapping content, specify how many pixels from the bottom should be transparent */
28− readonly property int allowedBottomOverlap: units.dp(1)
29−
3026 source: "graphics/ListItemDividerHorizontal.png"
3127}
Components/ListViewWithPageHeader.qmldeleted−189
@@ -1,189 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import "Math.js" as MathLocal
19−
20−Item {
21− id: root
22− property Item pageHeader: null
23− property Component sectionDelegate: null
24− property string sectionProperty: ""
25− property alias model: listView.model
26− property alias delegate: listView.delegate
27− property ListView view: listView
28− property alias moving: flicker.moving
29− property alias atYEnd: flicker.atYEnd
30− property bool clipListView: true
31−
32− readonly property real __headerHeight: (pageHeader) ? pageHeader.implicitHeight : 0
33− property real __headerVisibleHeight: __headerHeight
34− readonly property real __overshootHeight: (flicker.contentY < 0) ? -flicker.contentY : 0
35−
36−
37− // TODO move to AnimationController
38− ParallelAnimation {
39− id: headerAnimation
40− property real targetContentY
41− NumberAnimation {
42− target: root
43− property: "__headerVisibleHeight"
44− to: root.__headerHeight
45− duration: 200
46− easing.type: Easing.OutQuad
47− }
48− NumberAnimation {
49− target: listView
50− property: "contentY"
51− to: headerAnimation.targetContentY
52− duration: 200
53− easing.type: Easing.OutQuad
54− }
55− }
56−
57− function positionAtBeginning() {
58− __headerVisibleHeight = __headerHeight
59− flicker.contentY = 0
60− }
61−
62− function showHeader() {
63− headerAnimation.targetContentY = listView.contentY + (__headerHeight - __headerVisibleHeight)
64− headerAnimation.start()
65− }
66−
67− function flick(xVelocity, yVelocity) {
68− flicker.flick(xVelocity, yVelocity);
69− }
70−
71− onPageHeaderChanged: {
72− pageHeader.parent = pageHeaderContainer;
73− pageHeader.anchors.fill = pageHeaderContainer;
74− }
75−
76− Item {
77− id: pageHeaderClipper
78− parent: flicker // parent to Flickable so mouse click events passed through to the header component
79− anchors {
80− top: parent.top
81− left: parent.left
82− right: parent.right
83− }
84− height: __headerVisibleHeight + __overshootHeight
85−
86− Item {
87− id: pageHeaderContainer
88− anchors {
89− left: parent.left
90− right: parent.right
91− bottom: parent.bottom
92− }
93− height: __headerHeight + __overshootHeight
94− }
95− }
96−
97− ListView {
98− id: listView
99− parent: flicker // parent to Flickable so mouse click events passed through to List delegates
100− anchors {
101− left: parent.left
102− right: parent.right
103− top: parent.top
104− topMargin: __headerVisibleHeight
105− }
106− height: root.height
107−
108− // FIXME scrolling workaround, see below
109− cacheBuffer: height*10
110−
111− section.property: sectionProperty
112− section.criteria: ViewSection.FullString
113− section.labelPositioning: ViewSection.InlineLabels | ViewSection.CurrentLabelAtStart
114− section.delegate: sectionDelegate
115−
116− interactive: false
117− clip: root.clipListView
118−
119− property int __sectionDelegateHeight: __getHeight(section.delegate)
120− function __getHeight(component) {
121− // want height (minus allowed overlap) of the section delegate as is needed for clipping
122− if (component === null) return 0;
123− var object = component.createObject(); //FIXME: throws 'section' not defined error
124− var value = object.height - object.bottomBorderAllowedOverlap;
125− object.destroy();
126− return value;
127− }
128−
129− property real previousOriginY: 0
130− onOriginYChanged: {
131− var deltaOriginY = originY - previousOriginY;
132− previousOriginY = originY;
133− /* When originY changes, it causes the top of the flicker and the top of the list to fall
134− out of sync - and thus the contentY positioning will be broken. To correct for this we
135− manually change the flickable's contentY here */
136− flicker.contentY -= deltaOriginY;
137− }
138−
139− /* For case when list content greater than container height and list scrolled down so header
140− hidden. If content shrinks to be smaller than the container height, we want the header to
141− re-appear */
142− property real __previousContentHeight: 0
143− onContentHeightChanged: {
144− var deltaContentHeight = contentHeight - __previousContentHeight;
145− __previousContentHeight = contentHeight;
146− if (contentHeight < height && deltaContentHeight < 0 && __headerVisibleHeight < height - contentHeight) {
147− __headerVisibleHeight = Math.min(height - contentHeight, __headerHeight);
148− }
149− }
150− }
151−
152− Flickable {
153− id: flicker
154− anchors.fill: parent
155− contentHeight: listView.contentHeight + __headerHeight
156− maximumFlickVelocity: height * 10
157− flickDeceleration: height * 2
158− onContentYChanged: {
159− var deltaContentY = contentY - __previousContentY;
160− __previousContentY = contentY;
161−
162− // first decide if movement will prompt the page header to change height
163− if ((deltaContentY < 0 && __headerVisibleHeight >= 0) ||
164− (deltaContentY > 0 && __headerVisibleHeight <= __headerHeight)) {
165−
166− // calculate header height - but prevent bounce from changing it
167− if (contentY > 0 && contentY < contentHeight - height) {
168− __headerVisibleHeight = MathLocal.clamp(__headerVisibleHeight - deltaContentY, 0, __headerHeight);
169− }
170− }
171−
172− // now we move list position, taking into account page header height
173−
174− // BUG: With section headers enabled, the values of originY and contentY appear not
175− // correct at the exact point originY changes. originY changes when the ListView
176− // deletes/creates hidden delegates which are above the visible delegates.
177− // As a result of this bug, you experience jittering scrolling when rapidly moving
178− // around in large lists. See https://bugreports.qt-project.org/browse/QTBUG-27997
179− // A workaround is to use a large enough cacheBuffer to prevent deletions/creations
180− // so effectively originY is always zero.
181− var newContentY = flicker.contentY + listView.originY - __headerHeight + __headerVisibleHeight
182− if (newContentY < listView.contentHeight) {
183− listView.contentY = newContentY;
184− }
185− }
186−
187− property real __previousContentY: 0
188− }
189−}
Components/PageHeader.qml+2−2
@@ -149,7 +149,7 @@ Item {
149149
150150 primaryItem: Button {
151151 enabled: searchField.text != ""
152− ItemStyle.class: "transparent-button"
152+ color: "transparent"
153153 onClicked: {
154154 if (searchField.text != "") {
155155 searchHistory.addQuery(searchField.text)
@@ -272,7 +272,7 @@ Item {
272272 // FIXME: this should go into the first item below, but enable: false
273273 // prevents mouse events propagation
274274 Button {
275− ItemStyle.class: "transparent-button"
275+ color: "transparent"
276276 anchors {
277277 top: parent.top
278278 right: parent.right
Components/Stage.qml+8−10
@@ -416,12 +416,14 @@ Showable {
416416 }
417417 }
418418
419− AxisVelocityCalculator {
420− id: dragVelocityCalculator
421− trackedPosition: rightEdgeDraggingArea.distance
419+ EdgeDragEvaluator {
420+ id: dragEvaluator
421+ trackedPosition: rightEdgeDraggingArea.touchX
422+ direction: rightEdgeDraggingArea.direction
423+ maxDragDistance: stage.width
422424 }
423425
424− DirectionalDragArea {
426+ EdgeDragArea {
425427 id: rightEdgeDraggingArea
426428
427429 enabled: {
@@ -439,10 +441,6 @@ Showable {
439441 anchors.right: parent.right
440442
441443 direction: Direction.Leftwards
442− maxDeviation: units.gu(1)
443− wideningAngle: 20
444− distanceThreshold: units.gu(3)
445− minSpeed: units.gu(5)
446444
447445 onDistanceChanged: {
448446 if (status !== DirectionalDragArea.Recognized)
@@ -478,7 +476,7 @@ Showable {
478476 }
479477
480478 function onUndecided() {
481− dragVelocityCalculator.reset()
479+ dragEvaluator.reset();
482480
483481 var nextApplication = null;
484482 if (stage.applications.count > 1) {
@@ -491,7 +489,7 @@ Showable {
491489 }
492490
493491 function onGestureEnded() {
494− if (stage.applications.count > 1 && dragVelocityCalculator.calculate() < 0) {
492+ if (stage.applications.count > 1 && dragEvaluator.shouldAutoComplete()) {
495493 switchToApplicationAnimationController.completeToEndWithSignal();
496494 } else {
497495 switchToApplicationAnimationController.completeToBeginningWithSignal();
Components/Tile.qml+1−1
@@ -51,7 +51,7 @@ AbstractButton {
5151
5252 anchors.fill: icon
5353 radius: "medium"
54− borderSource: ItemStyle.style.borderPressed
54+ borderSource: "radius_pressed.sci"
5555 opacity: root.pressed ? 1.0 : 0.0
5656 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
5757 }
Components/UbuntuShapeForItem.qml+12−56
@@ -15,7 +15,7 @@
1515 */
1616
1717import QtQuick 2.0
18−import Ubuntu.Components 0.1 as Theming
18+import Ubuntu.Components 0.1
1919
2020/* FIXME: This component is duplicating the UbuntuShape from the SDK, but shapes more
2121 * general (Item-based) components. This ability should be incorporated into the SDK's
@@ -24,66 +24,22 @@ import Ubuntu.Components 0.1 as Theming
2424 */
2525
2626Item {
27− id: shape
27+ id: root
2828
29− Theming.ItemStyle.class: "UbuntuShape-radius-" + radius
29+ property alias radius: shape.radius
30+ property alias image: source.sourceItem
3031
31− property string radius: "small"
32− property url maskSource: Theming.ComponentUtils.style(shape, "maskSource", "")
33− property url borderSource: Theming.ComponentUtils.style(shape, "borderIdle", "")
34− property Item image
35−
36− implicitWidth: units.gu(8)
37− implicitHeight: units.gu(8)
38−
39− onWidthChanged: __updateImageDimensions()
40− onHeightChanged: __updateImageDimensions()
41− onImageChanged: __updateImageDimensions()
42−
43− function __updateImageDimensions() {
44− if (!image) return;
45− image.width = shape.width;
46− image.height = shape.height;
47− image.visible = false;
48− }
49−
50− ShaderEffect {
51− anchors.fill: parent
52− visible: shape.image
53−
54− property ShaderEffectSource mask: ShaderEffectSource {
55− sourceItem: BorderImage {
56− width: shape.width
57− height: shape.height
58− source: shape.maskSource
59− visible: false
60− }
61− }
62−
63− property ShaderEffectSource image: ShaderEffectSource {
64− sourceItem: shape.image
65− }
66−
67− fragmentShader:
68− "
69− varying highp vec2 qt_TexCoord0;
70− uniform lowp float qt_Opacity;
71− uniform sampler2D mask;
72− uniform sampler2D image;
73−
74− void main(void)
75− {
76− lowp vec4 maskColor = texture2D(mask, qt_TexCoord0.st);
77− lowp vec4 imageColor = texture2D(image, qt_TexCoord0.st);
78− gl_FragColor = imageColor * maskColor.a * qt_Opacity;
79− }
80− "
32+ ShaderEffectSource {
33+ id: source
34+ width: 1
35+ height: 1
36+ hideSource: true
8137 }
8238
83− BorderImage {
84− id: border
39+ Shape {
40+ id: shape
41+ image: source
8542
8643 anchors.fill: parent
87− source: shape.borderSource
8844 }
8945}
Components/WrongPasswordAnimation.qml+3−3
@@ -26,14 +26,14 @@ SequentialAnimation {
2626 property: "anchors.horizontalCenterOffset"
2727 duration: 50
2828 easing.type: Easing.InQuad
29− to: units.gu(2)
29+ to: units.gu(1)
3030 }
3131 NumberAnimation {
3232 target: root.target
3333 property: "anchors.horizontalCenterOffset"
3434 duration: 100
3535 easing.type: Easing.InOutQuad
36− to: -units.gu(2)
36+ to: -units.gu(1)
3737 }
3838 NumberAnimation {
3939 target: root.target
@@ -41,6 +41,6 @@ SequentialAnimation {
4141 properties: "anchors.horizontalCenterOffset"
4242 to: 0
4343 duration: 400
44− easing.overshoot: units.gu(2)
44+ easing.overshoot: units.gu(1)
4545 }
4646}
Dash/Apps/RunningApplicationTile.qml+1−1
@@ -87,7 +87,7 @@ AbstractButton {
8787
8888 anchors.fill: shapedApplicationImage
8989 radius: "medium"
90− borderSource: ItemStyle.style.borderPressed
90+ borderSource: "radius_pressed.sci"
9191 opacity: root.pressed ? 1.0 : 0.0
9292 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
9393 }
Dash/DashApps.qml+2−3
@@ -99,7 +99,7 @@ ScopeView {
9999 When using Loader to load external QML file in the list deelgate, the ListView has
100100 a bug where it can position the delegate content to overlap the section header
101101 of the ListView - a workaround is to use sourceComponent of Loader instead */
102− Component { id: runningApplicationsGrid; RunningApplicationsGrid {} }
102+ Component { id: runningApplicationsGrid; RunningApplicationsGrid { clip: true } }
103103 Component {
104104 id: applicationsFilterGrid;
105105 ApplicationsFilterGrid {
@@ -112,7 +112,7 @@ ScopeView {
112112 "ApplicationsFilterGrid": applicationsFilterGrid,
113113 }
114114
115− ListViewWithPageHeader {
115+ ScopeListView {
116116 id: categoryView
117117 anchors.fill: parent
118118 model: SortFilterProxyModel {
@@ -150,7 +150,6 @@ ScopeView {
150150 item.model = categoryModels[modelName]
151151 }
152152 }
153− asynchronous: true
154153 }
155154
156155 ListView.onRemove: SequentialAnimation {
Dash/DashHome.qml+1−2
@@ -130,7 +130,7 @@ ScopeView {
130130 "VideosGrid": videosGrid,
131131 }
132132
133− ListViewWithPageHeader {
133+ ScopeListView {
134134 id: listView
135135 anchors.fill: parent
136136 model: categoryListModel
@@ -161,7 +161,6 @@ ScopeView {
161161 item.clicked.connect(playVideo);
162162 }
163163 }
164− asynchronous: true
165164 }
166165 }
167166
Dash/DashMusic.qml+1−2
@@ -64,7 +64,7 @@ ScopeView {
6464 }
6565 }
6666
67− ListViewWithPageHeader {
67+ ScopeListView {
6868 id: categoryView
6969 anchors.fill: parent
7070 model: scopeView.categories
@@ -84,7 +84,6 @@ ScopeView {
8484 onLoaded: {
8585 item.model = results
8686 }
87− asynchronous: true
8887 }
8988 }
9089
Dash/DashVideos.qml+2−3
@@ -97,11 +97,11 @@ ScopeView {
9797 }
9898 }
9999
100− ListViewWithPageHeader {
100+ ScopeListView {
101101 id: categoryView
102102 anchors.fill: parent
103103 model: scopeView.categories
104− clipListView: !previewLoader.onScreen
104+ forceNoClip: previewLoader.onScreen
105105
106106 onAtYEndChanged: if (atYEnd) endReached()
107107 onMovingChanged: if (moving && atYEnd) endReached()
@@ -119,7 +119,6 @@ ScopeView {
119119 onLoaded: {
120120 item.model = results
121121 }
122− asynchronous: true
123122
124123 Connections {
125124 target: loader.item
Dash/GenericScopeView.qml+1−1
@@ -43,7 +43,7 @@ ScopeView {
4343 }
4444 }
4545
46− ListViewWithPageHeader {
46+ ScopeListView {
4747 id: categoryView
4848 anchors.fill: parent
4949 model: scopeView.categories
Dash/Music/AlbumTile.qml+1−1
@@ -45,7 +45,7 @@ AbstractButton {
4545
4646 anchors.fill: icon
4747 radius: "medium"
48− borderSource: ItemStyle.style.borderPressed
48+ borderSource: "radius_pressed.sci"
4949 opacity: root.pressed ? 1.0 : 0.0
5050 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
5151 }
Dash/ScopeListView.qmlnew file+23
@@ -0,0 +1,23 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import ListViewWithPageHeader 0.1
19+
20+ListViewWithPageHeader {
21+ maximumFlickVelocity: height * 10
22+ flickDeceleration: height * 2
23+}
Greeter/Greeter.qml+28−2
@@ -16,14 +16,23 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
1920import LightDM 0.1 as LightDM
2021import "../Components"
22+import "../Components/Math.js" as MathLocal
2123
2224Showable {
2325 id: greeter
2426 enabled: shown
2527 created: greeterContentLoader.status == Loader.Ready && greeterContentLoader.item.ready
2628
29+ // 1 when fully shown and 0 when fully hidden
30+ property real showProgress: MathLocal.clamp((width + x) / width, 0, 1)
31+
32+ showAnimation: StandardAnimation { property: "x"; to: 0 }
33+ hideAnimation: StandardAnimation { property: "x"; to: -width }
34+
35+ property alias dragHandleWidth: dragHandle.width
2736 property alias model: greeterContentLoader.model
2837 property bool locked: shown && multiUser && !greeterContentLoader.promptless
2938
@@ -39,7 +48,7 @@ Showable {
3948 signal unlocked(int uid)
4049
4150 onRightTeaserPressedChanged: {
42− if (rightTeaserPressed) {
51+ if (rightTeaserPressed && !locked) {
4352 teasingTimer.start();
4453 }
4554 }
@@ -72,7 +81,7 @@ Showable {
7281 states: [
7382 State {
7483 name: "teasing"
75− when: greeter.rightTeaserPressed || teasingTimer.running
84+ when: teasingTimer.running
7685 PropertyChanges {
7786 target: greeter
7887 x: -units.gu(2)
@@ -91,4 +100,21 @@ Showable {
91100 }
92101 }
93102 ]
103+
104+ DragHandle {
105+ id: dragHandle
106+
107+ anchors.top: parent.top
108+ anchors.bottom: parent.bottom
109+ anchors.right: parent.right
110+
111+ // no need for requiring a directional drag since we are covering the screen
112+ // anyway (i.e., no change user could be trying to interact with some other
113+ // UI element)
114+ distanceThreshold: 0
115+
116+ enabled: !greeter.locked
117+
118+ direction: Direction.Leftwards
119+ }
94120}
Greeter/GreeterContent.qml+3−1
@@ -80,7 +80,9 @@ MouseArea {
8080 source: greeter.narrowMode ? "" : "LoginList.qml"
8181
8282 onLoaded: {
83− item.currentIndex = greeterContentLoader.currentIndex
83+ item.currentIndex = greeterContentLoader.currentIndex;
84+ selected(item.currentIndex);
85+ item.resetAuthentication();
8486 }
8587
8688 Binding {
Greeter/LoginList.qml−8
@@ -66,14 +66,6 @@ Item {
6666
6767 readonly property bool movingInternally: moveTimer.running || userList.moving
6868
69− onCountChanged: {
70− // Start authentication when we start up
71− if (!LightDM.Greeter.authenticationUser && userList.currentItem) {
72− root.selected(userList.currentIndex);
73− root.resetAuthentication();
74− }
75− }
76−
7769 onCurrentIndexChanged: {
7870 if (LightDM.Greeter.authenticationUser != userList.model.data(currentIndex, LightDM.UserRoles.NameRole)) {
7971 root.resetAuthentication();
Hud/SearchBar.qml−7
@@ -55,13 +55,6 @@ Item {
5555 }
5656 }
5757
58− // Don't let the style play with our opacity
59− Binding {
60− target: searchBar.ItemStyle.style
61− property: "opacity"
62− value: 1
63− }
64−
6558 Item {
6659 id: primary
6760 height: searchBar.height
Hud/ToolBarIcon.qml+1−1
@@ -18,7 +18,7 @@ import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919
2020Button {
21− ItemStyle.class: "transparent-button"
21+ color: "transparent"
2222
2323 property alias source: image.source
2424
Launcher/Launcher.qml+9−17
@@ -25,7 +25,6 @@ Item {
2525
2626 property bool available: true // can be used to disable all interactions
2727
28− property bool teasing: false
2928 property int panelWidth: units.gu(8.5)
3029 property int dragAreaWidth: units.gu(1)
3130 property real progress: dragArea.dragging && dragArea.touchX > panel.width ? dragArea.touchX : 0
@@ -50,7 +49,7 @@ Item {
5049 }
5150
5251 function hide() {
53− state = ""
52+ switchToNextState("")
5453 }
5554
5655 function switchToNextState(state) {
@@ -58,8 +57,8 @@ Item {
5857 animateTimer.start();
5958 }
6059
61− onTeasingChanged: {
62− if (teasing) {
60+ function tease() {
61+ if (available) {
6362 teaseTimer.start();
6463 }
6564 }
@@ -181,18 +180,11 @@ Item {
181180 }
182181 }
183182
184− DirectionalDragArea {
183+ EdgeDragArea {
185184 id: dragArea
186185
187186 direction: Direction.Rightwards
188187
189− // values to be tweaked and later removed from here and set in stone as defaults
190− // once we are confident it's all good.
191− maxDeviation: units.gu(1)
192− wideningAngle: 30
193− distanceThreshold: units.gu(3)
194− minSpeed: units.gu(5)
195−
196188 enabled: root.available && root.state !== "visible"
197189 width: root.dragAreaWidth
198190 height: root.height
@@ -215,11 +207,11 @@ Item {
215207
216208 onDraggingChanged: {
217209 if (!dragging) {
218− if (distance > root.width / 2) {
219− root.dash()
220− root.switchToNextState("")
221− } else if (distance > panel.width/2) {
210+ if (distance > panel.width / 2) {
222211 root.switchToNextState("visible")
212+ if (distance > panel.width * 2) {
213+ root.dash()
214+ }
223215 } else {
224216 root.switchToNextState("")
225217 }
@@ -244,7 +236,7 @@ Item {
244236 },
245237 State {
246238 name: "teasing"
247− when: root.teasing || teaseTimer.running
239+ when: teaseTimer.running
248240 PropertyChanges {
249241 target: panel
250242 x: -root.panelWidth + units.gu(2)
Launcher/LauncherDelegate.qml+202−39
@@ -25,6 +25,8 @@ Item {
2525 property real angle: 0
2626 property bool highlighted: false
2727 property real offset: 0
28+ property alias brightness: transformEffect.brightness
29+ property real itemOpacity: 1
2830
2931 property real maxAngle: 0
3032 property bool inverted: false
@@ -32,74 +34,237 @@ Item {
3234 readonly property int effectiveHeight: Math.cos(angle * Math.PI / 180) * height
3335 readonly property real foldedHeight: Math.cos(maxAngle * Math.PI / 180) * height
3436
35− property int itemsBeforeThis: 0
36− property int itemsAfterThis: 0
37−
3837 property bool dragging:false
3938
4039 signal clicked()
4140 signal longtap()
4241 signal released()
4342
44− UbuntuShape {
43+ Item {
4544 id: iconItem
46− color: Qt.rgba(0, 0, 1, 0.5)
4745 width: parent.width
4846 height: parent.height
4947 anchors.centerIn: parent
50− anchors.verticalCenterOffset: root.offset + (height - root.effectiveHeight)/2 * (angle < 0 ? -1 : 1)
51− rotation: root.inverted ? 180 : 0
52− radius: "medium"
53−
54− transform: Rotation {
55− axis { x: 1; y: 0; z: 0 }
56− origin { x: iconItem.width / 2; y: iconItem.height / 2; z: 0 }
57− angle: root.angle
58− }
59−
60− image: Image {
61− source: "../graphics/applicationIcons/" + root.iconName + ".png"
62− }
6348
64− MouseArea {
65− id: mouseArea
49+ UbuntuShape {
50+ id: iconShape
6651 anchors.fill: parent
67− onClicked: root.clicked()
68− onCanceled: root.released()
69− preventStealing: false
52+ anchors.margins: units.gu(0.5)
53+ radius: "medium"
7054
71− onPressAndHold: {
72− root.state = "moving"
55+ image: Image {
56+ id: iconImage
57+ sourceSize.width: iconShape.width
58+ sourceSize.height: iconShape.height
59+ source: "../graphics/applicationIcons/" + root.iconName + ".png"
7360 }
74− onReleased: {
75− root.state = "docked"
61+
62+ MouseArea {
63+ id: mouseArea
64+ anchors.fill: parent
65+ onClicked: root.clicked()
66+ onCanceled: root.released()
67+ preventStealing: false
68+ enabled: root.angle < 5
69+
70+ onPressAndHold: {
71+ root.state = "moving"
72+ }
73+ onReleased: {
74+ root.state = "docked"
75+ }
7676 }
7777 }
78−
7978 BorderImage {
8079 id: overlayHighlight
8180 anchors.centerIn: iconItem
8281 rotation: inverted ? 180 : 0
83− source: root.highlighted || mouseArea.pressed ? "graphics/selected.sci" : "graphics/non-selected.sci"
84− width: iconItem.width + units.gu(1.5)
82+ source: isSelected ? "graphics/selected.sci" : "graphics/non-selected.sci"
83+ width: root.width + units.gu(0.5)
8584 height: width
85+ property bool isSelected: root.highlighted || mouseArea.pressed
86+ onIsSelectedChanged: shaderEffectSource.scheduleUpdate();
8687 }
8788 }
8889
90+ ShaderEffect {
91+ id: transformEffect
92+ anchors.centerIn: parent
93+ anchors.verticalCenterOffset: root.offset
94+ width: parent.width
95+ height: parent.height
96+ property real itemOpacity: root.itemOpacity
97+ property real brightness: 0
98+ property real angle: root.angle
99+ rotation: root.inverted ? 180 : 0
100+
101+
102+ property variant source: ShaderEffectSource {
103+ id: shaderEffectSource
104+ sourceItem: iconItem
105+ hideSource: true
106+ live: false
107+ }
108+
109+ transform: [
110+ // Rotating 3 times at top/bottom because that increases the perspective.
111+ // This is a hack, but as QML does not support real 3D coordinates
112+ // getting a higher perspective can only be done by a hack. This is the most
113+ // readable/understandable one I could come up with.
114+ Rotation {
115+ axis { x: 1; y: 0; z: 0 }
116+ origin { x: iconItem.width / 2; y: angle > 0 ? 0 : iconItem.height; z: 0 }
117+ angle: root.angle * 0.7
118+ },
119+ Rotation {
120+ axis { x: 1; y: 0; z: 0 }
121+ origin { x: iconItem.width / 2; y: angle > 0 ? 0 : iconItem.height; z: 0 }
122+ angle: root.angle * 0.7
123+ },
124+ Rotation {
125+ axis { x: 1; y: 0; z: 0 }
126+ origin { x: iconItem.width / 2; y: angle > 0 ? 0 : iconItem.height; z: 0 }
127+ angle: root.angle * 0.7
128+ },
129+ // Because rotating it 3 times moves it more to the front/back, i.e. it gets
130+ // bigger/smaller and we need a scale to compensate that again.
131+ Scale {
132+ xScale: 1 - (Math.abs(angle) / 500)
133+ yScale: 1 - (Math.abs(angle) / 500)
134+ origin { x: iconItem.width / 2; y: iconItem.height / 2}
135+ }
136+ ]
137+
138+ // Using a fragment shader instead of QML's opacity and BrightnessContrast
139+ // to be able to do both in one step which gives quite some better performance
140+ fragmentShader: "
141+ varying highp vec2 qt_TexCoord0;
142+ uniform sampler2D source;
143+ uniform lowp float brightness;
144+ uniform lowp float itemOpacity;
145+ void main(void)
146+ {
147+ highp vec4 sourceColor = texture2D(source, qt_TexCoord0);
148+ sourceColor.rgb = mix(sourceColor.rgb, vec3(step(0.0, brightness)), abs(brightness));
149+ sourceColor *= itemOpacity;
150+ gl_FragColor = sourceColor;
151+ }"
152+ }
153+
154+ QtObject {
155+ id: priv
156+
157+ property ListView listView: root.ListView.view
158+ property real totalUnfoldedHeight: listView.itemSize + listView.spacing
159+ property real totalEffectiveHeight: effectiveHeight + listView.spacing
160+ property real effectiveContentY: listView.contentY - listView.originY
161+ property real effectiveY: y - listView.originY
162+ property real distanceFromTopEdge: -(effectiveContentY + listView.topMargin - index*totalUnfoldedHeight)
163+ property real distanceFromBottomEdge: listView.height - listView.bottomMargin - (effectiveY+height) + effectiveContentY
164+
165+ property real distanceFromEdge: Math.abs(distanceFromBottomEdge) < Math.abs(distanceFromTopEdge) ? distanceFromBottomEdge : distanceFromTopEdge
166+ property real orientationFlag: Math.abs(distanceFromBottomEdge) < Math.abs(distanceFromTopEdge) ? -1 : 1
167+
168+ property real overlapWithFoldingArea: listView.foldingAreaHeight - distanceFromEdge
169+ }
170+
89171 states: [
90172 State {
91173 name: "docked"
92174 PropertyChanges {
93175 target: root
94− offset: if (launcherFlickable.contentY > itemsBeforeThis * (foldedHeight + launcherColumn.spacing*2)) {
95− return launcherFlickable.contentY - (index * (foldedHeight + launcherColumn.spacing*2));
96− } else if (y + height - launcherFlickable.contentY > launcherFlickable.height - (itemsAfterThis*(foldedHeight - launcherColumn.spacing))) {
97− return launcherFlickable.height - (y+height) + launcherFlickable.contentY - (itemsAfterThis*(foldedHeight - launcherColumn.spacing));
98− } else {
99− return 0;
176+
177+ // This is the offset that keeps the items inside the panel
178+ offset: {
179+ // First/last items are special
180+ if (index == 0 || index == priv.listView.count-1) {
181+ // Just keep them bound to the edges in case they're outside of the visible area
182+ if (priv.distanceFromEdge < 0) {
183+ return (-priv.distanceFromEdge - (height - effectiveHeight)) * priv.orientationFlag;
184+ }
185+ return 0;
186+ }
187+
188+ // Are we already completely outside the flickable? Stop the icon here.
189+ if (priv.distanceFromEdge < -priv.totalUnfoldedHeight) {
190+ return (-priv.distanceFromEdge - (root.height - effectiveHeight)) * priv.orientationFlag;
191+ }
192+
193+ // We're touching the edge, move slower than the actual flicking speed.
194+ if (priv.distanceFromEdge < 0) {
195+ return (Math.abs(priv.distanceFromEdge) * priv.totalEffectiveHeight / priv.totalUnfoldedHeight) * priv.orientationFlag
196+ }
197+ return 0;
198+ }
199+
200+ // The angle used for rotating
201+ angle: {
202+ // First/last items are special
203+ if (index == 0 || index == priv.listView.count-1) {
204+ if (priv.distanceFromEdge < 0) {
205+ // proportion equation: distanceFromTopEdge : angle = totalUnfoldedHeight/2 : maxAngle
206+ return Math.max(-maxAngle, priv.distanceFromEdge * maxAngle / (priv.listView.foldingAreaHeight)) * priv.orientationFlag
100207 }
101− angle: -Math.min(Math.max(offset * maxAngle / foldedHeight, -maxAngle), maxAngle)
208+ return 0; // Don't fold first/last item as long as inside the view
209+ }
102210
211+ // Are we in the already completely outside the flickable? Fold for the last 5 degrees
212+ if (priv.distanceFromEdge < 0) {
213+ // proportion equation: -distanceFromTopEdge : angle = totalUnfoldedHeight : 5
214+ return Math.max(-maxAngle, (priv.distanceFromEdge * 5 / priv.listView.foldingAreaHeight) - (maxAngle-5)) * priv.orientationFlag
215+ }
216+
217+ // We are overlapping with the folding area, fold the icon to maxAngle - 5 degrees
218+ if (priv.overlapWithFoldingArea > 0) {
219+ // proportion equation: overlap: totalHeight = angle : (maxAngle - 5)
220+ return -priv.overlapWithFoldingArea * (maxAngle -5) / priv.listView.foldingAreaHeight * priv.orientationFlag;
221+ }
222+ return 0;
223+ }
224+
225+ itemOpacity: {
226+ // First/last items are special
227+ if (index == 0 || index == priv.listView.count-1) {
228+ if (priv.distanceFromEdge < 0) {
229+ // Fade from 1 to 0 in the distance of 3 * foldingAreaHeight (which is when the next item reaches the edge)
230+ return 1.0 - (-priv.distanceFromEdge / (priv.listView.foldingAreaHeight * 3))
231+ }
232+ return 1; // Don't make first/last item transparent as long as inside the view
233+ }
234+
235+ // Are we already completely outside the flickable? Fade from 0.75 to 0 in 2 items height
236+ if (priv.distanceFromEdge < 0) {
237+ // proportion equation: -distanceFromEdge : 1-opacity = totalUnfoldedHeight : 0.75
238+ return 0.75 - (-priv.distanceFromEdge * 0.75 / (priv.totalUnfoldedHeight*2))
239+ }
240+
241+ // We are overlapping with the folding area, fade out to 0.75
242+ if (priv.overlapWithFoldingArea > 0) {
243+ // proportion equation: overlap : totalHeight = 1-opacity : 0.25
244+ return 1 - (priv.overlapWithFoldingArea * 0.25 / priv.listView.foldingAreaHeight)
245+ }
246+ return 1;
247+ }
248+
249+ brightness: {
250+ // First/last items are special
251+ if (index == 0 || index == priv.listView.count-1) {
252+ if (priv.distanceFromEdge < 0) {
253+ return -(-priv.distanceFromEdge / (priv.listView.foldingAreaHeight * 3))
254+ }
255+ return 0;
256+ }
257+ // Are we already completely outside the flickable? Fade from 0.7 to 0 in 2 items height
258+ if (priv.distanceFromEdge < 0) {
259+ return -0.3 - (-priv.distanceFromEdge * 0.1 / (priv.totalUnfoldedHeight*2))
260+ }
261+
262+ // We are overlapping with the folding area, fade out to 0.7
263+ if (priv.overlapWithFoldingArea > 0) {
264+ return - (priv.overlapWithFoldingArea * 0.3 / priv.listView.foldingAreaHeight)
265+ }
266+ return 0;
267+ }
103268 }
104269 },
105270
@@ -121,7 +286,5 @@ Item {
121286 drag.target: root
122287 }
123288 }
124−
125289 ]
126−
127290}
Launcher/LauncherPanel.qml+106−52
@@ -17,6 +17,7 @@
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Unity 0.1
20+import "../Components/ListItems"
2021
2122Item {
2223 id: root
@@ -26,7 +27,7 @@ Item {
2627 property var model
2728 property bool inverted: true
2829 property bool dragging: false
29− property bool moving: launcherFlickable.moving
30+ property bool moving: launcherListView.moving || launcherListView.flicking
3031 property int dragPosition: 0
3132 property int highlightIndex: -1
3233
@@ -34,23 +35,23 @@ Item {
3435 signal dashItemSelected(int index)
3536
3637 onDragPositionChanged: {
37− var effectiveDragPosition = root.inverted ? launcherFlickable.height - dragPosition : dragPosition - mainColumn.anchors.margins
38+ var effectiveDragPosition = root.inverted ? launcherListView.height - dragPosition : dragPosition - mainColumn.anchors.margins
3839
39− var hiddenContentHeight = launcherFlickable.contentHeight - launcherFlickable.height
40+ var hiddenContentHeight = launcherListView.contentHeight - launcherListView.height
4041 // Shortening scrollable height because the first/last item needs to be fully expanded before reaching the top/bottom
41− var scrollableHeight = launcherFlickable.height - (launcherFlickable.itemSize + launcherColumn.spacing) *2
42+ var scrollableHeight = launcherListView.height - (launcherListView.itemSize + launcherColumn.spacing) *2
4243 // As we shortened the scrollableHeight, lets move everything down by the itemSize
43− var shortenedEffectiveDragPosition = effectiveDragPosition - launcherFlickable.itemSize - launcherColumn.spacing
44+ var shortenedEffectiveDragPosition = effectiveDragPosition - launcherListView.itemSize - launcherColumn.spacing
4445 var newContentY = shortenedEffectiveDragPosition * hiddenContentHeight / scrollableHeight
4546
4647 // limit top/bottom to prevent overshooting
47− launcherFlickable.contentY = Math.min(hiddenContentHeight, Math.max(0, newContentY));
48+ launcherListView.contentY = Math.min(hiddenContentHeight, Math.max(0, newContentY));
4849
4950 // Now calculate the current index:
5051 // > the current mouse position + the hidden/scolled content on top is the mouse position in the averall view
5152 // > adjust that removing all the margins
5253 // > divide by itemSize to get index
53− highlightIndex = (effectiveDragPosition + launcherFlickable.contentY - mainColumn.anchors.margins*3 - launcherColumn.spacing/2) / (launcherFlickable.itemSize + launcherColumn.spacing)
54+ highlightIndex = (effectiveDragPosition + launcherListView.contentY - mainColumn.anchors.margins*3 - launcherColumn.spacing/2) / (launcherListView.itemSize + launcherColumn.spacing)
5455 }
5556
5657 BorderImage {
@@ -61,58 +62,111 @@ Item {
6162
6263 Column {
6364 id: mainColumn
64− anchors.fill: parent
65− anchors.margins: units.gu(1)
66− spacing: units.gu(1)
65+ anchors {
66+ fill: parent
67+ topMargin: units.gu(0.5)
68+ bottomMargin: units.gu(1)
69+ leftMargin: units.gu(0.5)
70+ rightMargin: units.gu(0.5)
71+ }
72+ spacing: units.gu(0.5)
6773
68− LauncherDelegate {
74+ MouseArea {
6975 id: dashItem
70− objectName: "dashItem"
71− width: launcherFlickable.itemSize
72− height: launcherFlickable.itemSize
73− anchors.horizontalCenter: parent.horizontalCenter
74− iconName: "dash"
76+ width: parent.width
77+ height: units.gu(6.5)
7578 onClicked: root.dashItemSelected(0)
79+ z: 1
80+ Image {
81+ objectName: "dashItem"
82+ width: units.gu(5.5)
83+ height: width
84+ anchors.centerIn: parent
85+ source: "graphics/home.png"
86+ }
7687 }
77− Flickable {
78− id: launcherFlickable
88+ ThinDivider {
89+ anchors {
90+ left: parent.left
91+ right: parent.right
92+ margins: -mainColumn.anchors.leftMargin
93+ }
94+ rotation: root.rotation
95+ }
96+
97+ Item {
7998 anchors.left: parent.left
8099 anchors.right: parent.right
81− height: parent.height - dashItem.height - parent.spacing
82− contentHeight: launcherColumn.height
83−
84− property int itemSize: width
85−
86− Column {
87− id: launcherColumn
88− width: parent.width
89− spacing: units.gu(1)
90− anchors.horizontalCenter: parent.horizontalCenter
91−
92− Repeater {
93− id: iconRepeater
94− model: root.model
95−
96− LauncherDelegate {
97− id: launcherDelegate
98− objectName: "launcherDelegate" + index
99− width: launcherFlickable.itemSize
100− height: launcherFlickable.itemSize
101− iconName: model.icon
102− inverted: root.inverted
103− highlighted: root.dragging && index === root.highlightIndex
104− z: -Math.abs(offset)
105− state: "docked"
106−
107− maxAngle: 60
108−
109− itemsBeforeThis: index
110− itemsAfterThis: iconRepeater.count - (index+1)
111−
112− onClicked: {
113− root.applicationSelected(launcherModel.get(index).desktopFile);
114− }
100+ height: parent.height - dashItem.height - parent.spacing*2
101+ ListView {
102+ id: launcherListView
103+ anchors.fill: parent
104+ anchors.topMargin: -itemSize
105+ anchors.bottomMargin: -itemSize
106+ topMargin: itemSize
107+ bottomMargin: itemSize
108+ height: parent.height - dashItem.height - parent.spacing*2
109+ model: root.model
110+ cacheBuffer: itemSize * 3
111+ snapMode: ListView.SnapToItem
112+ highlightRangeMode: ListView.ApplyRange
113+ preferredHighlightBegin: (height - itemSize) / 2
114+ preferredHighlightEnd: (height + itemSize) / 2
115+
116+ // The height of the area where icons start getting folded
117+ property int foldingAreaHeight: itemSize * 0.75
118+ property int itemSize: width
119+
120+ Component.onCompleted: {
121+ // This is needed because snapping would partially fold
122+ // the first item on initialisation. This can only be
123+ // overridden by mouse interactions - which is what flick()
124+ // simulates. Setting contentY to 0 would not work because
125+ // of this.
126+ flick(0, units.gu(20))
127+ }
128+
129+ delegate: LauncherDelegate {
130+ id: launcherDelegate
131+ objectName: "launcherDelegate" + index
132+ width: launcherListView.itemSize
133+ height: launcherListView.itemSize
134+ iconName: model.icon
135+ inverted: root.inverted
136+ highlighted: root.dragging && index === root.highlightIndex
137+ z: -Math.abs(offset)
138+ state: "docked"
139+ maxAngle: 60
140+
141+ onClicked: {
142+ root.applicationSelected(launcherModel.get(index).desktopFile);
143+ }
144+ }
145+
146+ MouseArea {
147+ id: topFoldingArea
148+ anchors {
149+ left: parent.left
150+ right: parent.right
151+ top: parent.top
152+ topMargin: launcherListView.topMargin
153+ }
154+ height: launcherListView.itemSize
155+ enabled: launcherListView.contentY > -launcherListView.topMargin
156+ onClicked: launcherListView.flick(0, units.gu(40))
157+ }
158+
159+ MouseArea {
160+ id: bottomFoldingArea
161+ anchors {
162+ left: parent.left
163+ right: parent.right
164+ bottom: parent.bottom
165+ bottomMargin: launcherListView.bottomMargin
115166 }
167+ height: launcherListView.itemSize
168+ enabled: launcherListView.contentHeight - launcherListView.height - launcherListView.contentY > -launcherListView.bottomMargin
169+ onClicked: launcherListView.flick(0, -units.gu(40))
116170 }
117171 }
118172 }
Launcher/graphics/home@18.pngnew file

Binary file not shown.

Shell.qml+42−40
@@ -17,6 +17,7 @@
1717import QtQuick 2.0
1818import Ubuntu.Application 0.1
1919import Ubuntu.Components 0.1
20+import Ubuntu.Gestures 0.1
2021import LightDM 0.1 as LightDM
2122import "Dash"
2223import "Greeter"
@@ -167,7 +168,14 @@ FocusScope {
167168
168169 contentScale: 1.0 - 0.2 * disappearingAnimationProgress
169170 opacity: 1.0 - disappearingAnimationProgress
170− property real disappearingAnimationProgress: ((greeter.shown) ? greeterRevealer.animatedProgress : stagesRevealer.animatedProgress)
171+ property real disappearingAnimationProgress: {
172+ if (greeter.shown) {
173+ return greeter.showProgress;
174+ } else {
175+ return stagesOuterContainer.showProgress;
176+ }
177+ }
178+
171179 // FIXME: only necessary because stagesRevealer.animatedProgress and
172180 // greeterRevealer.animatedProgress are not animated
173181 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
@@ -176,26 +184,29 @@ FocusScope {
176184
177185
178186 Item {
187+ id: stagesOuterContainer
179188
180189 width: parent.width
181190 height: parent.height
182191 x: launcher.progress
183192 Behavior on x {SmoothedAnimation{velocity: 600}}
184193
194+ property real showProgress:
195+ MathLocal.clamp(1 - (x + stages.x) / shell.width, 0, 1)
185196
186197 Showable {
187198 id: stages
188199
189− property bool fullyShown: shown && stages[stagesRevealer.boundProperty] == stagesRevealer.openedValue
190− && parent.x == 0
200+ x: width
191201
192− property bool fullyHidden: !shown && stages[stagesRevealer.boundProperty] == stagesRevealer.closedValue
202+ property bool fullyShown: shown && x == 0 && parent.x == 0
203+ property bool fullyHidden: !shown && x == width
193204 available: !greeter.shown
194205 hides: [launcher, panel.indicators]
195206 shown: false
196207 opacity: 1.0
197− showAnimation: StandardAnimation { property: "x"; duration: 350; to: stagesRevealer.openedValue; easing.type: Easing.OutCubic }
198− hideAnimation: StandardAnimation { property: "x"; duration: 350; to: stagesRevealer.closedValue; easing.type: Easing.OutCubic }
208+ showAnimation: StandardAnimation { property: "x"; duration: 350; to: 0; easing.type: Easing.OutCubic }
209+ hideAnimation: StandardAnimation { property: "x"; duration: 350; to: width; easing.type: Easing.OutCubic }
199210
200211 width: parent.width
201212 height: parent.height
@@ -326,24 +337,19 @@ FocusScope {
326337 height: sideStage.height
327338 orientation: Qt.Horizontal
328339 }
329− }
330− }
331340
341+ DragHandle {
342+ id: stagesRevealer
343+
344+ anchors.top: parent.top
345+ anchors.bottom: parent.bottom
346+ anchors.right: parent.left
332347
333− Revealer {
334− id: stagesRevealer
335−
336− property real animatedProgress: MathLocal.clamp((-dragPosition - launcher.progress) / closedValue, 0, 1)
337− enabled: mainStage.applications.count > 0 || sideStage.applications.count > 0
338− direction: Qt.RightToLeft
339− openedValue: 0
340− hintDisplacement: units.gu(3)
341− handleSize: shell.edgeSize
342− closedValue: width
343− target: stages
344− width: stages.width
345− height: stages.height
346− orientation: Qt.Horizontal
348+ width: shell.edgeSize
349+ direction: Direction.Leftwards
350+ enabled: mainStage.applications.count > 0 || sideStage.applications.count > 0
351+ }
352+ }
347353 }
348354
349355 Lockscreen {
@@ -392,12 +398,13 @@ FocusScope {
392398 available: true
393399 hides: [launcher, panel.indicators, hud]
394400 shown: true
395− showAnimation: StandardAnimation { property: "x"; to: greeterRevealer.openedValue }
396− hideAnimation: StandardAnimation { property: "x"; to: greeterRevealer.closedValue }
401+
397402 y: panel.panelHeight
398403 width: parent.width
399404 height: parent.height - panel.panelHeight
400405
406+ dragHandleWidth: shell.edgeSize
407+
401408 property var previousMainApp: null
402409 property var previousSideApp: null
403410
@@ -432,6 +439,12 @@ FocusScope {
432439 var bgPath = greeter.model.data(uid, LightDM.UserRoles.BackgroundPathRole)
433440 shell.background = bgPath ? bgPath : default_background
434441 }
442+
443+ onLeftTeaserPressedChanged: {
444+ if (leftTeaserPressed) {
445+ launcher.tease();
446+ }
447+ }
435448 }
436449
437450 InputFilterArea {
@@ -439,19 +452,6 @@ FocusScope {
439452 blockInput: greeter.shown || lockscreen.shown
440453 }
441454
442− Revealer {
443− id: greeterRevealer
444−
445− property real animatedProgress: MathLocal.clamp(-dragPosition / closedValue, 0, 1)
446− target: greeter
447− width: greeter.width
448− height: greeter.height
449− handleSize: shell.edgeSize
450− orientation: Qt.Horizontal
451− visible: greeter.shown
452− enabled: !greeter.locked
453− }
454−
455455 Item {
456456 id: overlay
457457
@@ -538,7 +538,6 @@ FocusScope {
538538 width: parent.width
539539 dragAreaWidth: shell.edgeSize
540540 available: !greeter.locked
541− teasing: available && greeter.leftTeaserPressed
542541 onDashItemSelected: {
543542 greeter.hide()
544543 // Animate if moving between application and dash
@@ -550,8 +549,11 @@ FocusScope {
550549 stages.hide();
551550 }
552551 onDash: {
553− dash.setCurrentScope("applications.scope", true, false)
554− stages.hide();
552+ if (stages.shown) {
553+ dash.setCurrentScope("applications.scope", true, false)
554+ stages.hide();
555+ launcher.hide();
556+ }
555557 }
556558 onLauncherApplicationSelected:{
557559 greeter.hide()
build+2
@@ -49,6 +49,8 @@ install_dependencies() {
4949 indicators-client-plugin-* \
5050 ubuntu-mobile-icons \
5151 unity-notifications-impl-1 \
52+ unity-scope-home \
53+ unity-lens-applications \
5254 || exit 5
5355}
5456
debian/changelog+24
@@ -1,3 +1,27 @@
1+unity8 (7.81.3) UNRELEASED; urgency=low
2+
3+ * Choose more appropriate values for edge-drag gestures (LP: #1194150)
4+
5+ -- Daniel d'Andrada <daniel.dandrada@canonical.com> Fri, 28 Jun 2013 16:28:24 -0300
6+
7+unity8 (7.81.2) saucy; urgency=low
8+
9+ * Translation updates.
10+
11+ [ Michał Sawicz ]
12+ * Fix icons in ApplicationsFilterGrid.qml.
13+ * Support flipped image in run_on_device.
14+
15+ [ Michael Zanetti ]
16+ * Don't clear lockscreen when it's fading out.
17+ * Reworked Launcher folding.
18+ * Tweak Launcher revealing.
19+
20+ [ Michal Hruby ]
21+ * Add content_type property to category models.
22+
23+ -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 26 Jun 2013 18:10:39 +0200
24+
125unity8 (7.81.1) saucy; urgency=low
226
327 * Translation updates.
debian/control+2
@@ -11,6 +11,7 @@ Build-Depends: cmake,
1111 libgles2-mesa-dev[armhf],
1212 libhud-client2-dev,
1313 libpulse-dev,
14+ libqt5v8-5-private-dev,
1415 libunity-core-6.0-dev (<< 7.80),
1516 libxcb1-dev,
1617 pkg-config,
@@ -20,6 +21,7 @@ Build-Depends: cmake,
2021 qtbase5-private-dev,
2122 qtdeclarative5-dev,
2223 qtdeclarative5-dev-tools,
24+ qtdeclarative5-private-dev,
2325 qtdeclarative5-qtquick2-plugin,
2426 qtdeclarative5-test-plugin,
2527 qtdeclarative5-ubuntu-ui-toolkit-plugin,
debian/unity8.install+1
@@ -15,6 +15,7 @@
1515/usr/share/unity8/graphics/*
1616/usr/share/unity8/plugins/HudClient/*
1717/usr/share/unity8/plugins/LightDM/*
18+/usr/share/unity8/plugins/ListViewWithPageHeader/*
1819/usr/share/unity8/plugins/Ubuntu/*
1920/usr/share/unity8/plugins/Unity/*
2021/usr/share/unity8/plugins/Utils/*
main.cpp+26−6
@@ -31,13 +31,33 @@
3131#include "MouseTouchAdaptor.h"
3232
3333namespace {
34+
35+void prependImportPaths(QQmlEngine *engine, const QStringList &paths)
36+{
37+ QStringList importPathList = engine->importPathList();
38+ for (int i = paths.count() -1; i >= 0; i--) {
39+ // don't duplicate
40+ const QString& path = paths[i];
41+ QStringList::iterator iter = qFind(importPathList.begin(), importPathList.end(), path);
42+ if (iter == importPathList.end())
43+ importPathList.prepend(path);
44+ }
45+ engine->setImportPathList(importPathList);
46+}
47+
3448/* When you append and import path to the list of import paths it will be the *last*
3549 place where Qt will search for QML modules.
3650 The usual QQmlEngine::addImportPath() actually prepends the given path.*/
37−void appendImportPath(QQmlEngine *engine, const QString &path)
51+void appendImportPaths(QQmlEngine *engine, const QStringList &paths)
3852{
3953 QStringList importPathList = engine->importPathList();
40− importPathList.append(path);
54+ Q_FOREACH(const QString& path, paths) {
55+ // don't duplicate
56+ QStringList::iterator iter = qFind(importPathList.begin(), importPathList.end(), path);
57+ if (iter == importPathList.end())
58+ importPathList.append(path);
59+ }
60+ importPathList.append(paths);
4161 engine->setImportPathList(importPathList);
4262}
4363
@@ -88,7 +108,7 @@ int main(int argc, char** argv)
88108 QQuickView* view = new QQuickView();
89109 view->setResizeMode(QQuickView::SizeRootObjectToView);
90110 view->setTitle("Qml Phone Shell");
91− view->engine()->setBaseUrl(QUrl::fromLocalFile(shellAppDirectory()));
111+ view->engine()->setBaseUrl(QUrl::fromLocalFile(::shellAppDirectory()));
92112 if (args.contains(QLatin1String("-frameless"))) {
93113 view->setFlags(Qt::FramelessWindowHint);
94114 }
@@ -114,9 +134,9 @@ int main(int argc, char** argv)
114134 QObject::connect(view->engine(), SIGNAL(quit()), qApp, SLOT(quit()));
115135
116136 QUrl source("Shell.qml");
117− view->engine()->addImportPath(shellAppDirectory());
118− view->engine()->addImportPath(shellImportPath());
119− appendImportPath(view->engine(), fakePluginsImportPath());
137+ prependImportPaths(view->engine(), QStringList() << ::shellAppDirectory());
138+ prependImportPaths(view->engine(), ::shellImportPaths());
139+ appendImportPaths(view->engine(), QStringList() << ::fakePluginsImportPath());
120140 view->setSource(source);
121141 view->setColor("transparent");
122142
paths.h.in+10−3
@@ -17,6 +17,9 @@
1717 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1818 */
1919
20+#ifndef PATHS_H
21+#define PATHS_H
22+
2023// Qt
2124#include <QtCore/QCoreApplication>
2225#include <QtCore/QDir>
@@ -43,12 +46,14 @@ inline QString shellAppDirectory() {
4346 }
4447}
4548
46−inline QString shellImportPath() {
49+inline QStringList shellImportPaths() {
50+ QStringList paths;
4751 if (isRunningInstalled()) {
48− return QString("@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/plugins");
52+ paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/plugins");
4953 } else {
50− return QString("@CMAKE_BINARY_DIR@/plugins/");
54+ paths << QString("@CMAKE_BINARY_DIR@/plugins");
5155 }
56+ return paths;
5257}
5358
5459inline QString fakePluginsImportPath() {
@@ -62,3 +67,5 @@ inline QString fakePluginsImportPath() {
6267inline QString sourceDirectory() {
6368 return QString("@CMAKE_SOURCE_DIR@/");
6469}
70+
71+#endif
plugins/CMakeLists.txt+1
@@ -3,3 +3,4 @@ add_subdirectory(Utils)
33add_subdirectory(Unity)
44add_subdirectory(HudClient)
55add_subdirectory(LightDM)
6+add_subdirectory(ListViewWithPageHeader)
plugins/ListViewWithPageHeader/CMakeLists.txtnew file+44
@@ -0,0 +1,44 @@
1+# There's no cmake var for v8 include path :-/
2+# so create one
3+LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
4+SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
5+
6+include_directories(
7+ ${CMAKE_CURRENT_SOURCE_DIR}
8+ ${CMAKE_CURRENT_BINARY_DIR}
9+ ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
10+ ${Qt5Quick_INCLUDE_DIRS}
11+ ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
12+ ${Qt5V8_PRIVATE_INCLUDE_DIR}
13+)
14+
15+remove_definitions(-DQT_NO_KEYWORDS)
16+
17+set(QMLPLUGIN_SRC
18+ plugin.cpp
19+ listviewwithpageheader.cpp
20+ )
21+
22+add_library(ListViewWithPageHeader-qml MODULE
23+ ${QMLPLUGIN_SRC}
24+ )
25+
26+target_link_libraries(ListViewWithPageHeader-qml
27+ ${Qt5Gui_LIBRARIES}
28+ ${Qt5Quick_LIBRARIES}
29+ )
30+
31+qt5_use_modules(ListViewWithPageHeader-qml Qml Quick)
32+
33+# copy qmldir file into build directory for shadow builds
34+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
35+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
36+ )
37+
38+install(TARGETS ListViewWithPageHeader-qml
39+ DESTINATION ${SHELL_APP_DIR}/plugins/ListViewWithPageHeader
40+ )
41+
42+install(FILES qmldir
43+ DESTINATION ${SHELL_APP_DIR}/plugins/ListViewWithPageHeader
44+ )
plugins/ListViewWithPageHeader/listviewwithpageheader.cppnew file+1059
@@ -0,0 +1,1059 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+/*
18+ * Some documentation on how this thing works:
19+ *
20+ * A flickable has two very important concepts that define the top and
21+ * height of the flickable area.
22+ * The top is returned in minYExtent()
23+ * The height is set using setContentHeight()
24+ * By changing those two values we can make the list grow up or down
25+ * as needed. e.g. if we are in the middle of the list
26+ * and something that is above the viewport grows, since we do not
27+ * want to change the viewport because of that we just adjust the
28+ * minYExtent so that the list grows up.
29+ *
30+ * The implementation on the list relies on the delegateModel doing
31+ * most of the instantiation work. You call createItem() when you
32+ * need to create an item asking for it async or not. If returns null
33+ * it means the item will be created async and the model will call the
34+ * itemCreated slot with the item.
35+ *
36+ * updatePolish is the central point of dispatch for the work of the
37+ * class. It is called by the scene graph just before drawing the class.
38+ * In it we:
39+ * * Make sure all items are positioned correctly
40+ * * Add/Remove items if needed
41+ * * Update the content height if it was dirty
42+ *
43+ * m_visibleItems contains all the items we have created at the moment.
44+ * Actually not all of them are visible since it includes the ones
45+ * in the cache area we create asynchronously to help performance.
46+ * The first item in m_visibleItems has the m_firstVisibleIndex in
47+ * the model. If you actually want to know what is the first
48+ * item in the viewport you have to find the first non culled element
49+ * in m_visibleItems
50+ *
51+ * All the items (except the header) are childs of m_clipItem which
52+ * is a child of the contentItem() of the flickable (The contentItem()
53+ * is what actually 'moves' in a a flickable). This way
54+ * we can implement the clipping needed so we can have the header
55+ * shown in the middle of the list over the items without the items
56+ * leaking under the header in case it is transparent.
57+ *
58+ * The first item of m_visibleItems is the one that defines the
59+ * positions of all the rest of items (see updatePolish()) and
60+ * this is why sometimes we move it even if it's not the item
61+ * that has triggered the function (i.e. in itemGeometryChanged())
62+ *
63+ * m_visibleItems is a list of ListItem. Each ListItem
64+ * will contain a item and potentially a sectionItem. The sectionItem
65+ * is only there when the list is using sectionDelegate+sectionProperty
66+ * and this is the first item of the section. Each ListItem is vertically
67+ * layouted with the sectionItem first and then the item.
68+ *
69+ * For sectioning we also have a section item alone (m_topSectionItem)
70+ * that is used for the cases we need to show the sticky section item at
71+ * the top of the view.
72+ *
73+ * Each delegate item has a context property called heightToClip that is
74+ * used to communicate to the delegate implementation in case it has to
75+ * clip itself because of overlapping with the top sticky section item.
76+ * This is an implementation decision since it has been agreed it
77+ * is easier to implement the clipping in QML with this info than to
78+ * do it at the C++ level.
79+ *
80+ * Note that minYExtent and height are not always totally accurate, since
81+ * we don't have the items created we can't guess their heights
82+ * so we can only guarantee the values are correct when the first/last
83+ * items of the list are visible, otherwise we just live with good enough
84+ * values that make the list scrollable
85+ *
86+ * There are a few things that are not really implemented or tested properly
87+ * which we don't use at the moment like changing the model, changing
88+ * the section delegate, having a section delegate that changes its size, etc.
89+ * The known missing features are marked with TODOs along the code.
90+ */
91+
92+#include "listviewwithpageheader.h"
93+
94+#include <QDebug>
95+#include <qqmlinfo.h>
96+#include <qqmlengine.h>
97+#include <private/qquickvisualdatamodel_p.h>
98+#include <private/qqmlglobal_p.h>
99+#include <private/qquickitem_p.h>
100+#include <private/qquickanimation_p.h>
101+// #include <private/qquickrectangle_p.h>
102+
103+static const qreal bufferRatio = 0.5;
104+
105+qreal ListViewWithPageHeader::ListItem::height() const
106+{
107+ return m_item->height() + (m_sectionItem ? m_sectionItem->height() : 0);
108+}
109+
110+qreal ListViewWithPageHeader::ListItem::y() const
111+{
112+ return m_item->y() - (m_sectionItem ? m_sectionItem->height() : 0);
113+}
114+
115+void ListViewWithPageHeader::ListItem::setY(qreal newY)
116+{
117+ if (m_sectionItem) {
118+ m_sectionItem->setY(newY);
119+ m_item->setY(newY + m_sectionItem->height());
120+ } else {
121+ m_item->setY(newY);
122+ }
123+}
124+
125+bool ListViewWithPageHeader::ListItem::culled() const
126+{
127+ return QQuickItemPrivate::get(m_item)->culled;
128+}
129+
130+void ListViewWithPageHeader::ListItem::setCulled(bool culled)
131+{
132+ QQuickItemPrivate::get(m_item)->setCulled(culled);
133+ if (m_sectionItem)
134+ QQuickItemPrivate::get(m_sectionItem)->setCulled(culled);
135+}
136+
137+ListViewWithPageHeader::ListViewWithPageHeader()
138+ : m_delegateModel(nullptr)
139+ , m_asyncRequestedIndex(-1)
140+ , m_delegateValidated(false)
141+ , m_firstVisibleIndex(-1)
142+ , m_minYExtent(0)
143+ , m_contentHeightDirty(false)
144+ , m_headerItem(nullptr)
145+ , m_previousContentY(0)
146+ , m_headerItemShownHeight(0)
147+ , m_sectionDelegate(nullptr)
148+ , m_topSectionItem(nullptr)
149+ , m_forceNoClip(false)
150+ , m_inLayout(false)
151+{
152+ m_clipItem = new QQuickItem(contentItem());
153+// m_clipItem = new QQuickRectangle(contentItem());
154+// ((QQuickRectangle*)m_clipItem)->setColor(Qt::gray);
155+
156+ m_headerShowAnimation = new QQuickNumberAnimation(this);
157+ m_headerShowAnimation->setEasing(QEasingCurve::OutQuad);
158+ m_headerShowAnimation->setProperty("contentY");
159+ m_headerShowAnimation->setDuration(200);
160+ m_headerShowAnimation->setTargetObject(this);
161+
162+ connect(this, SIGNAL(contentWidthChanged()), this, SLOT(onContentWidthChanged()));
163+ connect(this, SIGNAL(contentHeightChanged()), this, SLOT(onContentHeightChanged()));
164+ connect(this, SIGNAL(heightChanged()), this, SLOT(onHeightChanged()));
165+ connect(m_headerShowAnimation, SIGNAL(stopped()), this, SLOT(onShowHeaderAnimationFinished()));
166+}
167+
168+ListViewWithPageHeader::~ListViewWithPageHeader()
169+{
170+}
171+
172+QAbstractItemModel *ListViewWithPageHeader::model() const
173+{
174+ return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() : nullptr;
175+}
176+
177+void ListViewWithPageHeader::setModel(QAbstractItemModel *model)
178+{
179+ if (model != this->model()) {
180+ if (!m_delegateModel) {
181+ createDelegateModel();
182+ } else {
183+ disconnect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
184+ }
185+ m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
186+ connect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
187+ Q_EMIT modelChanged();
188+ // TODO?
189+// Q_EMIT contentHeightChanged();
190+// Q_EMIT contentYChanged();
191+ }
192+}
193+
194+QQmlComponent *ListViewWithPageHeader::delegate() const
195+{
196+ return m_delegateModel ? m_delegateModel->delegate() : nullptr;
197+}
198+
199+void ListViewWithPageHeader::setDelegate(QQmlComponent *delegate)
200+{
201+ if (delegate != this->delegate()) {
202+ if (!m_delegateModel) {
203+ createDelegateModel();
204+ }
205+
206+ // Cleanup the existing items
207+ Q_FOREACH(ListItem *item, m_visibleItems)
208+ releaseItem(item);
209+ m_visibleItems.clear();
210+ m_firstVisibleIndex = -1;
211+ adjustMinYExtent();
212+ setContentY(0);
213+ m_clipItem->setY(0);
214+ if (m_topSectionItem) {
215+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
216+ }
217+
218+ m_delegateModel->setDelegate(delegate);
219+
220+ Q_EMIT delegateChanged();
221+ m_delegateValidated = false;
222+ m_contentHeightDirty = true;
223+ polish();
224+ }
225+}
226+
227+QQuickItem *ListViewWithPageHeader::header() const
228+{
229+ return m_headerItem;
230+}
231+
232+void ListViewWithPageHeader::setHeader(QQuickItem *headerItem)
233+{
234+ if (m_headerItem != headerItem) {
235+ qreal oldHeaderHeight = 0;
236+ qreal oldHeaderY = 0;
237+ if (m_headerItem) {
238+ oldHeaderHeight = m_headerItem->height();
239+ oldHeaderY = m_headerItem->y();
240+ m_headerItem->setParentItem(nullptr);
241+ }
242+ m_headerItem = headerItem;
243+ if (m_headerItem) {
244+ m_headerItem->setParentItem(contentItem());
245+ m_headerItem->setZ(1);
246+ }
247+ qreal newHeaderHeight = m_headerItem ? m_headerItem->height() : 0;
248+ if (!m_visibleItems.isEmpty() && newHeaderHeight != oldHeaderHeight) {
249+ headerHeightChanged(newHeaderHeight, oldHeaderHeight, oldHeaderY);
250+ polish();
251+ m_contentHeightDirty = true;
252+ }
253+ Q_EMIT headerChanged();
254+ }
255+}
256+
257+QQmlComponent *ListViewWithPageHeader::sectionDelegate() const
258+{
259+ return m_sectionDelegate;
260+}
261+
262+void ListViewWithPageHeader::setSectionDelegate(QQmlComponent *delegate)
263+{
264+ if (delegate != m_sectionDelegate) {
265+ // TODO clean existing sections
266+
267+ m_sectionDelegate = delegate;
268+
269+ m_topSectionItem = getSectionItem(QString());
270+ m_topSectionItem->setZ(3);
271+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
272+
273+ // TODO create sections for existing items
274+
275+ Q_EMIT sectionDelegateChanged();
276+ }
277+}
278+
279+QString ListViewWithPageHeader::sectionProperty() const
280+{
281+ return m_sectionProperty;
282+}
283+
284+void ListViewWithPageHeader::setSectionProperty(const QString &property)
285+{
286+ if (property != m_sectionProperty) {
287+ m_sectionProperty = property;
288+
289+ updateWatchedRoles();
290+
291+ // TODO recreate sections
292+
293+ Q_EMIT sectionPropertyChanged();
294+ }
295+}
296+
297+bool ListViewWithPageHeader::forceNoClip() const
298+{
299+ return m_forceNoClip;
300+}
301+
302+void ListViewWithPageHeader::setForceNoClip(bool noClip)
303+{
304+ if (noClip != m_forceNoClip) {
305+ m_forceNoClip = noClip;
306+ updateClipItem();
307+ Q_EMIT forceNoClipChanged();
308+ }
309+}
310+
311+void ListViewWithPageHeader::positionAtBeginning()
312+{
313+ qreal headerHeight = (m_headerItem ? m_headerItem->height() : 0);
314+ if (m_firstVisibleIndex != 0) {
315+ // TODO This could be optimized by trying to reuse the interesection
316+ // of items that may end up intersecting between the existing
317+ // m_visibleItems and the items we are creating in the next loop
318+ Q_FOREACH(ListItem *item, m_visibleItems)
319+ releaseItem(item);
320+ m_visibleItems.clear();
321+ m_firstVisibleIndex = -1;
322+
323+ // Create the item 0, it will be already correctly positioned at createItem()
324+ m_clipItem->setY(0);
325+ ListItem *item = createItem(0, false);
326+ // Create the subsequent items
327+ int modelIndex = 1;
328+ qreal pos = item->y() + item->height();
329+ const qreal buffer = height() * bufferRatio;
330+ const qreal bufferTo = height() + buffer;
331+ while (modelIndex < m_delegateModel->count() && pos <= bufferTo) {
332+ if (!(item = createItem(modelIndex, false)))
333+ break;
334+ pos += item->height();
335+ ++modelIndex;
336+ }
337+
338+ m_previousContentY = m_visibleItems.first()->y() - headerHeight;
339+ }
340+ setContentY(m_visibleItems.first()->y() + m_clipItem->y() - headerHeight);
341+}
342+
343+void ListViewWithPageHeader::showHeader()
344+{
345+ auto to = qMax(-minYExtent(), contentY() - m_headerItem->height() + m_headerItemShownHeight);
346+ if (to != contentY()) {
347+ m_headerShowAnimation->setTo(to);
348+ m_headerShowAnimation->start();
349+ }
350+}
351+
352+qreal ListViewWithPageHeader::minYExtent() const
353+{
354+// qDebug() << "ListViewWithPageHeader::minYExtent" << m_minYExtent;
355+ return m_minYExtent;
356+}
357+
358+void ListViewWithPageHeader::componentComplete()
359+{
360+ if (m_delegateModel)
361+ m_delegateModel->componentComplete();
362+
363+ QQuickFlickable::componentComplete();
364+
365+ polish();
366+}
367+
368+void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
369+{
370+ QQuickFlickable::viewportMoved(orient);
371+// qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY();
372+ qreal diff = m_previousContentY - contentY();
373+ if (m_headerItem) {
374+ auto oldHeaderItemShownHeight = m_headerItemShownHeight;
375+ if (contentY() < -m_minYExtent) {
376+ // Stick the header item to the top when dragging down
377+ m_headerItem->setY(contentY());
378+ m_headerItem->setHeight(m_headerItem->implicitHeight() + (-m_minYExtent - contentY()));
379+ } else {
380+ m_headerItem->setHeight(m_headerItem->implicitHeight());
381+ // We are going down (but it's not because of the rebound at the end)
382+ // (but the header was not shown by it's own position)
383+ // or the header is partially shown
384+ const bool scrolledUp = m_previousContentY > contentY();
385+ const bool notRebounding = contentY() + height() < contentHeight();
386+ const bool notShownByItsOwn = contentY() + diff > m_headerItem->y() + m_headerItem->height();
387+
388+ if (!scrolledUp && contentY() == -m_minYExtent) {
389+ m_headerItemShownHeight = 0;
390+ m_headerItem->setY(contentY());
391+ } else if ((scrolledUp && notRebounding && notShownByItsOwn) || (m_headerItemShownHeight > 0)) {
392+ m_headerItemShownHeight += diff;
393+ if (contentY() == -m_minYExtent) {
394+ m_headerItemShownHeight = 0;
395+ } else {
396+ m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, m_headerItem->height());
397+ }
398+ if (m_headerItemShownHeight > 0) {
399+ m_headerItem->setY(contentY() - m_headerItem->height() + m_headerItemShownHeight);
400+ } else {
401+ m_headerItem->setY(-m_minYExtent);
402+ }
403+ }
404+ }
405+ // We will be changing the clip item, need to accomadate for it
406+ // otherwise we move the firstItem down/up twice (unless the
407+ // show header animation is running, where we want to keep the viewport stable)
408+ if (!m_headerShowAnimation->isRunning()) {
409+ diff += oldHeaderItemShownHeight - m_headerItemShownHeight;
410+ } else {
411+ diff = -diff;
412+ }
413+ }
414+ if (!m_visibleItems.isEmpty()) {
415+ updateClipItem();
416+ ListItem *firstItem = m_visibleItems.first();
417+ firstItem->setY(firstItem->y() + diff);
418+ if (m_headerShowAnimation->isRunning()) {
419+ adjustMinYExtent();
420+ }
421+ }
422+
423+ m_previousContentY = contentY();
424+ layout();
425+ polish();
426+}
427+
428+void ListViewWithPageHeader::createDelegateModel()
429+{
430+ m_delegateModel = new QQuickVisualDataModel(qmlContext(this), this);
431+ connect(m_delegateModel, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(itemCreated(int,QQuickItem*)));
432+ if (isComponentComplete())
433+ m_delegateModel->componentComplete();
434+ updateWatchedRoles();
435+}
436+
437+void ListViewWithPageHeader::refill()
438+{
439+ if (m_inLayout) {
440+ return;
441+ }
442+ if (!isComponentComplete()) {
443+ return;
444+ }
445+
446+ const qreal buffer = height() * bufferRatio;
447+ const qreal from = contentY();
448+ const qreal to = from + height();
449+ const qreal bufferFrom = from - buffer;
450+ const qreal bufferTo = to + buffer;
451+
452+ bool added = addVisibleItems(from, to, false);
453+ bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
454+ added |= addVisibleItems(bufferFrom, bufferTo, true);
455+
456+ if (added || removed) {
457+ m_contentHeightDirty = true;
458+ }
459+}
460+
461+bool ListViewWithPageHeader::addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous)
462+{
463+ if (!delegate())
464+ return false;
465+
466+ if (m_delegateModel->count() == 0)
467+ return false;
468+
469+ ListItem *item;
470+// qDebug() << "ListViewWithPageHeader::addVisibleItems" << fillFrom << fillTo << asynchronous;
471+
472+ int modelIndex = 0;
473+ qreal pos = 0;
474+ if (!m_visibleItems.isEmpty()) {
475+ modelIndex = m_firstVisibleIndex + m_visibleItems.count();
476+ item = m_visibleItems.last();
477+ pos = item->y() + item->height() + m_clipItem->y();
478+ }
479+ bool changed = false;
480+// qDebug() << (modelIndex < m_delegateModel->count()) << pos << fillTo;
481+ while (modelIndex < m_delegateModel->count() && pos <= fillTo) {
482+// qDebug() << "refill: append item" << modelIndex << "pos" << pos << "asynchronous" << asynchronous;
483+ if (!(item = createItem(modelIndex, asynchronous)))
484+ break;
485+ pos += item->height();
486+ ++modelIndex;
487+ changed = true;
488+ }
489+
490+ modelIndex = 0;
491+ pos = 0;
492+ if (!m_visibleItems.isEmpty()) {
493+ modelIndex = m_firstVisibleIndex - 1;
494+ item = m_visibleItems.first();
495+ pos = item->y() + m_clipItem->y();
496+ }
497+ while (modelIndex >= 0 && pos > fillFrom) {
498+// qDebug() << "refill: prepend item" << modelIndex << "pos" << pos << "fillFrom" << fillFrom << "asynchronous" << asynchronous;
499+ if (!(item = createItem(modelIndex, asynchronous)))
500+ break;
501+ pos -= item->height();
502+ --modelIndex;
503+ changed = true;
504+ }
505+
506+ return changed;
507+}
508+
509+void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
510+{
511+ QQuickItem *item = listItem->m_item;
512+ QQuickVisualModel::ReleaseFlags flags = m_delegateModel->release(item);
513+ if (flags & QQuickVisualModel::Destroyed) {
514+ item->setParentItem(nullptr);
515+ }
516+ delete listItem->m_sectionItem;
517+ delete listItem;
518+}
519+
520+void ListViewWithPageHeader::releaseItem(ListItem *listItem)
521+{
522+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(listItem->m_item);
523+ itemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
524+ m_itemsToRelease << listItem;
525+}
526+
527+void ListViewWithPageHeader::updateWatchedRoles()
528+{
529+ if (m_delegateModel) {
530+ QList<QByteArray> roles;
531+ if (!m_sectionProperty.isEmpty())
532+ roles << m_sectionProperty.toUtf8();
533+ m_delegateModel->setWatchedRoles(roles);
534+ }
535+}
536+
537+QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyInserted)
538+{
539+ if (!m_sectionDelegate)
540+ return nullptr;
541+
542+ const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
543+ if (modelIndex > 0) {
544+ const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
545+ if (section == prevSection)
546+ return nullptr;
547+ }
548+ if (modelIndex + 1 < model()->rowCount() && !alreadyInserted) {
549+ // Already inserted items can't steal next section header
550+ const QString nextSection = m_delegateModel->stringValue(modelIndex + 1, m_sectionProperty);
551+ if (section == nextSection) {
552+ // Steal the section header
553+ ListItem *nextItem = itemAtIndex(modelIndex); // Not +1 since not yet inserted into m_visibleItems
554+ if (nextItem) {
555+ QQuickItem *sectionItem = nextItem->m_sectionItem;
556+ nextItem->m_sectionItem = nullptr;
557+ return sectionItem;
558+ }
559+ }
560+ }
561+
562+ return getSectionItem(section);
563+}
564+
565+QQuickItem *ListViewWithPageHeader::getSectionItem(const QString &sectionText)
566+{
567+ QQuickItem *sectionItem = nullptr;
568+
569+ QQmlContext *creationContext = m_sectionDelegate->creationContext();
570+ QQmlContext *context = new QQmlContext(creationContext ? creationContext : qmlContext(this));
571+ context->setContextProperty(QLatin1String("section"), sectionText);
572+ QObject *nobj = m_sectionDelegate->beginCreate(context);
573+ if (nobj) {
574+ QQml_setParent_noEvent(context, nobj);
575+ sectionItem = qobject_cast<QQuickItem *>(nobj);
576+ if (!sectionItem) {
577+ delete nobj;
578+ } else {
579+ sectionItem->setZ(2);
580+ QQml_setParent_noEvent(sectionItem, m_clipItem);
581+ sectionItem->setParentItem(m_clipItem);
582+ }
583+ } else {
584+ delete context;
585+ }
586+ m_sectionDelegate->completeCreate();
587+
588+ // TODO attach to sectionItem so we can accomodate to it changing its height
589+
590+ return sectionItem;
591+}
592+
593+bool ListViewWithPageHeader::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
594+{
595+// qDebug() << "ListViewWithPageHeader::removeNonVisibleItems" << bufferFrom << bufferTo;
596+ // Do not remove items if we are overshooting up or down, since we'll come back
597+ // to the "stable" position and delete/create items without any reason
598+ if (contentY() < -m_minYExtent) {
599+ return false;
600+ } else if (contentY() + height() > contentHeight()) {
601+ return false;
602+ }
603+ bool changed = false;
604+
605+ bool foundVisible = false;
606+ int i = 0;
607+ int removedItems = 0;
608+ const auto oldFirstVisibleIndex = m_firstVisibleIndex;
609+ while (i < m_visibleItems.count()) {
610+ ListItem *item = m_visibleItems[i];
611+ const qreal pos = item->y() + m_clipItem->y();
612+// qDebug() << i << pos << (pos + item->height()) << bufferFrom << bufferTo;
613+ if (pos + item->height() < bufferFrom || pos > bufferTo) {
614+// qDebug() << "Releasing" << i << (pos + item->height() < bufferFrom) << pos + item->height() << bufferFrom << (pos > bufferTo) << pos << bufferTo;
615+ releaseItem(item);
616+ m_visibleItems.removeAt(i);
617+ changed = true;
618+ ++removedItems;
619+ } else {
620+ if (!foundVisible) {
621+ foundVisible = true;
622+ const int itemIndex = m_firstVisibleIndex + removedItems + i;
623+ m_firstVisibleIndex = itemIndex;
624+ }
625+ ++i;
626+ }
627+ }
628+ if (m_firstVisibleIndex != oldFirstVisibleIndex) {
629+ adjustMinYExtent();
630+ }
631+
632+ return changed;
633+}
634+
635+ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIndex, bool asynchronous)
636+{
637+// qDebug() << "CREATE ITEM" << modelIndex;
638+ if (asynchronous && m_asyncRequestedIndex != -1)
639+ return nullptr;
640+
641+ m_asyncRequestedIndex = -1;
642+ QQuickItem *item = m_delegateModel->item(modelIndex, asynchronous);
643+ if (!item) {
644+ m_asyncRequestedIndex = modelIndex;
645+ return 0;
646+ } else {
647+// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
648+ ListItem *listItem = new ListItem;
649+ listItem->m_item = item;
650+ listItem->m_sectionItem = getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/);
651+ QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
652+ ListItem *prevItem = itemAtIndex(modelIndex - 1);
653+ bool lostItem = false; // Is an item that we requested async but because of model changes
654+ // it is no longer attached to any of the existing items (has no prev nor next item)
655+ // nor is the first item
656+ if (prevItem) {
657+ listItem->setY(prevItem->y() + prevItem->height());
658+ } else {
659+ ListItem *currItem = itemAtIndex(modelIndex);
660+ if (currItem) {
661+ // There's something already in m_visibleItems at out index, meaning this is an insert, so attach to its top
662+ listItem->setY(currItem->y() - listItem->height());
663+ } else {
664+ ListItem *nextItem = itemAtIndex(modelIndex + 1);
665+ if (nextItem) {
666+ listItem->setY(nextItem->y() - listItem->height());
667+ } else if (modelIndex == 0 && m_headerItem) {
668+ listItem->setY(m_headerItem->height());
669+ } else if (!m_visibleItems.isEmpty()) {
670+ lostItem = true;
671+ }
672+ }
673+ }
674+ if (lostItem) {
675+ releaseItem(listItem);
676+ listItem = nullptr;
677+ } else {
678+ listItem->setCulled(listItem->y() + listItem->height() + m_clipItem->y() < contentY() || listItem->y() + m_clipItem->y() >= contentY() + height());
679+ if (m_visibleItems.isEmpty()) {
680+ m_visibleItems << listItem;
681+ } else {
682+ m_visibleItems.insert(modelIndex - m_firstVisibleIndex, listItem);
683+ }
684+ if (m_firstVisibleIndex < 0 || modelIndex < m_firstVisibleIndex) {
685+ m_firstVisibleIndex = modelIndex;
686+ polish();
687+ }
688+ adjustMinYExtent();
689+ m_contentHeightDirty = true;
690+ }
691+ return listItem;
692+ }
693+}
694+
695+void ListViewWithPageHeader::itemCreated(int modelIndex, QQuickItem *item)
696+{
697+// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
698+
699+ item->setParentItem(m_clipItem);
700+ QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
701+ context->setContextProperty(QLatin1String("ListViewWithPageHeader"), this);
702+ context->setContextProperty(QLatin1String("heightToClip"), QVariant::fromValue<int>(0));
703+ if (modelIndex == m_asyncRequestedIndex) {
704+ createItem(modelIndex, false);
705+ refill();
706+ }
707+}
708+
709+void ListViewWithPageHeader::updateClipItem()
710+{
711+ m_clipItem->setHeight(height() - m_headerItemShownHeight);
712+ m_clipItem->setY(contentY() + m_headerItemShownHeight);
713+ m_clipItem->setClip(!m_forceNoClip && m_headerItemShownHeight > 0);
714+}
715+
716+void ListViewWithPageHeader::onContentHeightChanged()
717+{
718+ updateClipItem();
719+}
720+
721+void ListViewWithPageHeader::onContentWidthChanged()
722+{
723+ m_clipItem->setWidth(contentItem()->width());
724+}
725+
726+void ListViewWithPageHeader::onHeightChanged()
727+{
728+ polish();
729+}
730+
731+void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bool /*reset*/)
732+{
733+ // TODO Do something with reset
734+// qDebug() << "ListViewWithPageHeader::onModelUpdated" << changeSet << reset;
735+ const auto oldFirstVisibleIndex = m_firstVisibleIndex;
736+
737+ Q_FOREACH(const QQuickChangeSet::Remove &remove, changeSet.removes()) {
738+// qDebug() << "ListViewWithPageHeader::onModelUpdated Remove" << remove.index << remove.count;
739+ if (remove.index + remove.count > m_firstVisibleIndex && remove.index < m_firstVisibleIndex + m_visibleItems.count()) {
740+ const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
741+ // If all the items we are removing are either not created or culled
742+ // we have to grow down to avoid viewport changing
743+ bool growDown = true;
744+ for (int i = 0; growDown && i < remove.count; ++i) {
745+ const int modelIndex = remove.index + i;
746+ ListItem *item = itemAtIndex(modelIndex);
747+ if (item && !item->culled()) {
748+ growDown = false;
749+ }
750+ }
751+ for (int i = remove.count - 1; i >= 0; --i) {
752+ const int visibleIndex = remove.index + i - m_firstVisibleIndex;
753+ if (visibleIndex >= 0 && visibleIndex < m_visibleItems.count()) {
754+ ListItem *item = m_visibleItems[visibleIndex];
755+ // Pass the section item down if needed
756+ if (item->m_sectionItem && visibleIndex + 1 < m_visibleItems.count()) {
757+ ListItem *nextItem = m_visibleItems[visibleIndex + 1];
758+ if (!nextItem->m_sectionItem) {
759+ nextItem->m_sectionItem = item->m_sectionItem;
760+ item->m_sectionItem = nullptr;
761+ }
762+ }
763+ releaseItem(item);
764+ m_visibleItems.removeAt(visibleIndex);
765+ }
766+ }
767+ if (growDown) {
768+ adjustMinYExtent();
769+ } else if (remove.index <= m_firstVisibleIndex && !m_visibleItems.isEmpty()) {
770+ // We removed the first item that is the one that positions the rest
771+ // position the new first item correctly
772+ m_visibleItems.first()->setY(oldFirstValidIndexPos);
773+ }
774+ } else if (remove.index + remove.count <= m_firstVisibleIndex) {
775+ m_firstVisibleIndex -= remove.count;
776+ }
777+ for (int i = remove.count - 1; i >= 0; --i) {
778+ const int modelIndex = remove.index + i;
779+ if (modelIndex == m_asyncRequestedIndex) {
780+ m_asyncRequestedIndex = -1;
781+ } else if (modelIndex < m_asyncRequestedIndex) {
782+ m_asyncRequestedIndex--;
783+ }
784+ }
785+ }
786+
787+ Q_FOREACH(const QQuickChangeSet::Insert &insert, changeSet.inserts()) {
788+// qDebug() << "ListViewWithPageHeader::onModelUpdated Insert" << insert.index << insert.count;
789+ const bool insertingInValidIndexes = insert.index > m_firstVisibleIndex && insert.index < m_firstVisibleIndex + m_visibleItems.count();
790+ const bool firstItemWithViewOnTop = insert.index == 0 && m_firstVisibleIndex == 0 && m_visibleItems.first()->y() + m_clipItem->y() > contentY();
791+ if (insertingInValidIndexes || firstItemWithViewOnTop)
792+ {
793+ // If the items we are adding won't be really visible
794+ // we grow up instead of down to not change the viewport
795+ bool growUp = false;
796+ if (!firstItemWithViewOnTop) {
797+ for (int i = 0; i < m_visibleItems.count(); ++i) {
798+ if (!m_visibleItems[i]->culled()) {
799+ if (insert.index <= m_firstVisibleIndex + i) {
800+ growUp = true;
801+ }
802+ break;
803+ }
804+ }
805+ }
806+
807+ const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
808+ for (int i = insert.count - 1; i >= 0; --i) {
809+ const int modelIndex = insert.index + i;
810+ ListItem *item = createItem(modelIndex, false);
811+ if (growUp) {
812+ ListItem *firstItem = m_visibleItems.first();
813+ firstItem->setY(firstItem->y() - item->height());
814+ adjustMinYExtent();
815+ }
816+ // Adding an item may break a "same section" chain, so check
817+ // if we need adding a new section item
818+ if (m_sectionDelegate) {
819+ ListItem *nextItem = itemAtIndex(modelIndex + 1);
820+ if (nextItem && !nextItem->m_sectionItem) {
821+ nextItem->m_sectionItem = getSectionItem(modelIndex + 1, true /* alredy inserted into m_visibleItems*/);
822+ if (growUp && nextItem->m_sectionItem) {
823+ ListItem *firstItem = m_visibleItems.first();
824+ firstItem->setY(firstItem->y() - nextItem->m_sectionItem->height());
825+ adjustMinYExtent();
826+ }
827+ }
828+ }
829+ }
830+ if (firstItemWithViewOnTop) {
831+ ListItem *firstItem = m_visibleItems.first();
832+ firstItem->setY(oldFirstValidIndexPos);
833+ }
834+ } else if (insert.index <= m_firstVisibleIndex) {
835+ m_firstVisibleIndex += insert.count;
836+ }
837+
838+ for (int i = insert.count - 1; i >= 0; --i) {
839+ const int modelIndex = insert.index + i;
840+ if (modelIndex <= m_asyncRequestedIndex) {
841+ m_asyncRequestedIndex++;
842+ }
843+ }
844+ }
845+
846+ if (m_firstVisibleIndex != oldFirstVisibleIndex) {
847+ adjustMinYExtent();
848+ }
849+
850+ layout();
851+ polish();
852+ m_contentHeightDirty = true;
853+}
854+
855+void ListViewWithPageHeader::onShowHeaderAnimationFinished()
856+{
857+ m_contentHeightDirty = true;
858+ polish();
859+}
860+
861+void ListViewWithPageHeader::itemGeometryChanged(QQuickItem * /*item*/, const QRectF &newGeometry, const QRectF &oldGeometry)
862+{
863+ const qreal heightDiff = newGeometry.height() - oldGeometry.height();
864+ if (heightDiff != 0) {
865+ if (oldGeometry.y() + oldGeometry.height() + m_clipItem->y() < contentY() && !m_visibleItems.isEmpty()) {
866+ ListItem *firstItem = m_visibleItems.first();
867+ firstItem->setY(firstItem->y() - heightDiff);
868+ adjustMinYExtent();
869+ layout();
870+ }
871+ refill();
872+ adjustMinYExtent();
873+ polish();
874+ m_contentHeightDirty = true;
875+ }
876+}
877+
878+void ListViewWithPageHeader::headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY)
879+{
880+ const qreal heightDiff = newHeaderHeight - oldHeaderHeight;
881+ if (m_headerItemShownHeight > 0) {
882+ // If the header is shown because of the clip
883+ // Change its size
884+ m_headerItemShownHeight += heightDiff;
885+ m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, newHeaderHeight);
886+ updateClipItem();
887+ adjustMinYExtent();
888+ } else {
889+ if (oldHeaderY + oldHeaderHeight > contentY()) {
890+ // If the header is shown because its position
891+ // Change its size
892+ ListItem *firstItem = m_visibleItems.first();
893+ firstItem->setY(firstItem->y() + heightDiff);
894+ layout();
895+ } else {
896+ // If the header is not on screen, just change the start of the list
897+ // so the viewport is not changed
898+ adjustMinYExtent();
899+ }
900+ }
901+}
902+
903+
904+void ListViewWithPageHeader::adjustMinYExtent()
905+{
906+ if (m_visibleItems.isEmpty()) {
907+ m_minYExtent = 0;
908+ } else {
909+ qreal nonCreatedHeight = 0;
910+ if (m_firstVisibleIndex != 0) {
911+ // Calculate the average height of items to estimate the position of the list start
912+ const int visibleItems = m_visibleItems.count();
913+ qreal visibleItemsHeight = 0;
914+ Q_FOREACH(ListItem *item, m_visibleItems) {
915+ visibleItemsHeight += item->height();
916+ }
917+ nonCreatedHeight = m_firstVisibleIndex * visibleItemsHeight / visibleItems;
918+// qDebug() << m_firstVisibleIndex << visibleItemsHeight << visibleItems << nonCreatedHeight;
919+ }
920+ m_minYExtent = nonCreatedHeight - m_visibleItems.first()->y() - m_clipItem->y() + (m_headerItem ? m_headerItem->implicitHeight() : 0);
921+ }
922+}
923+
924+ListViewWithPageHeader::ListItem *ListViewWithPageHeader::itemAtIndex(int modelIndex) const
925+{
926+ const int visibleIndexedModelIndex = modelIndex - m_firstVisibleIndex;
927+ if (visibleIndexedModelIndex >= 0 && visibleIndexedModelIndex < m_visibleItems.count())
928+ return m_visibleItems[visibleIndexedModelIndex];
929+
930+ return nullptr;
931+}
932+
933+void ListViewWithPageHeader::layout()
934+{
935+ if (m_inLayout)
936+ return;
937+
938+ m_inLayout = true;
939+ if (!m_visibleItems.isEmpty()) {
940+ const qreal visibleFrom = contentY() - m_clipItem->y() + m_headerItemShownHeight;
941+ const qreal visibleTo = contentY() + height() - m_clipItem->y();
942+
943+ qreal pos = m_visibleItems.first()->y();
944+
945+// qDebug() << "ListViewWithPageHeader::layout Updating positions and heights. contentY" << contentY() << "minYExtent" << minYExtent();
946+ int firstReallyVisibleItem = -1;
947+ int modelIndex = m_firstVisibleIndex;
948+ Q_FOREACH(ListItem *item, m_visibleItems) {
949+ const bool cull = pos + item->height() < visibleFrom || pos >= visibleTo;
950+ item->setCulled(cull);
951+ item->setY(pos);
952+ if (!cull && firstReallyVisibleItem == -1) {
953+ firstReallyVisibleItem = modelIndex;
954+ if (m_topSectionItem) {
955+ // Update the top sticky section header
956+ const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
957+ QQmlContext *context = QQmlEngine::contextForObject(m_topSectionItem)->parentContext();
958+ context->setContextProperty(QLatin1String("section"), section);
959+
960+ // Positing the top section sticky item is a two step process
961+ // First we set it either we cull it (because it doesn't need to be sticked to the top)
962+ // or stick it to the top
963+ // Then after the loop we'll make sure that if there's another section just below it
964+ // pushed the sticky section up to make it disappear
965+ const qreal topSectionStickPos = m_headerItemShownHeight + contentY() - m_clipItem->y();
966+ if (topSectionStickPos <= pos) {
967+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
968+ if (item->m_sectionItem) {
969+ // This seems it should happen since why would we cull the top section
970+ // if the first visible item has no section header? This only happens briefly
971+ // when increasing the height of a list that is at the bottom, the m_topSectionItem
972+ // gets shown shortly in the next polish call
973+ QQuickItemPrivate::get(item->m_sectionItem)->setCulled(false);
974+ }
975+ } else {
976+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(false);
977+ m_topSectionItem->setY(topSectionStickPos);
978+ if (item->m_sectionItem) {
979+ QQuickItemPrivate::get(item->m_sectionItem)->setCulled(true);
980+ }
981+ }
982+ }
983+ }
984+ QQmlContext *context = QQmlEngine::contextForObject(item->m_item)->parentContext();
985+ const qreal clipFrom = visibleFrom + (!item->m_sectionItem && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
986+ if (!cull && pos < clipFrom) {
987+ context->setContextProperty(QLatin1String("heightToClip"), clipFrom - pos);
988+ } else {
989+ context->setContextProperty(QLatin1String("heightToClip"), QVariant::fromValue<int>(0));
990+ }
991+// qDebug() << "ListViewWithPageHeader::layout" << item->m_item;
992+ pos += item->height();
993+ ++modelIndex;
994+ }
995+
996+ // Second step of section sticky item positioning
997+ // Look at the next section header, check if it's pushing up the sticky one
998+ if (m_topSectionItem) {
999+ if (firstReallyVisibleItem >= 0) {
1000+ for (int i = firstReallyVisibleItem - m_firstVisibleIndex + 1; i < m_visibleItems.count(); ++i) {
1001+ ListItem *item = m_visibleItems[i];
1002+ if (item->m_sectionItem) {
1003+ if (m_topSectionItem->y() + m_topSectionItem->height() > item->y()) {
1004+ m_topSectionItem->setY(item->y() - m_topSectionItem->height());
1005+ }
1006+ break;
1007+ }
1008+ }
1009+ }
1010+ }
1011+ }
1012+ m_inLayout = false;
1013+}
1014+
1015+void ListViewWithPageHeader::updatePolish()
1016+{
1017+ Q_FOREACH(ListItem *item, m_itemsToRelease)
1018+ reallyReleaseItem(item);
1019+ m_itemsToRelease.clear();
1020+
1021+ if (!model())
1022+ return;
1023+
1024+ layout();
1025+
1026+ refill();
1027+
1028+ if (m_contentHeightDirty) {
1029+ qreal contentHeight;
1030+ if (m_visibleItems.isEmpty()) {
1031+ contentHeight = m_headerItem ? m_headerItem->height() : 0;
1032+ } else {
1033+ const int modelCount = model()->rowCount();
1034+ const int visibleItems = m_visibleItems.count();
1035+ const int lastValidIndex = m_firstVisibleIndex + visibleItems - 1;
1036+ qreal nonCreatedHeight = 0;
1037+ if (lastValidIndex != modelCount - 1) {
1038+ const int visibleItems = m_visibleItems.count();
1039+ qreal visibleItemsHeight = 0;
1040+ Q_FOREACH(ListItem *item, m_visibleItems) {
1041+ visibleItemsHeight += item->height();
1042+ }
1043+ const int unknownSizes = modelCount - (m_firstVisibleIndex + visibleItems);
1044+ nonCreatedHeight = unknownSizes * visibleItemsHeight / visibleItems;
1045+ }
1046+ ListItem *item = m_visibleItems.last();
1047+ contentHeight = nonCreatedHeight + item->y() + item->height() + m_clipItem->y();
1048+ if (m_firstVisibleIndex != 0) {
1049+ // Make sure that if we are shrinking we tell the view we still fit
1050+ m_minYExtent = qMax(m_minYExtent, -(contentHeight - height()));
1051+ }
1052+ }
1053+
1054+ m_contentHeightDirty = false;
1055+ setContentHeight(contentHeight);
1056+ }
1057+}
1058+
1059+#include "moc_listviewwithpageheader.cpp"
plugins/ListViewWithPageHeader/listviewwithpageheader.hnew file+180
@@ -0,0 +1,180 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef LISTVIEWWITHPAGEHEADER_H
18+#define LISTVIEWWITHPAGEHEADER_H
19+
20+#include <private/qquickitemchangelistener_p.h>
21+#include <private/qquickflickable_p.h>
22+
23+class QAbstractItemModel;
24+class QQuickChangeSet;
25+class QQuickNumberAnimation;
26+class QQuickVisualDataModel;
27+
28+
29+/**
30+ Note for users of this class
31+
32+ ListViewWithPageHeader already loads delegates async when appropiate so if
33+ your delegate uses a Loader you should not enable the asynchronous feature since
34+ that will need to introduce sizing problems
35+
36+ With the double async it may happen what while we are scrolling down
37+ we reach to a point where given the size of the just created delegate with loader not yet loaded (which will be very close to 0)
38+ we are already "at the end" of the list, but then a few milliseconds later the loader finishes loading and we could
39+ have kept scrolling. This is specially visible at the end of the list where you realize
40+ that scrolling ended a bit before the end of the list but the speed of the flicking was good
41+ to reach the end
42+
43+ By not having the second async we get a better sizing when the delegate is created and things work better
44+*/
45+
46+class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeListener
47+{
48+ Q_OBJECT
49+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
50+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
51+ Q_PROPERTY(QQuickItem *pageHeader READ header WRITE setHeader NOTIFY headerChanged)
52+ Q_PROPERTY(QQmlComponent *sectionDelegate READ sectionDelegate WRITE setSectionDelegate NOTIFY sectionDelegateChanged)
53+ Q_PROPERTY(QString sectionProperty READ sectionProperty WRITE setSectionProperty NOTIFY sectionPropertyChanged)
54+ Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
55+
56+ friend class ListViewWithPageHeaderTest;
57+ friend class ListViewWithPageHeaderTestSection;
58+
59+public:
60+ ListViewWithPageHeader();
61+ ~ListViewWithPageHeader();
62+
63+ QAbstractItemModel *model() const;
64+ void setModel(QAbstractItemModel *model);
65+
66+ QQmlComponent *delegate() const;
67+ void setDelegate(QQmlComponent *delegate);
68+
69+ QQuickItem *header() const;
70+ void setHeader(QQuickItem *header);
71+
72+ QQmlComponent *sectionDelegate() const;
73+ void setSectionDelegate(QQmlComponent *delegate);
74+
75+ QString sectionProperty() const;
76+ void setSectionProperty(const QString &property);
77+
78+ bool forceNoClip() const;
79+ void setForceNoClip(bool noClip);
80+
81+ Q_INVOKABLE void positionAtBeginning();
82+ Q_INVOKABLE void showHeader();
83+
84+Q_SIGNALS:
85+ void modelChanged();
86+ void delegateChanged();
87+ void headerChanged();
88+ void sectionDelegateChanged();
89+ void sectionPropertyChanged();
90+ void forceNoClipChanged();
91+
92+protected:
93+ void componentComplete();
94+ void viewportMoved(Qt::Orientations orient);
95+ qreal minYExtent() const;
96+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
97+ void updatePolish();
98+
99+private Q_SLOTS:
100+ void itemCreated(int modelIndex, QQuickItem *item);
101+ void onContentHeightChanged();
102+ void onContentWidthChanged();
103+ void onHeightChanged();
104+ void onModelUpdated(const QQuickChangeSet &changeSet, bool reset);
105+ void onShowHeaderAnimationFinished();
106+
107+private:
108+ class ListItem
109+ {
110+ public:
111+ qreal height() const;
112+
113+ qreal y() const;
114+ void setY(qreal newY);
115+
116+ bool culled() const;
117+ void setCulled(bool culled);
118+
119+ QQuickItem *m_item;
120+ QQuickItem *m_sectionItem;
121+ };
122+
123+ void createDelegateModel();
124+
125+ void layout();
126+ void refill();
127+ bool addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous);
128+ bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
129+ ListItem *createItem(int modelIndex, bool asynchronous);
130+
131+ void adjustMinYExtent();
132+ void updateClipItem();
133+ void headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY);
134+ ListItem *itemAtIndex(int modelIndex) const; // Returns the item at modelIndex if has been created
135+ void releaseItem(ListItem *item);
136+ void reallyReleaseItem(ListItem *item);
137+ void updateWatchedRoles();
138+ QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
139+ QQuickItem *getSectionItem(const QString &sectionText);
140+
141+ QQuickVisualDataModel *m_delegateModel;
142+
143+ // Index we are waiting because we requested it asynchronously
144+ int m_asyncRequestedIndex;
145+
146+ // Used to only give a warning once if the delegate does not return objects
147+ bool m_delegateValidated;
148+
149+ // Visible indexes, [0] is m_firstValidIndex, [0+1] is m_firstValidIndex +1, ...
150+ QList<ListItem *> m_visibleItems;
151+ int m_firstVisibleIndex;
152+
153+ qreal m_minYExtent;
154+
155+ QQuickItem *m_clipItem;
156+
157+ // If any of the heights has changed
158+ // or new items have been added/removed
159+ bool m_contentHeightDirty;
160+
161+ QQuickItem *m_headerItem;
162+ qreal m_previousContentY;
163+ qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
164+ // i.e. it's being shown after dragging down in the middle of the list
165+ QQuickNumberAnimation *m_headerShowAnimation;
166+
167+ QQmlComponent *m_sectionDelegate;
168+ QString m_sectionProperty;
169+ QQuickItem *m_topSectionItem;
170+
171+ bool m_forceNoClip;
172+ bool m_inLayout;
173+
174+ // Qt 5.0 doesn't like releasing the items just after itemCreated
175+ // so we delay the releasing until the next updatePolish
176+ QList<ListItem *> m_itemsToRelease;
177+};
178+
179+
180+#endif
plugins/ListViewWithPageHeader/plugin.cppnew file+29
@@ -0,0 +1,29 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#include "plugin.h"
19+
20+#include "listviewwithpageheader.h"
21+
22+#include <QAbstractItemModel>
23+
24+void ListViewWithPageHeaderPlugin::registerTypes(const char *uri)
25+{
26+ Q_ASSERT(uri == QLatin1String("ListViewWithPageHeader"));
27+ qmlRegisterType<QAbstractItemModel>();
28+ qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
29+}
plugins/ListViewWithPageHeader/plugin.hnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2012 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#ifndef LISTVIEWWITHPAGEHEADER_PLUGIN_H
19+#define LISTVIEWWITHPAGEHEADER_PLUGIN_H
20+
21+#include <QtQml/QQmlEngine>
22+#include <QtQml/QQmlExtensionPlugin>
23+
24+class ListViewWithPageHeaderPlugin : public QQmlExtensionPlugin
25+{
26+ Q_OBJECT
27+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
28+
29+public:
30+ void registerTypes(const char *uri);
31+};
32+
33+#endif
plugins/ListViewWithPageHeader/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module ListViewWithPageHeader
2+plugin ListViewWithPageHeader-qml
plugins/Ubuntu/Gestures/AxisVelocityCalculator.cpp+31−16
@@ -21,9 +21,10 @@
2121#include "AxisVelocityCalculator.h"
2222#include <QtCore/QElapsedTimer>
2323
24−class RealTimeSource : public AxisVelocityCalculator::TimeSource {
24+class RealTimeSource : public UbuntuGestures::TimeSource {
2525public:
26− RealTimeSource() {
26+ RealTimeSource()
27+ : UbuntuGestures::TimeSource() {
2728 m_timer.start();
2829 }
2930 virtual qint64 msecsSinceReference() {
@@ -33,23 +34,17 @@ private:
3334 QElapsedTimer m_timer;
3435};
3536
36−
3737AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
38− : AxisVelocityCalculator(new RealTimeSource, parent)
39−{
40−}
41−
42−AxisVelocityCalculator::AxisVelocityCalculator(TimeSource *timeSource, QObject *parent)
4338 : QObject(parent)
44− , m_timeSource(timeSource)
39+ , m_timeSource(new RealTimeSource)
4540 , m_trackedPosition(0.0)
4641{
42+ m_timeSource->setParent(this);
4743 reset();
4844}
4945
5046AxisVelocityCalculator::~AxisVelocityCalculator()
5147{
52− delete m_timeSource;
5348}
5449
5550qreal AxisVelocityCalculator::trackedPosition() const
@@ -59,13 +54,17 @@ qreal AxisVelocityCalculator::trackedPosition() const
5954
6055void AxisVelocityCalculator::setTrackedPosition(qreal newPosition)
6156{
62− if (newPosition == m_trackedPosition) {
63− return;
57+ processMovement(newPosition - m_trackedPosition);
58+
59+ if (newPosition != m_trackedPosition) {
60+ m_trackedPosition = newPosition;
61+ Q_EMIT trackedPositionChanged(newPosition);
6462 }
63+}
6564
66− processMovement(newPosition - m_trackedPosition);
67− m_trackedPosition = newPosition;
68− Q_EMIT trackedPositionChanged(newPosition);
65+void AxisVelocityCalculator::updateIdleTime()
66+{
67+ processMovement(0);
6968}
7069
7170void AxisVelocityCalculator::processMovement(qreal movement)
@@ -83,11 +82,12 @@ void AxisVelocityCalculator::processMovement(qreal movement)
8382 m_samplesWrite = (m_samplesWrite + 1) % MAX_SAMPLES;
8483}
8584
86−qreal AxisVelocityCalculator::calculate() const
85+qreal AxisVelocityCalculator::calculate()
8786{
8887 if (numSamples() < MIN_SAMPLES_NEEDED) {
8988 return 0.0;
9089 }
90+ updateIdleTime(); // consider the time elapsed since the last update and now
9191
9292 int lastIndex;
9393 if (m_samplesWrite == 0) {
@@ -141,3 +141,18 @@ int AxisVelocityCalculator::numSamples() const
141141 }
142142 }
143143}
144+
145+void AxisVelocityCalculator::setTimeSource(UbuntuGestures::TimeSource *timeSource)
146+{
147+ if (m_timeSource && m_timeSource->parent() == this)
148+ delete m_timeSource;
149+
150+ m_timeSource = timeSource;
151+
152+ if (numSamples() > 0) {
153+ qWarning("AxisVelocityCalculator: changing time source while there are samples present.");
154+ // Any existent samples are based on the old time source and are, therefore, incompatible
155+ // with this new one.
156+ reset();
157+ }
158+}
plugins/Ubuntu/Gestures/AxisVelocityCalculator.h+31−20
@@ -25,6 +25,19 @@
2525#include <stdint.h>
2626#include <QtCore/QObject>
2727
28+namespace UbuntuGestures {
29+/*
30+ Interface for a time source.
31+ */
32+class UBUNTUGESTURES_EXPORT TimeSource : public QObject {
33+ Q_OBJECT
34+public:
35+ virtual ~TimeSource() {}
36+ /* Returns the current time in milliseconds since some reference time in the past. */
37+ virtual qint64 msecsSinceReference() = 0;
38+};
39+}
40+
2841/*
2942 Estimates the current velocity of a finger based on recent movement along an axis
3043
@@ -59,27 +72,11 @@ class UBUNTUGESTURES_EXPORT AxisVelocityCalculator : public QObject
5972 NOTIFY trackedPositionChanged)
6073public:
6174
62− /*
63− Interface for a time source.
64− */
65− class TimeSource {
66− public:
67− virtual ~TimeSource() {}
68− /* Returns the current time in milliseconds since some reference time in the past. */
69− virtual qint64 msecsSinceReference() = 0;
70− };
71−
7275 /*
7376 Regular constructor
7477 */
7578 AxisVelocityCalculator(QObject *parent = 0);
7679
77− /*
78− Extended constructor useful for testing purposes where you can inject
79− a fake time source implementation.
80− */
81− AxisVelocityCalculator(TimeSource *timeSource, QObject *parent = 0);
82−
8380 virtual ~AxisVelocityCalculator();
8481
8582 qreal trackedPosition() const;
@@ -88,7 +85,7 @@ public:
8885 /*
8986 Calculates the finger velocity, in axis units/millisecond
9087 */
91− Q_INVOKABLE qreal calculate() const;
88+ Q_INVOKABLE qreal calculate();
9289
9390 /*
9491 Removes all stored movements from previous calls to setTrackedPosition()
@@ -97,6 +94,11 @@ public:
9794
9895 int numSamples() const;
9996
97+ /*
98+ Replaces the TimeSource with the given one. Useful for testing purposes.
99+ */
100+ void setTimeSource(UbuntuGestures::TimeSource *timeSource);
101+
100102 /*
101103 The minimum amount of samples needed for a velocity calculation.
102104 */
@@ -105,18 +107,27 @@ public:
105107 /*
106108 Maximum number of movement samples stored
107109 */
108− static const int MAX_SAMPLES = 10;
110+ static const int MAX_SAMPLES = 50;
109111
110112 /*
111113 Age of the oldest sample considered in the velocity calculations, in
112114 milliseconds, compared to the most recent one.
113115 */
114− static const int AGE_OLDEST_SAMPLE = 200;
116+ static const int AGE_OLDEST_SAMPLE = 100;
115117
116118Q_SIGNALS:
117119 void trackedPositionChanged(qreal value);
118120
119121private:
122+
123+ /*
124+ Inform that trackedPosition remained motionless since the time it was
125+ last changed.
126+
127+ It's the same as calling setTrackedPosition(trackedPosition())
128+ */
129+ void updateIdleTime();
130+
120131 /*
121132 How much the finger has moved since processMovement() was last called.
122133 */
@@ -134,7 +145,7 @@ private:
134145 int m_samplesRead; /* index of the oldest sample available. -1 if buffer is empty */
135146 int m_samplesWrite; /* index where the next sample will be written */
136147
137− TimeSource *m_timeSource;
148+ UbuntuGestures::TimeSource *m_timeSource;
138149
139150 qreal m_trackedPosition;
140151};
plugins/Ubuntu/Gestures/Direction.cpp+5
@@ -25,3 +25,8 @@ bool Direction::isVertical(Direction::Type type)
2525{
2626 return type == Direction::Upwards || type == Direction::Downwards;
2727}
28+
29+bool Direction::isPositive(Direction::Type type)
30+{
31+ return type == Rightwards || type == Downwards;
32+}
plugins/Ubuntu/Gestures/Direction.h+1
@@ -38,6 +38,7 @@ public:
3838
3939 Q_INVOKABLE static bool isHorizontal(Direction::Type type);
4040 Q_INVOKABLE static bool isVertical(Direction::Type type);
41+ Q_INVOKABLE static bool isPositive(Direction::Type type);
4142};
4243
4344#endif // DIRECTION_H
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+59−8
@@ -141,12 +141,9 @@ void DirectionalDragArea::setRecognitionTimer(UbuntuGestures::AbstractTimer *tim
141141 }
142142}
143143
144−void DirectionalDragArea::setAxisVelocityCalculator(AxisVelocityCalculator *newVelCalc)
144+void DirectionalDragArea::setTimeSource(UbuntuGestures::TimeSource *timeSource)
145145{
146− if (m_velocityCalculator->parent() == this)
147− delete m_velocityCalculator;
148−
149− m_velocityCalculator = newVelCalc;
146+ m_velocityCalculator->setTimeSource(timeSource);
150147}
151148
152149qreal DirectionalDragArea::distance() const
@@ -158,6 +155,15 @@ qreal DirectionalDragArea::distance() const
158155 }
159156}
160157
158+qreal DirectionalDragArea::sceneDistance() const
159+{
160+ if (Direction::isHorizontal(m_direction)) {
161+ return m_previousScenePos.x() - m_startScenePos.x();
162+ } else {
163+ return m_previousScenePos.y() - m_startScenePos.y();
164+ }
165+}
166+
161167qreal DirectionalDragArea::touchX() const
162168{
163169 return m_previousPos.x();
@@ -168,6 +174,16 @@ qreal DirectionalDragArea::touchY() const
168174 return m_previousPos.y();
169175}
170176
177+qreal DirectionalDragArea::touchSceneX() const
178+{
179+ return m_previousScenePos.x();
180+}
181+
182+qreal DirectionalDragArea::touchSceneY() const
183+{
184+ return m_previousScenePos.y();
185+}
186+
171187void DirectionalDragArea::touchEvent(QTouchEvent *event)
172188{
173189 if (!isEnabled() || !isVisible()) {
@@ -195,15 +211,22 @@ void DirectionalDragArea::touchEvent_absent(QTouchEvent *event)
195211{
196212 if ((event->touchPointStates() && (Qt::TouchPointPressed || Qt::TouchPointMoved))
197213 && event->touchPoints().count() == 1) {
198− m_startPos = event->touchPoints()[0].pos();
199− m_touchId = event->touchPoints()[0].id();
214+ const QTouchEvent::TouchPoint &touchPoint = event->touchPoints()[0];
215+ m_startPos = touchPoint.pos();
216+ m_startScenePos = touchPoint.scenePos();
217+ m_touchId = touchPoint.id();
200218 m_dampedPos.reset(m_startPos);
201219 updateVelocityCalculator(m_startPos);
202220 m_velocityCalculator->reset();
203221 m_numSamplesOnLastSpeedCheck = 0;
204222 m_silenceTime = 0;
205223 setPreviousPos(m_startPos);
206− setStatus(Undecided);
224+ setPreviousScenePos(m_startScenePos);
225+
226+ if (m_distanceThreshold > 0)
227+ setStatus(Undecided);
228+ else
229+ setStatus(Recognized);
207230 }
208231}
209232
@@ -241,6 +264,7 @@ void DirectionalDragArea::touchEvent_undecided(QTouchEvent *event)
241264 }
242265
243266 setPreviousPos(touchPos);
267+ setPreviousScenePos(touchPoint->scenePos());
244268
245269 if (movedFarEnough(touchPos)) {
246270 setStatus(Recognized);
@@ -252,6 +276,7 @@ void DirectionalDragArea::touchEvent_recognized(QTouchEvent *event)
252276 const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
253277
254278 setPreviousPos(touchPoint->pos());
279+ setPreviousScenePos(touchPoint->scenePos());
255280
256281 if (touchPoint->state() == Qt::TouchPointReleased) {
257282 setStatus(WaitingForTouch);
@@ -366,6 +391,10 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
366391 m_recognitionTimer->start();
367392 Q_EMIT draggingChanged(true);
368393 break;
394+ case Recognized:
395+ if (oldStatus == WaitingForTouch)
396+ Q_EMIT draggingChanged(true);
397+ break;
369398 case Rejected:
370399 Q_EMIT draggingChanged(false);
371400 break;
@@ -397,6 +426,28 @@ void DirectionalDragArea::setPreviousPos(QPointF point)
397426 }
398427}
399428
429+void DirectionalDragArea::setPreviousScenePos(QPointF point)
430+{
431+ Q_ASSERT(m_status != Rejected);
432+
433+ bool xChanged = m_previousScenePos.x() != point.x();
434+ bool yChanged = m_previousScenePos.y() != point.y();
435+
436+ m_previousScenePos = point;
437+
438+ if (xChanged) {
439+ Q_EMIT touchSceneXChanged(point.x());
440+ if (Direction::isHorizontal(m_direction))
441+ Q_EMIT sceneDistanceChanged(sceneDistance());
442+ }
443+
444+ if (yChanged) {
445+ Q_EMIT touchSceneYChanged(point.y());
446+ if (Direction::isVertical(m_direction))
447+ Q_EMIT sceneDistanceChanged(sceneDistance());
448+ }
449+}
450+
400451void DirectionalDragArea::updateVelocityCalculator(QPointF point)
401452{
402453 if (Direction::isHorizontal(m_direction)) {
plugins/Ubuntu/Gestures/DirectionalDragArea.h+21−3
@@ -60,10 +60,18 @@ class UBUNTUGESTURES_EXPORT DirectionalDragArea : public QQuickItem {
6060 // DirectionalDragArea's direction.
6161 Q_PROPERTY(qreal distance READ distance NOTIFY distanceChanged)
6262
63− // Position of the touch point performing the drag.
63+ // The distance travelled by the finger along the axis specified by
64+ // DirectionalDragArea's direction in scene coordinates
65+ Q_PROPERTY(qreal sceneDistance READ sceneDistance NOTIFY sceneDistanceChanged)
66+
67+ // Position of the touch point performing the drag relative to this item.
6468 Q_PROPERTY(qreal touchX READ touchX NOTIFY touchXChanged)
6569 Q_PROPERTY(qreal touchY READ touchY NOTIFY touchYChanged)
6670
71+ // Position of the touch point performing the drag, in scene's coordinate system
72+ Q_PROPERTY(qreal touchSceneX READ touchSceneX NOTIFY touchSceneXChanged)
73+ Q_PROPERTY(qreal touchSceneY READ touchSceneY NOTIFY touchSceneYChanged)
74+
6775 // The current status of the directional drag gesture area.
6876 Q_PROPERTY(Status status READ status NOTIFY statusChanged)
6977
@@ -146,10 +154,14 @@ public:
146154 Status status() const { return m_status; }
147155
148156 qreal distance() const;
157+ qreal sceneDistance() const;
149158
150159 qreal touchX() const;
151160 qreal touchY() const;
152161
162+ qreal touchSceneX() const;
163+ qreal touchSceneY() const;
164+
153165 bool dragging() const { return (m_status == Undecided) || (m_status == Recognized); }
154166
155167 qreal maxDeviation() const { return m_dampedPos.maxDelta(); }
@@ -172,14 +184,15 @@ public:
172184 // Useful for providing a fake timer when testing.
173185 void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
174186
175− // Useful for testing, where a calculator with a fake time source can be supplied
176− void setAxisVelocityCalculator(AxisVelocityCalculator *velCalc);
187+ // Useful for testing, where a fake time source can be supplied
188+ void setTimeSource(UbuntuGestures::TimeSource *timeSource);
177189
178190Q_SIGNALS:
179191 void directionChanged(Direction::Type direction);
180192 void statusChanged(Status value);
181193 void draggingChanged(bool value);
182194 void distanceChanged(qreal value);
195+ void sceneDistanceChanged(qreal value);
183196 void maxDeviationChanged(qreal value);
184197 void wideningAngleChanged(qreal value);
185198 void distanceThresholdChanged(qreal value);
@@ -187,6 +200,8 @@ Q_SIGNALS:
187200 void maxSilenceTimeChanged(int value);
188201 void touchXChanged(qreal value);
189202 void touchYChanged(qreal value);
203+ void touchSceneXChanged(qreal value);
204+ void touchSceneYChanged(qreal value);
190205
191206protected:
192207 virtual void touchEvent(QTouchEvent *event);
@@ -205,12 +220,15 @@ private:
205220 const QTouchEvent::TouchPoint *fetchTargetTouchPoint(QTouchEvent *event);
206221 void setStatus(Status newStatus);
207222 void setPreviousPos(QPointF point);
223+ void setPreviousScenePos(QPointF point);
208224 void updateVelocityCalculator(QPointF point);
209225
210226 Status m_status;
211227
212228 QPointF m_startPos;
229+ QPointF m_startScenePos;
213230 QPointF m_previousPos;
231+ QPointF m_previousScenePos;
214232 int m_touchId;
215233
216234 // A movement damper is used in some of the gesture recognition calculations
po/ar.po+37−45
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-22 16:15+0000\n"
1212"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
1313"Language-Team: Arabic <ar@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-23 05:56+0000\n"
18−"X-Generator: Launchpad (build 16677)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "متوفرة للتنزيل"
109109msgid "Apps"
110110msgstr "تطبيقات"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "تطبيقات مألوفة"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "الأشخاص المفضلون"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "أشخاص كانوا على اتصال مؤخرا"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "آخر الصوتيات المشغلة"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "فيديوهات رائجة على الإنترنت"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "الرئيسية"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "موسيقى"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "المفضلات"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "على اتصال موخرا"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "أشخاص جدد"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "A-Z"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "أشخاص"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "الشائع على الإنترنت"
@@ -193,7 +165,7 @@ msgstr "النجوم:"
193165msgid "Author:"
194166msgstr "المؤلف:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr "مكالمة طوارئ"
199171
@@ -234,19 +206,39 @@ msgstr "الجهاز"
234206msgid "Flight mode"
235207msgstr "نمط الطيران"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "ابحث"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "عذراً، لا يوجد ما يطابق بحثك."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "الشاشة الرئيسية"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
252−msgstr "رجاءً أدخِل %1:"
219+msgid "Please enter %1"
220+msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "أشخاص"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "الشاشة الرئيسية"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "الأشخاص المفضلون"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "أشخاص كانوا على اتصال مؤخرا"
233+
234+#~ msgid "A-Z"
235+#~ msgstr "A-Z"
236+
237+#~ msgid "Recently in touch"
238+#~ msgstr "على اتصال موخرا"
239+
240+#~ msgid "New Contacts"
241+#~ msgstr "أشخاص جدد"
242+
243+#~ msgid "Favourites"
244+#~ msgstr "المفضلات"
po/az.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Azerbaijani <az@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Tətbiqlər"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Ev"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Musiqi"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "İnsanlar"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Axtar"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Əsas Ekran"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "İnsanlar"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Əsas Ekran"
po/bg.po+24−44
@@ -7,7 +7,7 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-19 15:47+0000\n"
1212"Last-Translator: Miroslav E. Hadzhiev (Хаджиев) "
1313"<miroslav.hadzhiev@gmail.com>\n"
@@ -15,8 +15,8 @@ msgstr ""
1515"MIME-Version: 1.0\n"
1616"Content-Type: text/plain; charset=UTF-8\n"
1717"Content-Transfer-Encoding: 8bit\n"
18−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
19−"X-Generator: Launchpad (build 16673)\n"
18+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
19+"X-Generator: Launchpad (build 16681)\n"
2020
2121#: Applications/applications.js:23
2222msgid "Phone"
@@ -110,27 +110,19 @@ msgstr ""
110110msgid "Apps"
111111msgstr "Приложения"
112112
113−#: Dash/DashHome.qml:43
113+#: Dash/DashHome.qml:40
114114msgid "Frequent Apps"
115115msgstr ""
116116
117−#: Dash/DashHome.qml:46
118−msgid "Favourite People"
119−msgstr ""
120−
121−#: Dash/DashHome.qml:49
122−msgid "People Recently in Touch"
123−msgstr ""
124−
125−#: Dash/DashHome.qml:52
117+#: Dash/DashHome.qml:43
126118msgid "Recent Music"
127119msgstr ""
128120
129−#: Dash/DashHome.qml:55
121+#: Dash/DashHome.qml:46
130122msgid "Videos Popular Online"
131123msgstr ""
132124
133−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
125+#: Dash/DashHome.qml:175
134126msgid "Home"
135127msgstr "Начало"
136128
@@ -154,26 +146,6 @@ msgstr ""
154146msgid "Music"
155147msgstr "Музика"
156148
157−#: Dash/DashPeople.qml:31
158−msgid "Favourites"
159−msgstr "Любими"
160−
161−#: Dash/DashPeople.qml:32
162−msgid "Recently in touch"
163−msgstr ""
164−
165−#: Dash/DashPeople.qml:33
166−msgid "New Contacts"
167−msgstr ""
168−
169−#: Dash/DashPeople.qml:34
170−msgid "A-Z"
171−msgstr "А-Я"
172−
173−#: Dash/DashPeople.qml:123
174−msgid "People"
175−msgstr "Хора"
176−
177149#: Dash/DashVideos.qml:31
178150msgid "Popular Online"
179151msgstr ""
@@ -194,7 +166,7 @@ msgstr ""
194166msgid "Author:"
195167msgstr "Автор:"
196168
197−#: Greeter/Lockscreen.qml:126
169+#: Greeter/Lockscreen.qml:133
198170msgid "Emergency call"
199171msgstr ""
200172
@@ -235,19 +207,27 @@ msgstr "Устройство"
235207msgid "Flight mode"
236208msgstr ""
237209
238−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
210+#: Panel/SearchIndicator.qml:26
239211msgid "Search"
240212msgstr "Търсене"
241213
242−#: plugins/Unity/lens.cpp:333
214+#: plugins/Unity/scope.cpp:268
243215msgid "Sorry, there is nothing that matches your search."
244216msgstr "Съжаляваме, няма нищо, което да отговаря на вашето търсене."
245217
246−#: plugins/Unity/lenses.cpp:39
247−msgid "Home screen"
248−msgstr "Начален екран"
249−
250−#: Shell.qml:380
218+#: Shell.qml:383
251219#, qt-format
252−msgid "Please enter %1:"
220+msgid "Please enter %1"
253221msgstr ""
222+
223+#~ msgid "Favourites"
224+#~ msgstr "Любими"
225+
226+#~ msgid "People"
227+#~ msgstr "Хора"
228+
229+#~ msgid "A-Z"
230+#~ msgstr "А-Я"
231+
232+#~ msgid "Home screen"
233+#~ msgstr "Начален екран"
po/ca.po+24−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Catalan <ca@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Disponibles per baixar"
109109msgid "Apps"
110110msgstr "Aplicacions"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Aplicacions freqüents"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Gent preferida"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "Gent amb qui heu parlat"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Música recent"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Vídeos populars en línia"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Inici"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Música"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Gent"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,27 @@ msgstr "Dispositiu"
234206msgid "Flight mode"
235207msgstr "Mode d'avió"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Cerca"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "No hi ha res que coincideixi amb la cerca"
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Pantalla d'inici"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Gent"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Pantalla d'inici"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Gent preferida"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "Gent amb qui heu parlat"
po/de.po+38−46
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
11−"PO-Revision-Date: 2013-06-23 18:17+0000\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11+"PO-Revision-Date: 2013-06-29 12:53+0000\n"
1212"Last-Translator: Phillip Sz <Unknown>\n"
1313"Language-Team: German <de@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-24 05:27+0000\n"
18−"X-Generator: Launchpad (build 16677)\n"
17+"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18+"X-Generator: Launchpad (build 16692)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Zum Herunterladen verfügbar"
109109msgid "Apps"
110110msgstr "Anwendungen"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Häufig genutzte Anwendungen"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Lieblingspersonen"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "Zuletzt kontaktierte Personen"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Zuletzt gehörte Musik"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Beliebte Online-Videos"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Start"
135127
@@ -153,26 +145,6 @@ msgstr "Top Tabellenplatz"
153145msgid "Music"
154146msgstr "Musik"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "Favoriten"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "Kürzlich im Gespräch"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "Neue Kontakte"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "A-Z"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Personen"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "Online Beliebt"
@@ -193,7 +165,7 @@ msgstr "Darsteller:"
193165msgid "Author:"
194166msgstr "Autor:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr "Notruf"
199171
@@ -234,19 +206,39 @@ msgstr "Gerät"
234206msgid "Flight mode"
235207msgstr "Flugmodus"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Suchen"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Entschuldigung, es wurden keine Treffer erzielt."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Startseite"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
252−msgstr "Bitte geben Sie %1 ein:"
219+msgid "Please enter %1"
220+msgstr "Bitte geben Sie %1 ein"
221+
222+#~ msgid "People"
223+#~ msgstr "Personen"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Startseite"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Lieblingspersonen"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "Zuletzt kontaktierte Personen"
233+
234+#~ msgid "A-Z"
235+#~ msgstr "A-Z"
236+
237+#~ msgid "Recently in touch"
238+#~ msgstr "Kürzlich im Gespräch"
239+
240+#~ msgid "New Contacts"
241+#~ msgstr "Neue Kontakte"
242+
243+#~ msgid "Favourites"
244+#~ msgstr "Favoriten"
po/el.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Greek <el@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Εφαρμογές"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Αρχή"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Μουσική"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Πρόσωπα"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Αναζήτηση"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να ταιριάζει στην αναζήτησή σας."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Αρχική οθόνη"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Πρόσωπα"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Αρχική οθόνη"
po/en_AU.po+36−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-18 20:36+0000\n"
1212"Last-Translator: Jackson Doak <Doak.jackson@gmail.com>\n"
1313"Language-Team: English (Australia) <en_AU@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Available for download"
109109msgid "Apps"
110110msgstr "Apps"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Frequent Apps"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Favourite People"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "People Recently in Touch"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Recent Music"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Videos Popular Online"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Home"
135127
@@ -153,26 +145,6 @@ msgstr "Top Charting"
153145msgid "Music"
154146msgstr "Music"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "Favourites"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "Recently in touch"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "New Contacts"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "A-Z"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "People"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "Popular Online"
@@ -193,7 +165,7 @@ msgstr "Starring:"
193165msgid "Author:"
194166msgstr "Author:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,39 @@ msgstr "Device"
234206msgid "Flight mode"
235207msgstr "Flight mode"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Search"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Sorry, there is nothing that matches your search."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Home screen"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "People"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Home screen"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Favourite People"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "People Recently in Touch"
233+
234+#~ msgid "A-Z"
235+#~ msgstr "A-Z"
236+
237+#~ msgid "Recently in touch"
238+#~ msgstr "Recently in touch"
239+
240+#~ msgid "New Contacts"
241+#~ msgstr "New Contacts"
242+
243+#~ msgid "Favourites"
244+#~ msgstr "Favourites"
po/en_GB.po+38−46
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
11−"PO-Revision-Date: 2013-06-23 22:34+0000\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11+"PO-Revision-Date: 2013-06-27 00:22+0000\n"
1212"Last-Translator: Andi Chandler <Unknown>\n"
1313"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-24 05:27+0000\n"
18−"X-Generator: Launchpad (build 16677)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Available for download"
109109msgid "Apps"
110110msgstr "Apps"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Frequent Apps"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Favourite People"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "People Recently in Touch"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Recent Music"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Videos Popular Online"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Home"
135127
@@ -153,26 +145,6 @@ msgstr "Top Charting"
153145msgid "Music"
154146msgstr "Music"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "Favourites"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "Recently in touch"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "New Contacts"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "A-Z"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "People"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "Popular Online"
@@ -193,7 +165,7 @@ msgstr "Starring:"
193165msgid "Author:"
194166msgstr "Author:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr "Emergency call"
199171
@@ -234,19 +206,39 @@ msgstr "Device"
234206msgid "Flight mode"
235207msgstr "Flight mode"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Search"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Sorry, there is nothing that matches your search."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Home screen"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
252−msgstr "Please enter %1:"
219+msgid "Please enter %1"
220+msgstr "Please enter %1"
221+
222+#~ msgid "Favourite People"
223+#~ msgstr "Favourite People"
224+
225+#~ msgid "People Recently in Touch"
226+#~ msgstr "People Recently in Touch"
227+
228+#~ msgid "People"
229+#~ msgstr "People"
230+
231+#~ msgid "A-Z"
232+#~ msgstr "A-Z"
233+
234+#~ msgid "Recently in touch"
235+#~ msgstr "Recently in touch"
236+
237+#~ msgid "New Contacts"
238+#~ msgstr "New Contacts"
239+
240+#~ msgid "Favourites"
241+#~ msgstr "Favourites"
242+
243+#~ msgid "Home screen"
244+#~ msgstr "Home screen"
po/eo.po+12−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Esperanto <eo@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr ""
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr ""
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr ""
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr ""
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,15 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr ""
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr ""
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
po/es.po+36−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-16 23:44+0000\n"
1212"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
1313"Language-Team: Spanish <es@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Disponibles para descargar"
109109msgid "Apps"
110110msgstr "Aplicaciones"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Aplicaciones frecuentes"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Gente favorita"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "Gente contactada recientemente"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Música reciente"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Vídeos populares en línea"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Inicio"
135127
@@ -153,26 +145,6 @@ msgstr "Mejor posicionadas"
153145msgid "Music"
154146msgstr "Música"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "Favoritos"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "Contactados recientemente"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "Contactos nuevos"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "A-Z"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Gente"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "Populares en línea"
@@ -193,7 +165,7 @@ msgstr "Protagonistas:"
193165msgid "Author:"
194166msgstr "Autor:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,39 @@ msgstr "Dispositivo"
234206msgid "Flight mode"
235207msgstr "Modo de vuelo"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Buscar"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "No hay nada que coincida con su búsqueda."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Pantalla de inicio"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Gente"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Pantalla de inicio"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Gente favorita"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "Gente contactada recientemente"
233+
234+#~ msgid "Recently in touch"
235+#~ msgstr "Contactados recientemente"
236+
237+#~ msgid "Favourites"
238+#~ msgstr "Favoritos"
239+
240+#~ msgid "A-Z"
241+#~ msgstr "A-Z"
242+
243+#~ msgid "New Contacts"
244+#~ msgstr "Contactos nuevos"
po/fi.po+33−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-10 16:19+0000\n"
1212"Last-Translator: Jiri Grönroos <Unknown>\n"
1313"Language-Team: Finnish <fi@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Ladattavissa"
109109msgid "Apps"
110110msgstr "Sovellukset"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Yleisimmät sovellukset"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Suosikkihenkilöt"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "Viimeksi yhteydessä olleet henkilöt"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Viimeisin musiikki"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Suositut verkkovideot"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Kotinäyttö"
135127
@@ -153,26 +145,6 @@ msgstr "Nousukiidossa"
153145msgid "Music"
154146msgstr "Musiikki"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "Suosikit"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "Viimeksi yhteydessä"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "Uudet yhteystiedot"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Ihmiset"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "Suosittua verkossa"
@@ -193,7 +165,7 @@ msgstr "Pääosissa:"
193165msgid "Author:"
194166msgstr "Laatinut:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,36 @@ msgstr "Laite"
234206msgid "Flight mode"
235207msgstr "Lentokonetila"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Hae"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Hakuun täsmääviä tuloksia ei löydy."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Kotinäyttö"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Ihmiset"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Kotinäyttö"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Suosikkihenkilöt"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "Viimeksi yhteydessä olleet henkilöt"
233+
234+#~ msgid "Favourites"
235+#~ msgstr "Suosikit"
236+
237+#~ msgid "Recently in touch"
238+#~ msgstr "Viimeksi yhteydessä"
239+
240+#~ msgid "New Contacts"
241+#~ msgstr "Uudet yhteystiedot"
po/fo.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Faroese <fo@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Nýtsluskipanir"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Heim"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Tónleikur"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Fólk"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Leita"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Heimaskíggi"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Fólk"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Heimaskíggi"
po/fr.po+71−82
@@ -7,63 +7,63 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11+"PO-Revision-Date: 2013-06-26 15:11+0000\n"
12+"Last-Translator: Anne <anneonyme017@gmail.com>\n"
1313"Language-Team: French <fr@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
22−msgstr ""
22+msgstr "Téléphone"
2323
2424#: Applications/applications.js:29
2525msgid "Camera"
26−msgstr ""
26+msgstr "Appareil photo"
2727
2828#: Applications/applications.js:35
2929msgid "Gallery"
30−msgstr ""
30+msgstr "Galerie"
3131
3232#: Applications/applications.js:40
3333msgid "Facebook"
34−msgstr ""
34+msgstr "Facebook"
3535
3636#: Applications/applications.js:46
3737msgid "Browser"
38−msgstr ""
38+msgstr "Navigateur"
3939
4040#: Applications/applications.js:51
4141msgid "Twitter"
42−msgstr ""
42+msgstr "Twitter"
4343
4444#: Applications/applications.js:57
4545msgid "GMail"
46−msgstr ""
46+msgstr "GMail"
4747
4848#: Applications/applications.js:62
4949msgid "Weather"
50−msgstr ""
50+msgstr "Météo"
5151
5252#: Applications/applications.js:68
5353msgid "Notepad"
54−msgstr ""
54+msgstr "Bloc-notes"
5555
5656#: Applications/applications.js:74
5757msgid "Calendar"
58−msgstr ""
58+msgstr "Agenda"
5959
6060#: Applications/applications.js:80
6161msgid "Media Player"
62−msgstr ""
62+msgstr "Lecteur multimédia"
6363
6464#: Applications/applications.js:86
6565msgid "Evernote"
66−msgstr ""
66+msgstr "Evernote"
6767
6868#: Applications/applications.js:91
6969msgid "Map"
@@ -71,27 +71,27 @@ msgstr ""
7171
7272#: Applications/applications.js:96
7373msgid "Pinterest"
74−msgstr ""
74+msgstr "Pinterest"
7575
7676#: Applications/applications.js:101
7777msgid "SoundCloud"
78−msgstr ""
78+msgstr "SoundCloud"
7979
8080#: Applications/applications.js:106
8181msgid "Wikipedia"
82−msgstr ""
82+msgstr "Wikipédia"
8383
8484#: Applications/applications.js:111
8585msgid "YouTube"
86−msgstr ""
86+msgstr "YouTube"
8787
8888#: Components/PageHeader.qml:300
8989msgid "Recent searches"
90−msgstr ""
90+msgstr "Recherches récentes"
9191
9292#: Dash/DashApps.qml:65
9393msgid "Running apps"
94−msgstr ""
94+msgstr "Applications en cours d’exécution"
9595
9696#: Dash/DashApps.qml:68
9797msgid "Frequently used"
@@ -99,7 +99,7 @@ msgstr ""
9999
100100#: Dash/DashApps.qml:71
101101msgid "Installed"
102−msgstr ""
102+msgstr "Installées"
103103
104104#: Dash/DashApps.qml:74
105105msgid "Available for download"
@@ -109,29 +109,21 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Applications"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114−msgstr ""
115−
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
114+msgstr "Applications fréquemment utilisées"
119115
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126−msgstr ""
118+msgstr "Musique récente"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130−msgstr ""
122+msgstr "Vidéos populaires en ligne"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134−msgstr ""
126+msgstr "Accueil"
135127
136128#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
137129msgid "Featured"
@@ -143,7 +135,7 @@ msgstr ""
143135
144136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
145137msgid "New Releases"
146−msgstr ""
138+msgstr "Nouveautés"
147139
148140#: Dash/DashMusic.qml:30
149141msgid "Top Charting"
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Musique"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr ""
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -183,44 +155,44 @@ msgstr "Vidéos"
183155
184156#: Dash/Video/VideoPreview.qml:98
185157msgid "Directed by:"
186−msgstr ""
158+msgstr "Réalisé par :"
187159
188160#: Dash/Video/VideoPreview.qml:121
189161msgid "Starring:"
190−msgstr ""
162+msgstr "Acteurs :"
191163
192164#: Dash/Video/VideoPreview.qml:144
193165msgid "Author:"
194−msgstr ""
166+msgstr "Auteur :"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
200172#: Greeter/PassphraseLockscreen.qml:59
201173#, qt-format
202174msgid "Hello %1"
203−msgstr ""
175+msgstr "Bonjour %1"
204176
205177#: Greeter/PassphraseLockscreen.qml:59
206178msgid "Hello"
207−msgstr ""
179+msgstr "Bonjour"
208180
209181#: Hud/HudParametrizedActionsPage.qml:132
210182msgid "Confirm"
211−msgstr ""
183+msgstr "Confirmer"
212184
213185#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
214186msgid "Type or say a command"
215−msgstr ""
187+msgstr "Entrez ou dictez une commande"
216188
217189#: Hud/Hud.qml:84
218190msgid "Loading. Please Wait..."
219−msgstr ""
191+msgstr "Chargement. Veuillez patienter..."
220192
221193#: Hud/Hud.qml:89
222194msgid "Speak Now..."
223−msgstr ""
195+msgstr "Parlez maintenant..."
224196
225197#: Hud/Hud.qml:94
226198msgid "Speaking..."
@@ -232,21 +204,38 @@ msgstr ""
232204
233205#: Panel/Menus/Overview/FlightModeWidget.qml:42
234206msgid "Flight mode"
235−msgstr ""
207+msgstr "Mode avion"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239−msgstr ""
211+msgstr "Rechercher"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243−msgstr ""
244−
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
215+msgstr "Désolé, aucun résultat ne correspond à votre recherche."
248216
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "Home screen"
223+#~ msgstr "Écran d’accueil"
224+
225+#~ msgid "People"
226+#~ msgstr "Contacts"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Contacts favoris"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "Contacts récents"
233+
234+#~ msgid "A-Z"
235+#~ msgstr "A-Z"
236+
237+#~ msgid "New Contacts"
238+#~ msgstr "Nouveaux contacts"
239+
240+#~ msgid "Favourites"
241+#~ msgstr "Favoris"
po/gl.po+24−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Galician <gl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Dispoñíbel para descargar"
109109msgid "Apps"
110110msgstr "Aplicativos"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Aplicativos frecuentes"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Xente favorita"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "Xente contactada recentemente"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Música recente"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Vídeos populares en liña"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Cartafol persoal"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Música"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Persoas"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,27 @@ msgstr "Dispositivo"
234206msgid "Flight mode"
235207msgstr "Modo de voo"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Buscar"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Sentímolo, non hai nada que coincida con esta busca."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Pantalla de inicio"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Persoas"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Pantalla de inicio"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Xente favorita"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "Xente contactada recentemente"
po/he.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Hebrew <he@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "יישומים"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "בית"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "מוזיקה"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "אנשים"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "חיפוש"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "מסך הבית"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "אנשים"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "מסך הבית"
po/hr.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Croatian <hr@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Aplikacije"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Početna"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Glazba"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Osobe"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Pretraživanje"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Početni zaslon"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Osobe"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Početni zaslon"
po/hu.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Hungarian <hu@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Alkalmazások"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Kezdőoldal"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Zene"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Emberek"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr "Eszköz"
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Keresés"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Elnézést, nincs találat a keresésre."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Kezdőképernyő"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Emberek"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Kezdőképernyő"
po/hy.po+24−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-07 12:42+0000\n"
1212"Last-Translator: iAbaS <sosabazyan@yandex.ru>\n"
1313"Language-Team: Armenian <hy@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Հասանելի ծրագրեր"
109109msgid "Apps"
110110msgstr "Ծրագրեր"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Հաճախակի ծրագրերը"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Ֆավորիտներ"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "Վերջին մարդիկ"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Վերջին երգերը"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Հայտնի օնլայն վիդեոներ"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Տուն"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Երգեր"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Մարդիկ"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,27 @@ msgstr "Սարք"
234206msgid "Flight mode"
235207msgstr "Անկապ րեժիմ"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Որոնում"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Տուն"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People Recently in Touch"
223+#~ msgstr "Վերջին մարդիկ"
224+
225+#~ msgid "Favourite People"
226+#~ msgstr "Ֆավորիտներ"
227+
228+#~ msgid "People"
229+#~ msgstr "Մարդիկ"
230+
231+#~ msgid "Home screen"
232+#~ msgstr "Տուն"
po/id.po+12−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Indonesian <id@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr ""
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr ""
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr ""
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr ""
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,15 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr ""
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr ""
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
po/it.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Italian <it@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Applicazioni"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Home"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Musica"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Contatti"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Cerca"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Nessun risultato corrispondente alla ricerca."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Home"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Contatti"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Home"
po/ja.po+12−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-15 14:12+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Japanese <ja@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr ""
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr ""
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr ""
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr ""
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,15 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr ""
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr ""
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
po/kn.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Kannada <kn@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "ಮನೆ (Home)"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "ಸಂಗೀತ"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "ಜನರು"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "ಹುಡುಕು"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯಾದ ಹೊಂದಾಣಿಕೆಗಳು ದೊರಕುತ್ತಿಲ್ಲ"
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "ಹೋಮ್ ಸ್ಕ್ರೀನ್"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "ಜನರು"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "ಹೋಮ್ ಸ್ಕ್ರೀನ್"
po/ko.po+12−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Korean <ko@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "내려받을 수 있음"
109109msgid "Apps"
110110msgstr "앱"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "자주 쓰는 앱"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "요즈음 찾는 음악"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr ""
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "음악"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr ""
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,15 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "찾기"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr ""
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
po/ky.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Kirghiz <ky@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Тиркемелер"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Үй папкасы"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Музыка"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Адамдар"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Издөө"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Тилекке каршы, сиздин издөөңүзгө эч нерсе дал келген жок."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Башкы экран"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Адамдар"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Башкы экран"
po/lv.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Latvian <lv@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Lietotnes"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Mājas"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Mūzika"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Cilvēki"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Meklēt"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Mājas ekrāns"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Cilvēki"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Mājas ekrāns"
po/my.po+15−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Burmese <my@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Apps"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "ပင်မ"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "တေးဂီတ"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "လူ"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,18 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "ရှာဖွေ"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့်တူညီတာဘာမှမရှိပါ။"
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "လူ"
po/nb.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-17 09:10+0000\n"
1212"Last-Translator: Joakim Langvand <jlangvand@gmail.com>\n"
1313"Language-Team: Norwegian Bokmal <nb@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Tilgjengelig for nedlasting"
109109msgid "Apps"
110110msgstr "Programmer"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Hjem"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Musikk"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Personer"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr "Enhet"
234206msgid "Flight mode"
235207msgstr "Flymodus"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Søk"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Søket ga ingen treff."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Hjemmeskjerm"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Personer"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Hjemmeskjerm"
po/nl.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Dutch <nl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Apps"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Hoofdvenster"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Muziek"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Mensen"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Zoeken"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Startscherm"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Mensen"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Startscherm"
po/pl.po+36−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:43+0000\n"
1212"Last-Translator: Piotr Merski <Unknown>\n"
1313"Language-Team: Polish <pl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Dostępne do pobrania"
109109msgid "Apps"
110110msgstr "Aplikacje"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Często używane aplikacje"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Ulubione kontakty"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "Osoby ostatnio w kontakcie"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Najnowsza muzyka"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Wideo popularne online"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Dom"
135127
@@ -153,26 +145,6 @@ msgstr "Przeboje"
153145msgid "Music"
154146msgstr "Muzyka"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "Ulubione"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "Ostatnio w kontakcie"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "Nowe kontakty"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "A-Z"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Ludzie"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "Popularne w sieci"
@@ -193,7 +165,7 @@ msgstr "Obsada:"
193165msgid "Author:"
194166msgstr "Autor:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,39 @@ msgstr "Urządzenie"
234206msgid "Flight mode"
235207msgstr "Tryb samolotowy"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Szukaj"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Nie znaleziono pasujących wyników."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Ekran domowy"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "Home screen"
223+#~ msgstr "Ekran domowy"
224+
225+#~ msgid "People"
226+#~ msgstr "Ludzie"
227+
228+#~ msgid "People Recently in Touch"
229+#~ msgstr "Osoby ostatnio w kontakcie"
230+
231+#~ msgid "Favourite People"
232+#~ msgstr "Ulubione kontakty"
233+
234+#~ msgid "A-Z"
235+#~ msgstr "A-Z"
236+
237+#~ msgid "Recently in touch"
238+#~ msgstr "Ostatnio w kontakcie"
239+
240+#~ msgid "New Contacts"
241+#~ msgstr "Nowe kontakty"
242+
243+#~ msgid "Favourites"
244+#~ msgstr "Ulubione"
po/pt_BR.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Aplicativos"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Início"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Músicas"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Pessoas"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Pesquisar"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Tela inicial"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Pessoas"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Tela inicial"
po/ro.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Romanian <ro@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Aplicații"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Acasă"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Muzică"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Persoane"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,20 +206,22 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Căutare"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr ""
244216"Ne pare rău, nu este nimic care se potrivește căutării dumneavoastră."
245217
246−#: plugins/Unity/lenses.cpp:39
247−msgid "Home screen"
248−msgstr "Ecran principal"
249−
250−#: Shell.qml:380
218+#: Shell.qml:383
251219#, qt-format
252−msgid "Please enter %1:"
220+msgid "Please enter %1"
253221msgstr ""
222+
223+#~ msgid "People"
224+#~ msgstr "Persoane"
225+
226+#~ msgid "Home screen"
227+#~ msgstr "Ecran principal"
po/ru.po+27−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-21 10:08+0000\n"
1212"Last-Translator: Andrey Dedikov <iamawesome.ndr@gmail.com>\n"
1313"Language-Team: Russian <ru@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-22 06:26+0000\n"
18−"X-Generator: Launchpad (build 16677)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Доступно для загрузки"
109109msgid "Apps"
110110msgstr "Приложения"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Часто используемые приложения"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Избранные контакты"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "Недавние контакты"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Недавно прослушанная музыка"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Популярные видео из сети"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Главная"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Музыка"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "Новые контакты"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Люди"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr "В главных ролях"
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,30 @@ msgstr "Устройство"
234206msgid "Flight mode"
235207msgstr "Режим полета"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Поиск"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Извините, поиск не дал результатов."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Главный экран"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Люди"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Главный экран"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Избранные контакты"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "Недавние контакты"
233+
234+#~ msgid "New Contacts"
235+#~ msgstr "Новые контакты"
po/si.po+12−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Sinhalese <si@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr ""
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr ""
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr ""
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr ""
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,15 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr ""
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr ""
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
po/sl.po+43−69
@@ -7,83 +7,83 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
11−"PO-Revision-Date: 2013-06-09 10:23+0000\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11+"PO-Revision-Date: 2013-06-29 10:26+0000\n"
1212"Last-Translator: Damir Jerovšek <Unknown>\n"
1313"Language-Team: Slovenian <sl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18+"X-Generator: Launchpad (build 16692)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
22−msgstr ""
22+msgstr "Telefon"
2323
2424#: Applications/applications.js:29
2525msgid "Camera"
26−msgstr ""
26+msgstr "Fotoaparat"
2727
2828#: Applications/applications.js:35
2929msgid "Gallery"
30−msgstr ""
30+msgstr "Galerija"
3131
3232#: Applications/applications.js:40
3333msgid "Facebook"
34−msgstr ""
34+msgstr "Facebook"
3535
3636#: Applications/applications.js:46
3737msgid "Browser"
38−msgstr ""
38+msgstr "Brskalnik"
3939
4040#: Applications/applications.js:51
4141msgid "Twitter"
42−msgstr ""
42+msgstr "Twitter"
4343
4444#: Applications/applications.js:57
4545msgid "GMail"
46−msgstr ""
46+msgstr "GMail"
4747
4848#: Applications/applications.js:62
4949msgid "Weather"
50−msgstr ""
50+msgstr "Vreme"
5151
5252#: Applications/applications.js:68
5353msgid "Notepad"
54−msgstr ""
54+msgstr "Beležnica"
5555
5656#: Applications/applications.js:74
5757msgid "Calendar"
58−msgstr ""
58+msgstr "Koledar"
5959
6060#: Applications/applications.js:80
6161msgid "Media Player"
62−msgstr ""
62+msgstr "Predvajalnik predstavnosti"
6363
6464#: Applications/applications.js:86
6565msgid "Evernote"
66−msgstr ""
66+msgstr "Evernote"
6767
6868#: Applications/applications.js:91
6969msgid "Map"
70−msgstr ""
70+msgstr "Zemljevid"
7171
7272#: Applications/applications.js:96
7373msgid "Pinterest"
74−msgstr ""
74+msgstr "Pinterest"
7575
7676#: Applications/applications.js:101
7777msgid "SoundCloud"
78−msgstr ""
78+msgstr "SoundCloud"
7979
8080#: Applications/applications.js:106
8181msgid "Wikipedia"
82−msgstr ""
82+msgstr "Wikipedija"
8383
8484#: Applications/applications.js:111
8585msgid "YouTube"
86−msgstr ""
86+msgstr "YouTube"
8787
8888#: Components/PageHeader.qml:300
8989msgid "Recent searches"
@@ -109,27 +109,19 @@ msgstr "Na voljo za prejem"
109109msgid "Apps"
110110msgstr "Programi"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Nedavna glasba"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Domov"
135127
@@ -139,11 +131,11 @@ msgstr ""
139131
140132#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
141133msgid "Recent"
142−msgstr ""
134+msgstr "Nedavno"
143135
144136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
145137msgid "New Releases"
146−msgstr ""
138+msgstr "Nove izdaje"
147139
148140#: Dash/DashMusic.qml:30
149141msgid "Top Charting"
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Glasba"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Ljudje"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -191,20 +163,20 @@ msgstr ""
191163
192164#: Dash/Video/VideoPreview.qml:144
193165msgid "Author:"
194−msgstr ""
166+msgstr "Avtor:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198−msgstr ""
170+msgstr "Klic v sili"
199171
200172#: Greeter/PassphraseLockscreen.qml:59
201173#, qt-format
202174msgid "Hello %1"
203−msgstr ""
175+msgstr "Pozdravljeni, %1"
204176
205177#: Greeter/PassphraseLockscreen.qml:59
206178msgid "Hello"
207−msgstr ""
179+msgstr "Pozdravljeni"
208180
209181#: Hud/HudParametrizedActionsPage.qml:132
210182msgid "Confirm"
@@ -234,19 +206,21 @@ msgstr "Naprava"
234206msgid "Flight mode"
235207msgstr "Način letenja"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Iskanje"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Nič se ne ujema z vašim iskalnim nizom."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Domači zaslon"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
252−msgstr ""
219+msgid "Please enter %1"
220+msgstr "Vnesite %1"
221+
222+#~ msgid "People"
223+#~ msgstr "Ljudje"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Domači zaslon"
po/sr.po+18−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Serbian <sr@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr "Програми"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Почетна"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Музика"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Људи"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,21 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Претрага"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Нажалост, претрага није наишла на икакво подударање."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Почетни екран"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Људи"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Почетни екран"
po/sv.po+12−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Swedish <sv@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr ""
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr ""
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr ""
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr ""
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,15 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr ""
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr ""
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
po/te.po+12−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Telugu <te@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109109msgid "Apps"
110110msgstr ""
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr ""
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr ""
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr ""
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "నివాసం"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "సంగీతం"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr ""
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,15 @@ msgstr ""
234206msgid "Flight mode"
235207msgstr ""
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr ""
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr ""
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
po/th.ponew file+220
@@ -0,0 +1,220 @@
1+# Thai translation for unity
2+# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
3+# This file is distributed under the same license as the unity package.
4+# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
5+#
6+msgid ""
7+msgstr ""
8+"Project-Id-Version: unity\n"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11+"PO-Revision-Date: 2013-06-28 15:34+0000\n"
12+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13+"Language-Team: Thai <th@li.org>\n"
14+"MIME-Version: 1.0\n"
15+"Content-Type: text/plain; charset=UTF-8\n"
16+"Content-Transfer-Encoding: 8bit\n"
17+"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18+"X-Generator: Launchpad (build 16692)\n"
19+
20+#: Applications/applications.js:23
21+msgid "Phone"
22+msgstr ""
23+
24+#: Applications/applications.js:29
25+msgid "Camera"
26+msgstr ""
27+
28+#: Applications/applications.js:35
29+msgid "Gallery"
30+msgstr ""
31+
32+#: Applications/applications.js:40
33+msgid "Facebook"
34+msgstr ""
35+
36+#: Applications/applications.js:46
37+msgid "Browser"
38+msgstr ""
39+
40+#: Applications/applications.js:51
41+msgid "Twitter"
42+msgstr ""
43+
44+#: Applications/applications.js:57
45+msgid "GMail"
46+msgstr ""
47+
48+#: Applications/applications.js:62
49+msgid "Weather"
50+msgstr ""
51+
52+#: Applications/applications.js:68
53+msgid "Notepad"
54+msgstr ""
55+
56+#: Applications/applications.js:74
57+msgid "Calendar"
58+msgstr ""
59+
60+#: Applications/applications.js:80
61+msgid "Media Player"
62+msgstr ""
63+
64+#: Applications/applications.js:86
65+msgid "Evernote"
66+msgstr ""
67+
68+#: Applications/applications.js:91
69+msgid "Map"
70+msgstr ""
71+
72+#: Applications/applications.js:96
73+msgid "Pinterest"
74+msgstr ""
75+
76+#: Applications/applications.js:101
77+msgid "SoundCloud"
78+msgstr ""
79+
80+#: Applications/applications.js:106
81+msgid "Wikipedia"
82+msgstr ""
83+
84+#: Applications/applications.js:111
85+msgid "YouTube"
86+msgstr ""
87+
88+#: Components/PageHeader.qml:300
89+msgid "Recent searches"
90+msgstr ""
91+
92+#: Dash/DashApps.qml:65
93+msgid "Running apps"
94+msgstr ""
95+
96+#: Dash/DashApps.qml:68
97+msgid "Frequently used"
98+msgstr ""
99+
100+#: Dash/DashApps.qml:71
101+msgid "Installed"
102+msgstr ""
103+
104+#: Dash/DashApps.qml:74
105+msgid "Available for download"
106+msgstr ""
107+
108+#: Dash/DashApps.qml:178
109+msgid "Apps"
110+msgstr ""
111+
112+#: Dash/DashHome.qml:40
113+msgid "Frequent Apps"
114+msgstr ""
115+
116+#: Dash/DashHome.qml:43
117+msgid "Recent Music"
118+msgstr ""
119+
120+#: Dash/DashHome.qml:46
121+msgid "Videos Popular Online"
122+msgstr ""
123+
124+#: Dash/DashHome.qml:175
125+msgid "Home"
126+msgstr ""
127+
128+#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
129+msgid "Featured"
130+msgstr ""
131+
132+#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
133+msgid "Recent"
134+msgstr ""
135+
136+#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
137+msgid "New Releases"
138+msgstr ""
139+
140+#: Dash/DashMusic.qml:30
141+msgid "Top Charting"
142+msgstr ""
143+
144+#: Dash/DashMusic.qml:99
145+msgid "Music"
146+msgstr ""
147+
148+#: Dash/DashVideos.qml:31
149+msgid "Popular Online"
150+msgstr ""
151+
152+#: Dash/DashVideos.qml:155
153+msgid "Videos"
154+msgstr ""
155+
156+#: Dash/Video/VideoPreview.qml:98
157+msgid "Directed by:"
158+msgstr ""
159+
160+#: Dash/Video/VideoPreview.qml:121
161+msgid "Starring:"
162+msgstr ""
163+
164+#: Dash/Video/VideoPreview.qml:144
165+msgid "Author:"
166+msgstr ""
167+
168+#: Greeter/Lockscreen.qml:133
169+msgid "Emergency call"
170+msgstr ""
171+
172+#: Greeter/PassphraseLockscreen.qml:59
173+#, qt-format
174+msgid "Hello %1"
175+msgstr ""
176+
177+#: Greeter/PassphraseLockscreen.qml:59
178+msgid "Hello"
179+msgstr ""
180+
181+#: Hud/HudParametrizedActionsPage.qml:132
182+msgid "Confirm"
183+msgstr ""
184+
185+#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
186+msgid "Type or say a command"
187+msgstr ""
188+
189+#: Hud/Hud.qml:84
190+msgid "Loading. Please Wait..."
191+msgstr ""
192+
193+#: Hud/Hud.qml:89
194+msgid "Speak Now..."
195+msgstr ""
196+
197+#: Hud/Hud.qml:94
198+msgid "Speaking..."
199+msgstr ""
200+
201+#: Panel/MenuContent.qml:192
202+msgid "Device"
203+msgstr ""
204+
205+#: Panel/Menus/Overview/FlightModeWidget.qml:42
206+msgid "Flight mode"
207+msgstr ""
208+
209+#: Panel/SearchIndicator.qml:26
210+msgid "Search"
211+msgstr ""
212+
213+#: plugins/Unity/scope.cpp:268
214+msgid "Sorry, there is nothing that matches your search."
215+msgstr ""
216+
217+#: Shell.qml:383
218+#, qt-format
219+msgid "Please enter %1"
220+msgstr ""
po/tr.po+33−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-24 17:24+0000\n"
1212"Last-Translator: Adar Cem EREN <adarcemeren34@gmail.com>\n"
1313"Language-Team: Turkish <tr@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-25 06:00+0000\n"
18−"X-Generator: Launchpad (build 16677)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "İndirilebilir durumda"
109109msgid "Apps"
110110msgstr "Uygulamalar"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Sıkça Kullanılan Uygulamalar"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Favori Kişiler"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "En Son Konuşulan Kişiler"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "En Son Müzik"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Çevrimiçi Yaygın Videolar"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Ana Sayfa"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "Müzik"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "Favoriler"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "Yeni Kişiler"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "A-Z"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Kişiler"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "Genellikle Çevrimiçi"
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr "Yazar:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr "Acil Arama"
199171
@@ -234,19 +206,36 @@ msgstr "Aygıt"
234206msgid "Flight mode"
235207msgstr "Uçak Modu"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Ara"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Başlangıç ekranı"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Kişiler"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Başlangıç ekranı"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Favori Kişiler"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "En Son Konuşulan Kişiler"
233+
234+#~ msgid "A-Z"
235+#~ msgstr "A-Z"
236+
237+#~ msgid "New Contacts"
238+#~ msgstr "Yeni Kişiler"
239+
240+#~ msgid "Favourites"
241+#~ msgstr "Favoriler"
po/ug.po+36−47
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
11−"PO-Revision-Date: 2013-06-25 08:02+0000\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11+"PO-Revision-Date: 2013-06-28 04:36+0000\n"
1212"Last-Translator: Gheyret T.Kenji <Unknown>\n"
1313"Language-Team: Uyghur <ug@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-26 06:20+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
17+"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18+"X-Generator: Launchpad (build 16692)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "چۈشۈرگىلى بولىدىغانلىرى"
109109msgid "Apps"
110110msgstr "ئەپلەر"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "دائىم ئىشلىتىلىدىغان ئەپلەر"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "ھەمىشە ئالاقە قىلىدىغان كىشىلەر"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "يېقىندا ئالاقە قىلغان كىشىلەر"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "يېقىندا ئاڭلىغان مۇزىكىلار"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "توردىكى ئالقىشقا ئېرىشكەن سىنلار"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "ماكان"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "مۇزىكا"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "يېقىندا ئالاقە قىلغانلار"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "يېڭى ئالاقەداشلار"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "A-Z"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "كىشىلەر"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,14 +165,14 @@ msgstr ""
193165msgid "Author:"
194166msgstr "ئاپتور:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr "جىددىي تېلېفون"
199171
200172#: Greeter/PassphraseLockscreen.qml:59
201173#, qt-format
202174msgid "Hello %1"
203−msgstr ""
175+msgstr "سالام %1"
204176
205177#: Greeter/PassphraseLockscreen.qml:59
206178msgid "Hello"
@@ -234,19 +206,36 @@ msgstr "ئۈسكۈنە"
234206msgid "Flight mode"
235207msgstr "ئايروپىلاندا"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "ئىزدە"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپىلمىدى."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "ماكان ئېكران"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
252−msgstr "%1 نى كىرگۈزۈڭ:"
219+msgid "Please enter %1"
220+msgstr "%1 نى كىرگۈزۈڭ"
221+
222+#~ msgid "Favourite People"
223+#~ msgstr "ھەمىشە ئالاقە قىلىدىغان كىشىلەر"
224+
225+#~ msgid "People Recently in Touch"
226+#~ msgstr "يېقىندا ئالاقە قىلغان كىشىلەر"
227+
228+#~ msgid "People"
229+#~ msgstr "كىشىلەر"
230+
231+#~ msgid "Home screen"
232+#~ msgstr "ماكان ئېكران"
233+
234+#~ msgid "A-Z"
235+#~ msgstr "A-Z"
236+
237+#~ msgid "Recently in touch"
238+#~ msgstr "يېقىندا ئالاقە قىلغانلار"
239+
240+#~ msgid "New Contacts"
241+#~ msgstr "يېڭى ئالاقەداشلار"
po/uk.po+39−47
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
11−"PO-Revision-Date: 2013-06-25 08:08+0000\n"
12−"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11+"PO-Revision-Date: 2013-06-29 14:27+0000\n"
12+"Last-Translator: Roman Koshkin <mar2008m@rambler.ru>\n"
1313"Language-Team: Ukrainian <uk@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-26 06:20+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
17+"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18+"X-Generator: Launchpad (build 16692)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Доступно до завантаження"
109109msgid "Apps"
110110msgstr "Програми"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "Часто використовувані програми"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "Вибрані контакти"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "Недавні контакти"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "Нещодавно прослухана музика"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "Популярні в мережі відео"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "Домівка"
135127
@@ -153,26 +145,6 @@ msgstr "З високими оцінками"
153145msgid "Music"
154146msgstr "Музика"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "Улюблене"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "Нещодавні контакти"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "Нові контакти"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "А-Я"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "Люди"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "Популярне у мережі"
@@ -193,7 +165,7 @@ msgstr "Актори:"
193165msgid "Author:"
194166msgstr "Автор:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr "Екстрений виклик"
199171
@@ -234,19 +206,39 @@ msgstr "Пристрій"
234206msgid "Flight mode"
235207msgstr "Автономний режим"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "Пошук"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "Вибачте, для вказаних вами ключових слів нічого не знайдено."
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "Екран домівки"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
252−msgstr "Будь ласка, введіть %1:"
219+msgid "Please enter %1"
220+msgstr "Будь ласка, введіть %1"
221+
222+#~ msgid "People"
223+#~ msgstr "Люди"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Екран домівки"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "Вибрані контакти"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "Недавні контакти"
233+
234+#~ msgid "A-Z"
235+#~ msgstr "А-Я"
236+
237+#~ msgid "New Contacts"
238+#~ msgstr "Нові контакти"
239+
240+#~ msgid "Favourites"
241+#~ msgstr "Улюблене"
242+
243+#~ msgid "Recently in touch"
244+#~ msgstr "Нещодавні контакти"
po/unity8.pot+4−9
@@ -8,7 +8,7 @@ msgid ""
88msgstr ""
99"Project-Id-Version: unity8\n"
1010"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
11+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1212"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -165,7 +165,7 @@ msgstr ""
165165msgid "Author:"
166166msgstr ""
167167
168−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
169169msgid "Emergency call"
170170msgstr ""
171171
@@ -214,12 +214,7 @@ msgstr ""
214214msgid "Sorry, there is nothing that matches your search."
215215msgstr ""
216216
217−#: Shell.qml:380
217+#: Shell.qml:383
218218#, qt-format
219−msgid "Please enter %1:"
220−msgstr ""
221−
222−#: Shell.qml:380
223−#, qt-format
224−msgid "Please enter %1:"
219+msgid "Please enter %1"
225220msgstr ""
po/zh_CN.po+37−45
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-22 21:20+0000\n"
1212"Last-Translator: Anthony Wong <anthony.wong@canonical.com>\n"
1313"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-23 05:56+0000\n"
18−"X-Generator: Launchpad (build 16677)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "可供下载"
109109msgid "Apps"
110110msgstr "应用程序"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "常用软件"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "常用联系人"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "近期联系人"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "近期听过的音乐"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "热门在线视频"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "主页"
135127
@@ -153,26 +145,6 @@ msgstr "排行榜图"
153145msgid "Music"
154146msgstr "音乐"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr "最爱"
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr "最近联系"
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr "新建联系人"
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr "A-Z"
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "联系人"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr "经常在线"
@@ -193,7 +165,7 @@ msgstr "主演:"
193165msgid "Author:"
194166msgstr "作者:"
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr "紧急呼救"
199171
@@ -234,19 +206,39 @@ msgstr "设备"
234206msgid "Flight mode"
235207msgstr "飞行模式"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "搜索"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "对不起,没有找到您想要的结果。"
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "主页"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
252−msgstr "请输入 %1:"
219+msgid "Please enter %1"
220+msgstr ""
221+
222+#~ msgid "Home screen"
223+#~ msgstr "主页"
224+
225+#~ msgid "Favourite People"
226+#~ msgstr "常用联系人"
227+
228+#~ msgid "People Recently in Touch"
229+#~ msgstr "近期联系人"
230+
231+#~ msgid "People"
232+#~ msgstr "联系人"
233+
234+#~ msgid "Recently in touch"
235+#~ msgstr "最近联系"
236+
237+#~ msgid "New Contacts"
238+#~ msgstr "新建联系人"
239+
240+#~ msgid "Favourites"
241+#~ msgstr "最爱"
242+
243+#~ msgid "A-Z"
244+#~ msgstr "A-Z"
po/zh_TW.po+24−44
@@ -7,15 +7,15 @@ msgid ""
77msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
1111"PO-Revision-Date: 2013-06-05 22:20+0000\n"
1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18+"X-Generator: Launchpad (build 16681)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "可供下載"
109109msgid "Apps"
110110msgstr "程式"
111111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114114msgstr "常用的程式"
115115
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr "喜歡的朋友"
119−
120−#: Dash/DashHome.qml:49
121−msgid "People Recently in Touch"
122−msgstr "最近接觸的朋友"
123−
124−#: Dash/DashHome.qml:52
116+#: Dash/DashHome.qml:43
125117msgid "Recent Music"
126118msgstr "最近聽過的音樂"
127119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129121msgid "Videos Popular Online"
130122msgstr "線上熱門的影片"
131123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133125msgid "Home"
134126msgstr "家屋"
135127
@@ -153,26 +145,6 @@ msgstr ""
153145msgid "Music"
154146msgstr "音樂"
155147
156−#: Dash/DashPeople.qml:31
157−msgid "Favourites"
158−msgstr ""
159−
160−#: Dash/DashPeople.qml:32
161−msgid "Recently in touch"
162−msgstr ""
163−
164−#: Dash/DashPeople.qml:33
165−msgid "New Contacts"
166−msgstr ""
167−
168−#: Dash/DashPeople.qml:34
169−msgid "A-Z"
170−msgstr ""
171−
172−#: Dash/DashPeople.qml:123
173−msgid "People"
174−msgstr "朋友"
175−
176148#: Dash/DashVideos.qml:31
177149msgid "Popular Online"
178150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193165msgid "Author:"
194166msgstr ""
195167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197169msgid "Emergency call"
198170msgstr ""
199171
@@ -234,19 +206,27 @@ msgstr "裝置"
234206msgid "Flight mode"
235207msgstr "飛航模式"
236208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238210msgid "Search"
239211msgstr "搜尋"
240212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242214msgid "Sorry, there is nothing that matches your search."
243215msgstr "很抱歉,找不到符合您想搜尋的結果。"
244216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "家屋畫面"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "朋友"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "家屋畫面"
227+
228+#~ msgid "Favourite People"
229+#~ msgstr "喜歡的朋友"
230+
231+#~ msgid "People Recently in Touch"
232+#~ msgstr "最近接觸的朋友"
run_on_device+1−1
@@ -75,7 +75,7 @@ install_dependencies() {
7575sync_code() {
7676 [ -e .bzr ] && bzr export --uncommitted --format=dir /tmp/$CODE_DIR
7777 [ -e .git ] && git checkout-index -a -f --prefix=/tmp/$CODE_DIR/
78− rsync -crlOzv -e "ssh -p $TARGET_SSH_PORT -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" /tmp/$CODE_DIR/ $USER@$TARGET_IP:$CODE_DIR/
78+ rsync -crlOzv --delete --exclude builddir -e "ssh -p $TARGET_SSH_PORT -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" /tmp/$CODE_DIR/ $USER@$TARGET_IP:$CODE_DIR/
7979 rm -rf /tmp/$CODE_DIR
8080}
8181
tests/plugins/CMakeLists.txt+1
@@ -1,2 +1,3 @@
11add_subdirectory(Utils)
22add_subdirectory(Ubuntu)
3+add_subdirectory(ListViewWithPageHeader)
tests/plugins/ListViewWithPageHeader/CMakeLists.txtnew file+31
@@ -0,0 +1,31 @@
1+# There's no cmake var for v8 include path :-/
2+# so create one
3+LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
4+SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
5+
6+include_directories(
7+ ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
8+ ${Qt5Quick_INCLUDE_DIRS}
9+ ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
10+ ${Qt5V8_PRIVATE_INCLUDE_DIR}
11+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../plugins/ListViewWithPageHeader
12+ ${CMAKE_CURRENT_BINARY_DIR}
13+ )
14+
15+remove_definitions(-DQT_NO_KEYWORDS)
16+
17+add_definitions(-DLISTVIEWWITHPAGEHEADER_FOLDER="${CMAKE_CURRENT_SOURCE_DIR}")
18+add_definitions(-DBUILT_PLUGINS_DIR="${CMAKE_BINARY_DIR}/plugins")
19+
20+add_executable(listviewwithpageheadertestExec listviewwithpageheadertest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../../plugins/ListViewWithPageHeader/listviewwithpageheader.cpp)
21+qt5_use_modules(listviewwithpageheadertestExec Test Core Qml)
22+target_link_libraries(listviewwithpageheadertestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
23+add_custom_target(testlistviewwithpageheader ${CMAKE_CURRENT_BINARY_DIR}/listviewwithpageheadertestExec -o ${CMAKE_BINARY_DIR}/testlistviewwithpageheader.xml,xunitxml -o -,txt)
24+
25+add_executable(listviewwithpageheadertestsectionExec listviewwithpageheadertestsection.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../../plugins/ListViewWithPageHeader/listviewwithpageheader.cpp)
26+qt5_use_modules(listviewwithpageheadertestsectionExec Test Core Qml)
27+target_link_libraries(listviewwithpageheadertestsectionExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
28+add_custom_target(testlistviewwithpageheadersection ${CMAKE_CURRENT_BINARY_DIR}/listviewwithpageheadertestsectionExec -o ${CMAKE_BINARY_DIR}/testlistviewwithpageheadersection.xml,xunitxml -o -,txt)
29+
30+add_dependencies(qmluitests testlistviewwithpageheader)
31+add_dependencies(qmluitests testlistviewwithpageheadersection)
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cppnew file+1311
@@ -0,0 +1,1311 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "listviewwithpageheader.h"
18+
19+#include <QAbstractItemModel>
20+#include <QQmlEngine>
21+#include <QQuickView>
22+#include <QtTestGui>
23+#include <private/qquicklistmodel_p.h>
24+#include <private/qquickanimation_p.h>
25+#include <private/qquickitem_p.h>
26+
27+class ListViewWithPageHeaderTest : public QObject
28+{
29+ Q_OBJECT
30+
31+private:
32+ void verifyItem(int visibleIndex, qreal pos, qreal height, bool culled)
33+ {
34+ ListViewWithPageHeader::ListItem *item = lvwph->m_visibleItems[visibleIndex];
35+ QTRY_COMPARE(item->y(), pos);
36+ QTRY_COMPARE(item->height(), height);
37+ QCOMPARE(QQuickItemPrivate::get(item->m_item)->culled, culled);
38+ }
39+
40+ void changeContentY(qreal change)
41+ {
42+ const qreal dest = lvwph->contentY() + change;
43+ if (dest > lvwph->contentY()) {
44+ const qreal jump = 25;
45+ while (lvwph->contentY() + jump < dest) {
46+ lvwph->setContentY(lvwph->contentY() + jump);
47+ QTest::qWait(1);
48+ }
49+ } else {
50+ const qreal jump = -25;
51+ while (lvwph->contentY() + jump > dest) {
52+ lvwph->setContentY(lvwph->contentY() + jump);
53+ QTest::qWait(1);
54+ }
55+ }
56+ lvwph->setContentY(dest);
57+ QTest::qWait(1);
58+ }
59+
60+ void scrollToTop()
61+ {
62+ const qreal jump = -25;
63+ while (!lvwph->isAtYBeginning()) {
64+ if (lvwph->contentY() + jump > -lvwph->minYExtent()) {
65+ lvwph->setContentY(lvwph->contentY() + jump);
66+ } else {
67+ lvwph->setContentY(lvwph->contentY() - 1);
68+ }
69+ QTest::qWait(1);
70+ }
71+ }
72+
73+ void scrollToBottom()
74+ {
75+ const qreal jump = 25;
76+ while (!lvwph->isAtYEnd()) {
77+ if (lvwph->contentY() + lvwph->height() + jump < lvwph->contentHeight()) {
78+ lvwph->setContentY(lvwph->contentY() + jump);
79+ } else {
80+ lvwph->setContentY(lvwph->contentY() + 1);
81+ }
82+ QTest::qWait(1);
83+ }
84+ }
85+
86+ void verifyInitialTopPosition()
87+ {
88+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
89+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
90+ verifyItem(0, 50., 150., false);
91+ verifyItem(1, 200., 200., false);
92+ verifyItem(2, 400., 350., false);
93+ verifyItem(3, 750., 350., true);
94+ QCOMPARE(lvwph->m_minYExtent, 0.);
95+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
96+ QCOMPARE(lvwph->m_clipItem->clip(), false);
97+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
98+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
99+ QCOMPARE(lvwph->contentY(), 0.);
100+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
101+ }
102+
103+private Q_SLOTS:
104+
105+ void initTestCase()
106+ {
107+ }
108+
109+ void init()
110+ {
111+ view = new QQuickView();
112+ view->engine()->addImportPath(BUILT_PLUGINS_DIR);
113+ view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test.qml"));
114+ lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
115+ model = view->rootObject()->findChild<QQuickListModel*>();
116+ otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
117+ QVERIFY(lvwph);
118+ QVERIFY(model);
119+ QVERIFY(otherDelegate);
120+ view->show();
121+ QTest::qWaitForWindowExposed(view);
122+
123+ verifyInitialTopPosition();
124+ }
125+
126+ void cleanup()
127+ {
128+ delete view;
129+ }
130+
131+ void testCreationDeletion()
132+ {
133+ // Nothing, init/cleanup already tests this
134+ }
135+
136+ void testDrag1PixelUp()
137+ {
138+ lvwph->setContentY(lvwph->contentY() + 1);
139+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
140+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
141+ verifyItem(0, 49., 150., false);
142+ verifyItem(1, 199., 200., false);
143+ verifyItem(2, 399., 350., false);
144+ verifyItem(3, 749., 350., true);
145+ QCOMPARE(lvwph->m_minYExtent, 0.);
146+ QCOMPARE(lvwph->m_clipItem->y(), 1.);
147+ QCOMPARE(lvwph->m_clipItem->clip(), false);
148+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
149+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
150+ QCOMPARE(lvwph->contentY(), 1.);
151+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
152+ }
153+
154+ void testHeaderDetachDragDown()
155+ {
156+ QTest::mousePress(view, Qt::LeftButton, Qt::NoModifier, QPoint(0, 0));
157+ QTest::qWait(100);
158+ QTest::mouseMove(view, QPoint(0, 5));
159+ QTest::qWait(100);
160+ QTest::mouseMove(view, QPoint(0, 10));
161+ QTest::qWait(100);
162+ QTest::mouseMove(view, QPoint(0, 15));
163+ QTest::qWait(100);
164+ QTest::mouseMove(view, QPoint(0, 20));
165+ QTest::qWait(100);
166+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
167+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
168+ verifyItem(0, 55., 150., false);
169+ verifyItem(1, 205., 200., false);
170+ verifyItem(2, 405., 350., false);
171+ verifyItem(3, 755., 350., true);
172+ QCOMPARE(lvwph->m_minYExtent, 0.);
173+ QCOMPARE(lvwph->m_clipItem->y(), -5.);
174+ QCOMPARE(lvwph->m_clipItem->clip(), false);
175+ QCOMPARE(lvwph->m_headerItem->y(), -5.);
176+ QCOMPARE(lvwph->m_headerItem->height(), 55.);
177+ QCOMPARE(lvwph->contentY(), -5.);
178+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
179+
180+ QTest::mouseRelease(view, Qt::LeftButton, Qt::NoModifier, QPoint(0, 15));
181+
182+ verifyInitialTopPosition();
183+ }
184+
185+ void testDrag375PixelUp()
186+ {
187+ changeContentY(375);
188+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
189+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
190+ verifyItem(0, -325., 150., true);
191+ verifyItem(1, -175, 200., false);
192+ verifyItem(2, 25, 350., false);
193+ verifyItem(3, 375, 350., false);
194+ verifyItem(4, 725, 350., true);
195+ QCOMPARE(lvwph->m_minYExtent, 0.);
196+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
197+ QCOMPARE(lvwph->m_clipItem->clip(), false);
198+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
199+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
200+ QCOMPARE(lvwph->contentY(), 375.);
201+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
202+ }
203+
204+ void testDrag520PixelUp()
205+ {
206+ changeContentY(520);
207+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
208+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
209+ verifyItem(0, -320., 200., true);
210+ verifyItem(1, -120, 350., false);
211+ verifyItem(2, 230, 350., false);
212+ verifyItem(3, 580, 350., true);
213+ // Just here as first check against m_minYExtent when m_firstVisibleIndex is not 0
214+ // We as humans know that m_minYExtent will be 0 but since the first delegate is not there anymore
215+ // we have to estimate its size, the average item height is 312.5 which is 162.5 more than the
216+ // "real" size of 150 and that's why the m_minYExtent has that "peculiar" value
217+ // It's fine since what it means is that we could scroll more up than the original position
218+ // but we will recalculate m_minYExtent when the item 0 is created and set it correctly
219+ QCOMPARE(lvwph->m_minYExtent, 162.5);
220+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
221+ QCOMPARE(lvwph->m_clipItem->clip(), false);
222+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
223+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
224+ QCOMPARE(lvwph->contentY(), 520.);
225+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
226+ }
227+
228+ void testDragHeaderUpThenShow()
229+ {
230+ changeContentY(120);
231+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
232+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
233+ verifyItem(0, -70., 150., false);
234+ verifyItem(1, 80., 200., false);
235+ verifyItem(2, 280., 350., false);
236+ verifyItem(3, 630., 350., true);
237+ QCOMPARE(lvwph->m_minYExtent, 0.);
238+ QCOMPARE(lvwph->m_clipItem->y(), 120.);
239+ QCOMPARE(lvwph->m_clipItem->clip(), false);
240+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
241+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
242+ QCOMPARE(lvwph->contentY(), 120.);
243+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
244+
245+ changeContentY(-30);
246+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
247+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
248+ verifyItem(0, -70., 150., false);
249+ verifyItem(1, 80., 200., false);
250+ verifyItem(2, 280., 350., false);
251+ verifyItem(3, 630., 350., true);
252+ QCOMPARE(lvwph->m_minYExtent, 0.);
253+ QCOMPARE(lvwph->m_clipItem->y(), 120.);
254+ QCOMPARE(lvwph->m_clipItem->clip(), true);
255+ QTRY_COMPARE(lvwph->m_headerItem->y(), 70.);
256+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
257+ QCOMPARE(lvwph->contentY(), 90.);
258+ QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
259+ }
260+
261+ void testDragHeaderUpThenShowWithoutHidingTotally()
262+ {
263+ changeContentY(10);
264+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
265+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
266+ verifyItem(0, 40., 150., false);
267+ verifyItem(1, 190., 200., false);
268+ verifyItem(2, 390., 350., false);
269+ verifyItem(3, 740., 350., true);
270+ QCOMPARE(lvwph->m_minYExtent, 0.);
271+ QCOMPARE(lvwph->m_clipItem->y(), 10.);
272+ QCOMPARE(lvwph->m_clipItem->clip(), false);
273+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
274+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
275+ QCOMPARE(lvwph->contentY(), 10.);
276+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
277+
278+ changeContentY(-1);
279+
280+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
281+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
282+ verifyItem(0, 41., 150., false);
283+ verifyItem(1, 191., 200., false);
284+ verifyItem(2, 391., 350., false);
285+ verifyItem(3, 741., 350., true);
286+ QCOMPARE(lvwph->m_minYExtent, 0.);
287+ QCOMPARE(lvwph->m_clipItem->y(), 9.);
288+ QCOMPARE(lvwph->m_clipItem->clip(), false);
289+ QTRY_COMPARE(lvwph->m_headerItem->y(), 0.);
290+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
291+ QCOMPARE(lvwph->contentY(), 9.);
292+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
293+ }
294+
295+ void testPositionAtBeginningIndex0Visible()
296+ {
297+ changeContentY(375);
298+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
299+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
300+ verifyItem(0, -325., 150., true);
301+ verifyItem(1, -175, 200., false);
302+ verifyItem(2, 25, 350., false);
303+ verifyItem(3, 375, 350., false);
304+ verifyItem(4, 725, 350., true);
305+ QCOMPARE(lvwph->m_minYExtent, 0.);
306+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
307+ QCOMPARE(lvwph->m_clipItem->clip(), false);
308+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
309+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
310+ QCOMPARE(lvwph->contentY(), 375.);
311+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
312+
313+ lvwph->positionAtBeginning();
314+
315+ verifyInitialTopPosition();
316+ }
317+
318+ void testPositionAtBeginningIndex0NotVisible()
319+ {
320+ changeContentY(520);
321+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
322+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
323+ verifyItem(0, -320., 200., true);
324+ verifyItem(1, -120, 350., false);
325+ verifyItem(2, 230, 350., false);
326+ verifyItem(3, 580, 350., true);
327+ QCOMPARE(lvwph->m_minYExtent, 162.5);
328+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
329+ QCOMPARE(lvwph->m_clipItem->clip(), false);
330+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
331+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
332+ QCOMPARE(lvwph->contentY(), 520.);
333+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
334+
335+ lvwph->positionAtBeginning();
336+
337+ verifyInitialTopPosition();
338+ }
339+
340+ void testIndex0GrowOnScreen()
341+ {
342+ model->setProperty(0, "size", 400);
343+
344+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
345+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
346+ verifyItem(0, 50., 400., false);
347+ verifyItem(1, 450., 200., false);
348+ verifyItem(2, 650., 350., true);
349+ QCOMPARE(lvwph->m_minYExtent, 0.);
350+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
351+ QCOMPARE(lvwph->m_clipItem->clip(), false);
352+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
353+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
354+ QCOMPARE(lvwph->contentY(), 0.);
355+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
356+ }
357+
358+ void testIndex0GrowOffScreen()
359+ {
360+ changeContentY(375);
361+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
362+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
363+ verifyItem(0, -325., 150., true);
364+ verifyItem(1, -175, 200., false);
365+ verifyItem(2, 25, 350., false);
366+ verifyItem(3, 375, 350., false);
367+ verifyItem(4, 725, 350., true);
368+ QCOMPARE(lvwph->m_minYExtent, 0.);
369+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
370+ QCOMPARE(lvwph->m_clipItem->clip(), false);
371+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
372+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
373+ QCOMPARE(lvwph->contentY(), 375.);
374+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
375+
376+ model->setProperty(0, "size", 400);
377+
378+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
379+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
380+ verifyItem(0, -575., 400., true);
381+ verifyItem(1, -175, 200., false);
382+ verifyItem(2, 25, 350., false);
383+ verifyItem(3, 375, 350., false);
384+ verifyItem(4, 725, 350., true);
385+ QCOMPARE(lvwph->m_minYExtent, 250.);
386+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
387+ QCOMPARE(lvwph->m_clipItem->clip(), false);
388+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
389+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
390+ QCOMPARE(lvwph->contentY(), 375.);
391+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
392+
393+ scrollToTop();
394+
395+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
396+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
397+ verifyItem(0, 50., 400., false);
398+ verifyItem(1, 450, 200., false);
399+ verifyItem(2, 650, 350., true);
400+ QCOMPARE(lvwph->m_minYExtent, 250.);
401+ QCOMPARE(lvwph->m_clipItem->y(), -250.);
402+ QCOMPARE(lvwph->m_clipItem->clip(), false);
403+ QCOMPARE(lvwph->m_headerItem->y(), -250.);
404+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
405+ QCOMPARE(lvwph->contentY(), -250.);
406+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
407+
408+ changeContentY(30);
409+
410+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
411+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
412+ verifyItem(0, 20., 400., false);
413+ verifyItem(1, 420, 200., false);
414+ verifyItem(2, 620, 350., true);
415+ QCOMPARE(lvwph->m_minYExtent, 250.);
416+ QCOMPARE(lvwph->m_clipItem->y(), -220.);
417+ QCOMPARE(lvwph->m_clipItem->clip(), false);
418+ QCOMPARE(lvwph->m_headerItem->y(), -250.);
419+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
420+ QCOMPARE(lvwph->contentY(), -220.);
421+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
422+ }
423+
424+ void testIndex0GrowNotCreated()
425+ {
426+ changeContentY(520);
427+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
428+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
429+ verifyItem(0, -320., 200., true);
430+ verifyItem(1, -120, 350., false);
431+ verifyItem(2, 230, 350., false);
432+ verifyItem(3, 580, 350., true);
433+ QCOMPARE(lvwph->m_minYExtent, 162.5);
434+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
435+ QCOMPARE(lvwph->m_clipItem->clip(), false);
436+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
437+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
438+ QCOMPARE(lvwph->contentY(), 520.);
439+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
440+
441+ model->setProperty(0, "size", 400);
442+
443+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
444+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
445+ verifyItem(0, -320., 200., true);
446+ verifyItem(1, -120, 350., false);
447+ verifyItem(2, 230, 350., false);
448+ verifyItem(3, 580, 350., true);
449+ QCOMPARE(lvwph->m_minYExtent, 162.5);
450+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
451+ QCOMPARE(lvwph->m_clipItem->clip(), false);
452+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
453+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
454+ QCOMPARE(lvwph->contentY(), 520.);
455+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
456+
457+ scrollToTop();
458+
459+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
460+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
461+ verifyItem(0, 50., 400., false);
462+ verifyItem(1, 450, 200., false);
463+ verifyItem(2, 650, 350., true);
464+ QCOMPARE(lvwph->m_minYExtent, 250.);
465+ QCOMPARE(lvwph->m_clipItem->y(), -250.);
466+ QCOMPARE(lvwph->m_clipItem->clip(), false);
467+ QCOMPARE(lvwph->m_headerItem->y(), -250.);
468+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
469+ QCOMPARE(lvwph->contentY(), -250.);
470+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
471+ }
472+
473+ void testShowHideShowHeaderAtBottom()
474+ {
475+ scrollToBottom();
476+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
477+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
478+ verifyItem(0, -508., 350., true);
479+ verifyItem(1, -158, 350., false);
480+ verifyItem(2, 192, 350., false);
481+ QCOMPARE(lvwph->m_minYExtent, 350.);
482+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
483+ QCOMPARE(lvwph->m_clipItem->clip(), false);
484+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
485+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
486+ QCOMPARE(lvwph->contentY(), 1258.);
487+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
488+
489+ changeContentY(-30);
490+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
491+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
492+ verifyItem(0, -508., 350., true);
493+ verifyItem(1, -158, 350., false);
494+ verifyItem(2, 192, 350., false);
495+ QCOMPARE(lvwph->m_minYExtent, 350.);
496+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
497+ QCOMPARE(lvwph->m_clipItem->clip(), true);
498+ QCOMPARE(lvwph->m_headerItem->y(), 1208.);
499+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
500+ QCOMPARE(lvwph->contentY(), 1228.);
501+ QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
502+
503+ changeContentY(30);
504+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
505+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
506+ verifyItem(0, -508., 350., true);
507+ verifyItem(1, -158, 350., false);
508+ verifyItem(2, 192, 350., false);
509+ QCOMPARE(lvwph->m_minYExtent, 350.);
510+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
511+ QCOMPARE(lvwph->m_clipItem->clip(), false);
512+ QCOMPARE(lvwph->m_headerItem->y(), -350.);
513+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
514+ QCOMPARE(lvwph->contentY(), 1258.);
515+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
516+
517+ changeContentY(-30);
518+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
519+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
520+ verifyItem(0, -508., 350., true);
521+ verifyItem(1, -158, 350., false);
522+ verifyItem(2, 192, 350., false);
523+ QCOMPARE(lvwph->m_minYExtent, 350.);
524+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
525+ QCOMPARE(lvwph->m_clipItem->clip(), true);
526+ QCOMPARE(lvwph->m_headerItem->y(), 1208.);
527+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
528+ QCOMPARE(lvwph->contentY(), 1228.);
529+ QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
530+ }
531+
532+ void testChangeDelegateAtBottom()
533+ {
534+ scrollToBottom();
535+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
536+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
537+ verifyItem(0, -508., 350., true);
538+ verifyItem(1, -158, 350., false);
539+ verifyItem(2, 192, 350., false);
540+ QCOMPARE(lvwph->m_minYExtent, 350.);
541+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
542+ QCOMPARE(lvwph->m_clipItem->clip(), false);
543+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
544+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
545+ QCOMPARE(lvwph->contentY(), 1258.);
546+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
547+
548+ lvwph->setDelegate(otherDelegate);
549+
550+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 6);
551+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
552+ verifyItem(0, 50., 35., false);
553+ verifyItem(1, 85, 35., false);
554+ verifyItem(2, 120, 35., false);
555+ verifyItem(3, 155, 35., false);
556+ verifyItem(4, 190, 35., false);
557+ verifyItem(5, 225, 35., false);
558+ QCOMPARE(lvwph->m_minYExtent, 0.);
559+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
560+ QCOMPARE(lvwph->m_clipItem->clip(), false);
561+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
562+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
563+ QCOMPARE(lvwph->contentY(), 0.);
564+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
565+ }
566+
567+ void testSetEmptyHeaderAtTop()
568+ {
569+ lvwph->setHeader(nullptr);
570+
571+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
572+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
573+ verifyItem(0, 0., 150., false);
574+ verifyItem(1, 150., 200., false);
575+ verifyItem(2, 350., 350., false);
576+ verifyItem(3, 700., 350., true);
577+ QCOMPARE(lvwph->m_minYExtent, 0.);
578+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
579+ QCOMPARE(lvwph->m_clipItem->clip(), false);
580+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
581+ QCOMPARE(lvwph->contentY(), 0.);
582+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
583+ }
584+
585+ void testSetEmptyHeaderAtBottom()
586+ {
587+ scrollToBottom();
588+ lvwph->setHeader(nullptr);
589+
590+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
591+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
592+ verifyItem(0, -508., 350., true);
593+ verifyItem(1, -158, 350., false);
594+ verifyItem(2, 192, 350., false);
595+ QCOMPARE(lvwph->m_minYExtent, 300.);
596+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
597+ QCOMPARE(lvwph->m_clipItem->clip(), false);
598+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
599+ QCOMPARE(lvwph->contentY(), 1258.);
600+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
601+
602+ scrollToTop();
603+
604+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
605+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
606+ verifyItem(0, 0., 150., false);
607+ verifyItem(1, 150., 200., false);
608+ verifyItem(2, 350., 350., false);
609+ verifyItem(3, 700., 350., true);
610+ QCOMPARE(lvwph->m_minYExtent, -50.);
611+ QCOMPARE(lvwph->m_clipItem->y(), 50.);
612+ QCOMPARE(lvwph->m_clipItem->clip(), false);
613+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
614+ QCOMPARE(lvwph->contentY(), 50.);
615+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
616+ }
617+
618+ void testSetEmptyHeaderWhenPartlyShownClipped()
619+ {
620+ scrollToBottom();
621+ changeContentY(-30);
622+ lvwph->setHeader(nullptr);
623+
624+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
625+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
626+ verifyItem(0, -508., 350., true);
627+ verifyItem(1, -158, 350., false);
628+ verifyItem(2, 192, 350., false);
629+ QCOMPARE(lvwph->m_minYExtent, 330.);
630+ QCOMPARE(lvwph->m_clipItem->y(), 1228.);
631+ QCOMPARE(lvwph->m_clipItem->clip(), false);
632+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
633+ QCOMPARE(lvwph->contentY(), 1228.);
634+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
635+ QTRY_VERIFY(lvwph->isAtYEnd());
636+
637+ scrollToTop();
638+
639+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
640+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
641+ verifyItem(0, 0., 150., false);
642+ verifyItem(1, 150., 200., false);
643+ verifyItem(2, 350., 350., false);
644+ verifyItem(3, 700., 350., true);
645+ QCOMPARE(lvwph->m_minYExtent, -20.);
646+ QCOMPARE(lvwph->m_clipItem->y(), 20.);
647+ QCOMPARE(lvwph->m_clipItem->clip(), false);
648+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
649+ QCOMPARE(lvwph->contentY(), 20.);
650+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
651+ }
652+
653+ void testSetEmptyHeaderWhenPartlyShownNotClipped()
654+ {
655+ changeContentY(30);
656+ lvwph->setHeader(nullptr);
657+
658+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
659+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
660+ verifyItem(0, -30., 150., false);
661+ verifyItem(1, 120., 200., false);
662+ verifyItem(2, 320., 350., false);
663+ verifyItem(3, 670., 350., true);
664+ QCOMPARE(lvwph->m_minYExtent, 0.);
665+ QCOMPARE(lvwph->m_clipItem->y(), 30.);
666+ QCOMPARE(lvwph->m_clipItem->clip(), false);
667+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
668+ QCOMPARE(lvwph->contentY(), 30.);
669+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
670+ }
671+
672+ void testSetNullDelegate()
673+ {
674+ lvwph->setDelegate(nullptr);
675+
676+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 0);
677+ QCOMPARE(lvwph->m_firstVisibleIndex, -1);
678+ QCOMPARE(lvwph->m_minYExtent, 0.);
679+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
680+ QCOMPARE(lvwph->m_clipItem->clip(), false);
681+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
682+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
683+ QCOMPARE(lvwph->contentY(), 0.);
684+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
685+ QTRY_COMPARE(lvwph->contentHeight(), 50.);
686+ QVERIFY(lvwph->isAtYBeginning());
687+ QVERIFY(lvwph->isAtYEnd());
688+ }
689+
690+ void testInsertItems()
691+ {
692+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100));
693+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125));
694+
695+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
696+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
697+ verifyItem(0, 50., 150., false);
698+ verifyItem(1, 200., 125., false);
699+ verifyItem(2, 325., 100., false);
700+ verifyItem(3, 425., 200., false);
701+ verifyItem(4, 625., 350., true);
702+ QCOMPARE(lvwph->m_minYExtent, 0.);
703+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
704+ QCOMPARE(lvwph->m_clipItem->clip(), false);
705+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
706+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
707+ QCOMPARE(lvwph->contentY(), 0.);
708+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
709+ }
710+
711+ void testInsertItemsOnNotShownPosition()
712+ {
713+ changeContentY(700);
714+
715+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
716+ QTRY_COMPARE(lvwph->m_firstVisibleIndex, 2);
717+ verifyItem(0, -300., 350., false);
718+ verifyItem(1, 50, 350., false);
719+ verifyItem(2, 400, 350., false);
720+ verifyItem(3, 750, 350., true);
721+ QCOMPARE(lvwph->m_minYExtent, 350.);
722+ QCOMPARE(lvwph->m_clipItem->y(), 700.);
723+ QCOMPARE(lvwph->m_clipItem->clip(), false);
724+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
725+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
726+ QCOMPARE(lvwph->contentY(), 700.);
727+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
728+
729+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100));
730+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125));
731+
732+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
733+ QCOMPARE(lvwph->m_firstVisibleIndex, 4);
734+ verifyItem(0, -300., 350., false);
735+ verifyItem(1, 50, 350., false);
736+ verifyItem(2, 400, 350., false);
737+ verifyItem(3, 750, 350., true);
738+ QCOMPARE(lvwph->m_minYExtent, 1050.);
739+ QCOMPARE(lvwph->m_clipItem->y(), 700.);
740+ QCOMPARE(lvwph->m_clipItem->clip(), false);
741+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
742+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
743+ QCOMPARE(lvwph->contentY(), 700.);
744+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
745+
746+ scrollToTop();
747+
748+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
749+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
750+ verifyItem(0, 50., 150., false);
751+ verifyItem(1, 200., 125., false);
752+ verifyItem(2, 325., 100., false);
753+ verifyItem(3, 425., 200., false);
754+ verifyItem(4, 625., 350., true);
755+ QCOMPARE(lvwph->m_minYExtent, 225.);
756+ QCOMPARE(lvwph->m_clipItem->y(), -225.);
757+ QCOMPARE(lvwph->m_clipItem->clip(), false);
758+ QCOMPARE(lvwph->m_headerItem->y(), -225.);
759+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
760+ QCOMPARE(lvwph->contentY(), -225.);
761+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
762+ }
763+
764+ void testInsertItemsAtEndOfViewport()
765+ {
766+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 3), Q_ARG(QVariant, 100));
767+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 3), Q_ARG(QVariant, 125));
768+
769+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
770+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
771+ verifyItem(0, 50., 150., false);
772+ verifyItem(1, 200., 200., false);
773+ verifyItem(2, 400., 350., false);
774+ verifyItem(3, 750., 125., true);
775+ QCOMPARE(lvwph->m_minYExtent, 0.);
776+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
777+ QCOMPARE(lvwph->m_clipItem->clip(), false);
778+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
779+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
780+ QCOMPARE(lvwph->contentY(), 0.);
781+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
782+ }
783+
784+ void testInsertItemsBeforeValidIndex()
785+ {
786+ changeContentY(520);
787+
788+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
789+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
790+ verifyItem(0, -320., 200., true);
791+ verifyItem(1, -120, 350., false);
792+ verifyItem(2, 230, 350., false);
793+ verifyItem(3, 580, 350., true);
794+ QCOMPARE(lvwph->m_minYExtent, 162.5);
795+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
796+ QCOMPARE(lvwph->m_clipItem->clip(), false);
797+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
798+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
799+ QCOMPARE(lvwph->contentY(), 520.);
800+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
801+
802+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100));
803+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125));
804+
805+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
806+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
807+ verifyItem(0, -320., 200., true);
808+ verifyItem(1, -120, 350., false);
809+ verifyItem(2, 230, 350., false);
810+ verifyItem(3, 580, 350., true);
811+ QCOMPARE(lvwph->m_minYExtent, 787.5);
812+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
813+ QCOMPARE(lvwph->m_clipItem->clip(), false);
814+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
815+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
816+ QCOMPARE(lvwph->contentY(), 520.);
817+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
818+ }
819+
820+ void testInsertItemsBeforeViewport()
821+ {
822+ changeContentY(375);
823+
824+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
825+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
826+ verifyItem(0, -325., 150., true);
827+ verifyItem(1, -175, 200., false);
828+ verifyItem(2, 25, 350., false);
829+ verifyItem(3, 375, 350., false);
830+ verifyItem(4, 725, 350., true);
831+ QCOMPARE(lvwph->m_minYExtent, 0.);
832+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
833+ QCOMPARE(lvwph->m_clipItem->clip(), false);
834+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
835+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
836+ QCOMPARE(lvwph->contentY(), 375.);
837+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
838+
839+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100));
840+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125));
841+
842+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
843+ QCOMPARE(lvwph->m_firstVisibleIndex, 2);
844+ verifyItem(0, -275., 100., true);
845+ verifyItem(1, -175, 200., false);
846+ verifyItem(2, 25, 350., false);
847+ verifyItem(3, 375, 350., false);
848+ verifyItem(4, 725, 350., true);
849+ QCOMPARE(lvwph->m_minYExtent, 490.);
850+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
851+ QCOMPARE(lvwph->m_clipItem->clip(), false);
852+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
853+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
854+ QCOMPARE(lvwph->contentY(), 375.);
855+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
856+
857+ scrollToTop();
858+
859+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
860+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
861+ verifyItem(0, 50., 150., false);
862+ verifyItem(1, 200., 125., false);
863+ verifyItem(2, 325., 100., false);
864+ verifyItem(3, 425., 200., false);
865+ verifyItem(4, 625., 350., true);
866+ QCOMPARE(lvwph->m_minYExtent, 225.);
867+ QCOMPARE(lvwph->m_clipItem->y(), -225.);
868+ QCOMPARE(lvwph->m_clipItem->clip(), false);
869+ QCOMPARE(lvwph->m_headerItem->y(), -225.);
870+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
871+ QCOMPARE(lvwph->contentY(), -225.);
872+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
873+ }
874+
875+ void testInsertItemsAtBottom()
876+ {
877+ scrollToBottom();
878+
879+ QVERIFY(lvwph->isAtYEnd());
880+
881+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 100));
882+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 125));
883+
884+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
885+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
886+ verifyItem(0, -508., 350., true);
887+ verifyItem(1, -158, 350., false);
888+ verifyItem(2, 192, 350., false);
889+ verifyItem(3, 542, 125., true);
890+ verifyItem(4, 667, 100., true);
891+ QCOMPARE(lvwph->m_minYExtent, 65.);
892+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
893+ QCOMPARE(lvwph->m_clipItem->clip(), false);
894+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
895+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
896+ QCOMPARE(lvwph->contentY(), 1258.);
897+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
898+ QVERIFY(!lvwph->isAtYEnd());
899+
900+ scrollToBottom();
901+
902+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
903+ QCOMPARE(lvwph->m_firstVisibleIndex, 4);
904+ verifyItem(0, -383., 350., true);
905+ verifyItem(1, -33, 350., false);
906+ verifyItem(2, 317, 125., false);
907+ verifyItem(3, 442, 100., false);
908+ QCOMPARE(lvwph->m_minYExtent, -125.);
909+ QCOMPARE(lvwph->m_clipItem->y(), 1483.);
910+ QCOMPARE(lvwph->m_clipItem->clip(), false);
911+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
912+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
913+ QCOMPARE(lvwph->contentY(), 1483.);
914+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
915+ QVERIFY(lvwph->isAtYEnd());
916+ }
917+
918+ void testInsertItemAtTop()
919+ {
920+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
921+
922+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
923+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
924+ verifyItem(0, 50., 75., false);
925+ verifyItem(1, 125., 150., false);
926+ verifyItem(2, 275., 200., false);
927+ verifyItem(3, 475., 350., false);
928+ QCOMPARE(lvwph->m_minYExtent, 0.);
929+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
930+ QCOMPARE(lvwph->m_clipItem->clip(), false);
931+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
932+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
933+ QCOMPARE(lvwph->contentY(), 0.);
934+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
935+ QVERIFY(lvwph->isAtYBeginning());
936+ }
937+
938+ void testInsertItem10SmallItemsAtTopWhenAtBottom()
939+ {
940+ scrollToBottom();
941+
942+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
943+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
944+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
945+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
946+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
947+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
948+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
949+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
950+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
951+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75));
952+
953+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
954+ QCOMPARE(lvwph->m_firstVisibleIndex, 13);
955+ verifyItem(0, -508., 350., true);
956+ verifyItem(1, -158, 350., false);
957+ verifyItem(2, 192, 350., false);
958+ QCOMPARE(lvwph->m_minYExtent, 3850.);
959+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
960+ QCOMPARE(lvwph->m_clipItem->clip(), false);
961+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
962+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
963+ QCOMPARE(lvwph->contentY(), 1258.);
964+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
965+
966+ changeContentY(-1700);
967+
968+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 12);
969+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
970+ verifyItem(0, -308., 75., true);
971+ verifyItem(1, -233., 75., true);
972+ verifyItem(2, -158., 75., true);
973+ verifyItem(3, -83., 75., true);
974+ verifyItem(4, -8., 75., false);
975+ verifyItem(5, 67., 75., false);
976+ verifyItem(6, 142., 75., false);
977+ verifyItem(7, 217., 75., false);
978+ verifyItem(8, 292., 75., false);
979+ verifyItem(9, 367., 75., false);
980+ verifyItem(10, 442., 150., false);
981+ verifyItem(11, 592., 200., true);
982+ QCOMPARE(lvwph->m_minYExtent, 750.);
983+ QCOMPARE(lvwph->m_clipItem->y(), -392.);
984+ QCOMPARE(lvwph->m_clipItem->clip(), true);
985+ QCOMPARE(lvwph->m_headerItem->y(), -442.);
986+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
987+ QCOMPARE(lvwph->contentY(), -442.);
988+ QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
989+ }
990+
991+ void testRemoveItemsAtTop()
992+ {
993+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 2));
994+
995+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
996+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
997+ verifyItem(0, 50., 350., false);
998+ verifyItem(1, 400., 350., false);
999+ verifyItem(2, 750., 350., true);
1000+ QCOMPARE(lvwph->m_minYExtent, 0.);
1001+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1002+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1003+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1004+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1005+ QCOMPARE(lvwph->contentY(), 0.);
1006+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1007+ QVERIFY(lvwph->isAtYBeginning());
1008+ }
1009+
1010+ void testRemoveNonCreatedItemsAtTopWhenAtBottom()
1011+ {
1012+ scrollToBottom();
1013+
1014+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 2));
1015+
1016+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1017+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1018+ verifyItem(0, -508., 350., true);
1019+ verifyItem(1, -158, 350., false);
1020+ verifyItem(2, 192, 350., false);
1021+ QCOMPARE(lvwph->m_minYExtent, -350.);
1022+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
1023+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1024+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1025+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1026+ QCOMPARE(lvwph->contentY(), 1258.);
1027+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1028+ }
1029+
1030+ void testRemoveLastItemsAtBottom()
1031+ {
1032+ scrollToBottom();
1033+
1034+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 4), Q_ARG(QVariant, 2));
1035+
1036+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1037+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1038+ verifyItem(0, -358., 200., true);
1039+ verifyItem(1, -158, 350., false);
1040+ verifyItem(2, 192, 350., false);
1041+ QCOMPARE(lvwph->m_minYExtent, 150.);
1042+ QCOMPARE(lvwph->m_clipItem->y(), 558.);
1043+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1044+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1045+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1046+ QCOMPARE(lvwph->contentY(), 558.);
1047+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1048+ }
1049+
1050+ void testRemoveItemOutOfViewport()
1051+ {
1052+ changeContentY(520);
1053+
1054+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1055+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1056+ verifyItem(0, -320., 200., true);
1057+ verifyItem(1, -120, 350., false);
1058+ verifyItem(2, 230, 350., false);
1059+ verifyItem(3, 580, 350., true);
1060+ QCOMPARE(lvwph->m_minYExtent, 162.5);
1061+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
1062+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1063+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1064+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1065+ QCOMPARE(lvwph->contentY(), 520.);
1066+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1067+
1068+
1069+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 1), Q_ARG(QVariant, 1));
1070+
1071+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1072+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1073+ verifyItem(0, -270., 150., true);
1074+ verifyItem(1, -120., 350., false);
1075+ verifyItem(2, 230, 350., false);
1076+ verifyItem(3, 580, 350., true);
1077+ QCOMPARE(lvwph->m_minYExtent, -200.);
1078+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
1079+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1080+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1081+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1082+ QCOMPARE(lvwph->contentY(), 520.);
1083+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1084+ }
1085+
1086+ void testMoveFirstItems()
1087+ {
1088+ QMetaObject::invokeMethod(model, "moveItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 1), Q_ARG(QVariant, 1));
1089+
1090+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1091+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1092+ verifyItem(0, 50., 200., false);
1093+ verifyItem(1, 250., 150., false);
1094+ verifyItem(2, 400., 350., false);
1095+ verifyItem(3, 750., 350., true);
1096+ QCOMPARE(lvwph->m_minYExtent, 0.);
1097+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1098+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1099+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1100+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1101+ QCOMPARE(lvwph->contentY(), 0.);
1102+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1103+
1104+ }
1105+
1106+ void testMoveFirstOutOfVisibleItems()
1107+ {
1108+ QMetaObject::invokeMethod(model, "moveItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 4), Q_ARG(QVariant, 1));
1109+
1110+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1111+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1112+ verifyItem(0, 50., 200., false);
1113+ verifyItem(1, 250., 350., false);
1114+ verifyItem(2, 600., 350., true);
1115+ QCOMPARE(lvwph->m_minYExtent, 0.);
1116+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1117+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1118+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1119+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1120+ QCOMPARE(lvwph->contentY(), 0.);
1121+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1122+
1123+ }
1124+
1125+ void testMoveFirstToLastAtBottom()
1126+ {
1127+ scrollToBottom();
1128+
1129+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1130+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
1131+ verifyItem(0, -508., 350., true);
1132+ verifyItem(1, -158, 350., false);
1133+ verifyItem(2, 192, 350., false);
1134+ QCOMPARE(lvwph->m_minYExtent, 350.);
1135+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
1136+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1137+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1138+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1139+ QCOMPARE(lvwph->contentY(), 1258.);
1140+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1141+
1142+ QMetaObject::invokeMethod(model, "moveItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 5), Q_ARG(QVariant, 1));
1143+
1144+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1145+ QCOMPARE(lvwph->m_firstVisibleIndex, 2);
1146+ verifyItem(0, -508., 350., true);
1147+ verifyItem(1, -158, 350., false);
1148+ verifyItem(2, 192, 350., false);
1149+ verifyItem(3, 542, 150., true);
1150+ QCOMPARE(lvwph->m_minYExtent, -100.);
1151+ QCOMPARE(lvwph->m_clipItem->y(), 1258.);
1152+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1153+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1154+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1155+ QCOMPARE(lvwph->contentY(), 1258.);
1156+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1157+ QVERIFY(!lvwph->isAtYEnd());
1158+ }
1159+
1160+ void testChangeSizeVisibleItemNotOnViewport()
1161+ {
1162+ changeContentY(440);
1163+
1164+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1165+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1166+ verifyItem(0, -390., 150., true);
1167+ verifyItem(1, -240., 200., true);
1168+ verifyItem(2, -40, 350., false);
1169+ verifyItem(3, 310, 350., false);
1170+ verifyItem(4, 660, 350., true);
1171+ QCOMPARE(lvwph->m_minYExtent, 0.);
1172+ QCOMPARE(lvwph->m_clipItem->y(), 440.);
1173+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1174+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1175+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1176+ QCOMPARE(lvwph->contentY(), 440.);
1177+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1178+
1179+ model->setProperty(1, "size", 100);
1180+
1181+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1182+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1183+ verifyItem(0, -290., 150., true);
1184+ verifyItem(1, -140., 100., true);
1185+ verifyItem(2, -40, 350., false);
1186+ verifyItem(3, 310, 350., false);
1187+ verifyItem(4, 660, 350., true);
1188+ QCOMPARE(lvwph->m_minYExtent, -100.);
1189+ QCOMPARE(lvwph->m_clipItem->y(), 440.);
1190+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1191+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1192+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1193+ QCOMPARE(lvwph->contentY(), 440.);
1194+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1195+ }
1196+
1197+ void testShowHeaderCloseToTheTop()
1198+ {
1199+ changeContentY(375);
1200+
1201+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1202+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1203+ verifyItem(0, -325., 150., true);
1204+ verifyItem(1, -175, 200., false);
1205+ verifyItem(2, 25, 350., false);
1206+ verifyItem(3, 375, 350., false);
1207+ verifyItem(4, 725, 350., true);
1208+ QCOMPARE(lvwph->m_minYExtent, 0.);
1209+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
1210+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1211+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1212+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1213+ QCOMPARE(lvwph->contentY(), 375.);
1214+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);;
1215+
1216+ lvwph->showHeader();
1217+
1218+ QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1219+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1220+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1221+ verifyItem(0, -375., 150., true);
1222+ verifyItem(1, -225, 200., true);
1223+ verifyItem(2, -25, 350., false);
1224+ verifyItem(3, 325, 350., false);
1225+ verifyItem(4, 675, 350., true);
1226+ QCOMPARE(lvwph->m_minYExtent, 50.);
1227+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
1228+ QCOMPARE(lvwph->m_clipItem->clip(), true);
1229+ QCOMPARE(lvwph->m_headerItem->y(), 325.);
1230+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1231+ QCOMPARE(lvwph->contentY(), 325.);
1232+ QCOMPARE(lvwph->m_headerItemShownHeight, 50.);;
1233+
1234+ scrollToTop();
1235+
1236+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1237+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1238+ verifyItem(0, 50., 150., false);
1239+ verifyItem(1, 200., 200., false);
1240+ verifyItem(2, 400., 350., false);
1241+ verifyItem(3, 750., 350., true);
1242+ QCOMPARE(lvwph->m_minYExtent, 50.);
1243+ QCOMPARE(lvwph->m_clipItem->y(), -50.);
1244+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1245+ QCOMPARE(lvwph->m_headerItem->y(), -50.);
1246+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1247+ QCOMPARE(lvwph->contentY(), -50.);
1248+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1249+ }
1250+
1251+ void testShowHeaderAtBottom()
1252+ {
1253+ scrollToBottom();
1254+
1255+ lvwph->showHeader();
1256+
1257+ QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1258+ QTRY_VERIFY (lvwph->isAtYEnd());
1259+ }
1260+
1261+ void growWindow()
1262+ {
1263+ view->rootObject()->setHeight(850);
1264+
1265+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1266+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1267+ verifyItem(0, 50., 150., false);
1268+ verifyItem(1, 200., 200., false);
1269+ verifyItem(2, 400., 350., false);
1270+ verifyItem(3, 750., 350., false);
1271+ verifyItem(4, 1100., 350., true);
1272+ QCOMPARE(lvwph->m_minYExtent, 0.);
1273+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1274+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1275+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1276+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1277+ QCOMPARE(lvwph->contentY(), 0.);
1278+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1279+ }
1280+
1281+ void growWindowAtBottom()
1282+ {
1283+ scrollToBottom();
1284+
1285+ view->rootObject()->setHeight(850);
1286+
1287+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1288+ QCOMPARE(lvwph->m_firstVisibleIndex, 2);
1289+ verifyItem(0, -550., 350., true);
1290+ verifyItem(1, -200., 350., false);
1291+ verifyItem(2, 150, 350., false);
1292+ verifyItem(3, 500, 350., false);
1293+ QCOMPARE(lvwph->m_minYExtent, 350.);
1294+ QCOMPARE(lvwph->m_clipItem->y(), 950.);
1295+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1296+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1297+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1298+ QCOMPARE(lvwph->contentY(), 950.);
1299+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1300+ }
1301+
1302+private:
1303+ QQuickView *view;
1304+ ListViewWithPageHeader *lvwph;
1305+ QQuickListModel *model;
1306+ QQmlComponent *otherDelegate;
1307+};
1308+
1309+QTEST_MAIN(ListViewWithPageHeaderTest)
1310+
1311+#include "listviewwithpageheadertest.moc"
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cppnew file+1567
@@ -0,0 +1,1567 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "listviewwithpageheader.h"
18+
19+#include <QAbstractItemModel>
20+#include <QQmlEngine>
21+#include <QQuickView>
22+#include <QtTestGui>
23+#include <private/qquicklistmodel_p.h>
24+#include <private/qquickanimation_p.h>
25+#include <private/qquickitem_p.h>
26+
27+class ListViewWithPageHeaderTestSection : public QObject
28+{
29+ Q_OBJECT
30+
31+private:
32+ void verifyItem(int visibleIndex, qreal pos, qreal height, bool culled, const QString &sectionHeader, bool sectionHeaderCulled)
33+ {
34+ QTRY_VERIFY(visibleIndex < lvwph->m_visibleItems.count());
35+ QTRY_COMPARE(lvwph->m_visibleItems[visibleIndex]->y(), pos);
36+ QTRY_COMPARE(lvwph->m_visibleItems[visibleIndex]->height(), height);
37+ QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->m_item)->culled, culled);
38+ QCOMPARE(section(lvwph->m_visibleItems[visibleIndex]->m_sectionItem), sectionHeader);
39+ if (!sectionHeader.isNull()) {
40+ QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->m_sectionItem)->culled, sectionHeaderCulled);
41+ }
42+ }
43+
44+ void changeContentY(qreal change)
45+ {
46+ const qreal dest = lvwph->contentY() + change;
47+ if (dest > lvwph->contentY()) {
48+ const qreal jump = 25;
49+ while (lvwph->contentY() + jump < dest) {
50+ lvwph->setContentY(lvwph->contentY() + jump);
51+ QTest::qWait(1);
52+ }
53+ } else {
54+ const qreal jump = -25;
55+ while (lvwph->contentY() + jump > dest) {
56+ lvwph->setContentY(lvwph->contentY() + jump);
57+ QTest::qWait(1);
58+ }
59+ }
60+ lvwph->setContentY(dest);
61+ QTest::qWait(1);
62+ }
63+
64+ void scrollToTop()
65+ {
66+ const qreal jump = -25;
67+ while (!lvwph->isAtYBeginning()) {
68+ if (lvwph->contentY() + jump > -lvwph->minYExtent()) {
69+ lvwph->setContentY(lvwph->contentY() + jump);
70+ } else {
71+ lvwph->setContentY(lvwph->contentY() - 1);
72+ }
73+ QTest::qWait(1);
74+ }
75+ }
76+
77+ void scrollToBottom()
78+ {
79+ const qreal jump = 25;
80+ while (!lvwph->isAtYEnd()) {
81+ if (lvwph->contentY() + lvwph->height() + jump < lvwph->contentHeight()) {
82+ lvwph->setContentY(lvwph->contentY() + jump);
83+ } else {
84+ lvwph->setContentY(lvwph->contentY() + 1);
85+ }
86+ QTest::qWait(1);
87+ }
88+ }
89+
90+ void verifyInitialTopPosition()
91+ {
92+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
93+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
94+ verifyItem(0, 50., 190., false, "Agressive", false);
95+ verifyItem(1, 240., 240., false, "Regular", false);
96+ verifyItem(2, 480., 390., false, "Mild", false);
97+ QCOMPARE(lvwph->m_minYExtent, 0.);
98+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
99+ QCOMPARE(lvwph->m_clipItem->clip(), false);
100+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
101+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
102+ QCOMPARE(lvwph->contentY(), 0.);
103+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
104+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
105+ }
106+
107+ QString section(QQuickItem *item)
108+ {
109+ return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("section")).toString() : QString();
110+ }
111+
112+private Q_SLOTS:
113+
114+ void initTestCase()
115+ {
116+ }
117+
118+ void init()
119+ {
120+ view = new QQuickView();
121+ view->engine()->addImportPath(BUILT_PLUGINS_DIR);
122+ view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test_section.qml"));
123+ lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
124+ model = view->rootObject()->findChild<QQuickListModel*>();
125+ otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
126+ QVERIFY(lvwph);
127+ QVERIFY(model);
128+ QVERIFY(otherDelegate);
129+ view->show();
130+ QTest::qWaitForWindowExposed(view);
131+
132+ verifyInitialTopPosition();
133+ }
134+
135+ void cleanup()
136+ {
137+ delete view;
138+ }
139+
140+ void testCreationDeletion()
141+ {
142+ // Nothing, init/cleanup already tests this
143+ }
144+
145+ void testDrag1PixelUp()
146+ {
147+ lvwph->setContentY(lvwph->contentY() + 1);
148+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
149+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
150+ verifyItem(0, 49., 190., false, "Agressive", false);
151+ verifyItem(1, 239., 240., false, "Regular", false);
152+ verifyItem(2, 479., 390., false, "Mild", false);
153+ QCOMPARE(lvwph->m_minYExtent, 0.);
154+ QCOMPARE(lvwph->m_clipItem->y(), 1.);
155+ QCOMPARE(lvwph->m_clipItem->clip(), false);
156+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
157+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
158+ QCOMPARE(lvwph->contentY(), 1.);
159+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
160+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
161+ }
162+
163+ void testHeaderDetachDragDown()
164+ {
165+ QTest::mousePress(view, Qt::LeftButton, Qt::NoModifier, QPoint(0, 0));
166+ QTest::qWait(100);
167+ QTest::mouseMove(view, QPoint(0, 5));
168+ QTest::qWait(100);
169+ QTest::mouseMove(view, QPoint(0, 10));
170+ QTest::qWait(100);
171+ QTest::mouseMove(view, QPoint(0, 15));
172+ QTest::qWait(100);
173+ QTest::mouseMove(view, QPoint(0, 20));
174+ QTest::qWait(100);
175+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
176+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
177+ verifyItem(0, 55., 190., false, "Agressive", false);
178+ verifyItem(1, 245., 240., false, "Regular", false);
179+ verifyItem(2, 485., 390., false, "Mild", false);
180+ QCOMPARE(lvwph->m_minYExtent, 0.);
181+ QCOMPARE(lvwph->m_clipItem->y(), -5.);
182+ QCOMPARE(lvwph->m_clipItem->clip(), false);
183+ QCOMPARE(lvwph->m_headerItem->y(), -5.);
184+ QCOMPARE(lvwph->m_headerItem->height(), 55.);
185+ QCOMPARE(lvwph->contentY(), -5.);
186+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
187+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
188+
189+ QTest::mouseRelease(view, Qt::LeftButton, Qt::NoModifier, QPoint(0, 15));
190+
191+ verifyInitialTopPosition();
192+ }
193+
194+ void testDrag375PixelUp()
195+ {
196+ changeContentY(375);
197+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
198+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
199+ verifyItem(0, -325., 190., true, "Agressive", true);
200+ verifyItem(1, -135, 240., false, "Regular", true);
201+ verifyItem(2, 105, 390., false, "Mild", false);
202+ verifyItem(3, 495, 390., false, "Bold", false);
203+ QCOMPARE(lvwph->m_minYExtent, 0.);
204+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
205+ QCOMPARE(lvwph->m_clipItem->clip(), false);
206+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
207+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
208+ QCOMPARE(lvwph->contentY(), 375.);
209+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
210+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
211+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
212+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
213+ }
214+
215+ void testDrag520PixelUp()
216+ {
217+ changeContentY(520);
218+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
219+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
220+ verifyItem(0, -280., 240., true, "Regular", true);
221+ verifyItem(1, -40, 390., false, "Mild", true);
222+ verifyItem(2, 350, 390., false, "Bold", false);
223+ verifyItem(3, 740, 350., true, QString(), true);
224+ QCOMPARE(lvwph->m_minYExtent, 152.5);
225+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
226+ QCOMPARE(lvwph->m_clipItem->clip(), false);
227+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
228+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
229+ QCOMPARE(lvwph->contentY(), 520.);
230+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
231+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
232+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
233+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
234+ }
235+
236+ void testDragHeaderUpThenShow()
237+ {
238+ changeContentY(120);
239+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
240+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
241+ verifyItem(0, -70., 190., false, "Agressive", true);
242+ verifyItem(1, 120., 240., false, "Regular", false);
243+ verifyItem(2, 360., 390., false, "Mild", false);
244+ verifyItem(3, 750., 390., true, "Bold", true);
245+ QCOMPARE(lvwph->m_minYExtent, 0.);
246+ QCOMPARE(lvwph->m_clipItem->y(), 120.);
247+ QCOMPARE(lvwph->m_clipItem->clip(), false);
248+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
249+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
250+ QCOMPARE(lvwph->contentY(), 120.);
251+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
252+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
253+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
254+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
255+
256+ changeContentY(-30);
257+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
258+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
259+ verifyItem(0, -70., 190., false, "Agressive", true);
260+ verifyItem(1, 120., 240., false, "Regular", false);
261+ verifyItem(2, 360., 390., false, "Mild", false);
262+ verifyItem(3, 750., 390., true, "Bold", true);
263+ QCOMPARE(lvwph->m_minYExtent, 0.);
264+ QCOMPARE(lvwph->m_clipItem->y(), 120.);
265+ QCOMPARE(lvwph->m_clipItem->clip(), true);
266+ QTRY_COMPARE(lvwph->m_headerItem->y(), 70.);
267+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
268+ QCOMPARE(lvwph->contentY(), 90.);
269+ QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
270+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
271+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
272+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
273+ }
274+
275+ void testDragHeaderUpThenShowWithoutHidingTotally()
276+ {
277+ changeContentY(10);
278+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
279+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
280+ verifyItem(0, 40., 190., false, "Agressive", false);
281+ verifyItem(1, 230., 240., false, "Regular", false);
282+ verifyItem(2, 470., 390., false, "Mild", false);
283+ QCOMPARE(lvwph->m_minYExtent, 0.);
284+ QCOMPARE(lvwph->m_clipItem->y(), 10.);
285+ QCOMPARE(lvwph->m_clipItem->clip(), false);
286+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
287+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
288+ QCOMPARE(lvwph->contentY(), 10.);
289+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
290+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
291+
292+ changeContentY(-1);
293+
294+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
295+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
296+ verifyItem(0, 41., 190., false, "Agressive", false);
297+ verifyItem(1, 231., 240., false, "Regular", false);
298+ verifyItem(2, 471., 390., false, "Mild", false);
299+ QCOMPARE(lvwph->m_minYExtent, 0.);
300+ QCOMPARE(lvwph->m_clipItem->y(), 9.);
301+ QCOMPARE(lvwph->m_clipItem->clip(), false);
302+ QTRY_COMPARE(lvwph->m_headerItem->y(), 0.);
303+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
304+ QCOMPARE(lvwph->contentY(), 9.);
305+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
306+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
307+ }
308+
309+ void testPositionAtBeginningIndex0Visible()
310+ {
311+ changeContentY(375);
312+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
313+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
314+ verifyItem(0, -325., 190., true, "Agressive", true);
315+ verifyItem(1, -135, 240., false, "Regular", true);
316+ verifyItem(2, 105, 390., false, "Mild", false);
317+ verifyItem(3, 495, 390., false, "Bold", false);
318+ QCOMPARE(lvwph->m_minYExtent, 0.);
319+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
320+ QCOMPARE(lvwph->m_clipItem->clip(), false);
321+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
322+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
323+ QCOMPARE(lvwph->contentY(), 375.);
324+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
325+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
326+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
327+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
328+
329+ lvwph->positionAtBeginning();
330+
331+ verifyInitialTopPosition();
332+ }
333+
334+ void testPositionAtBeginningIndex0NotVisible()
335+ {
336+ changeContentY(520);
337+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
338+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
339+ verifyItem(0, -280., 240., true, "Regular", true);
340+ verifyItem(1, -40, 390., false, "Mild", true);
341+ verifyItem(2, 350, 390., false, "Bold", false);
342+ verifyItem(3, 740, 350., true, QString(), true);
343+ QCOMPARE(lvwph->m_minYExtent, 152.5);
344+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
345+ QCOMPARE(lvwph->m_clipItem->clip(), false);
346+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
347+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
348+ QCOMPARE(lvwph->contentY(), 520.);
349+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
350+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
351+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
352+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
353+
354+ lvwph->positionAtBeginning();
355+
356+ verifyInitialTopPosition();
357+ }
358+
359+ void testIndex0GrowOnScreen()
360+ {
361+ model->setProperty(0, "size", 400);
362+
363+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
364+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
365+ verifyItem(0, 50., 440., false, "Agressive", false);
366+ verifyItem(1, 490., 240., false, "Regular", false);
367+ verifyItem(2, 730., 390., true, "Mild", true);
368+ QCOMPARE(lvwph->m_minYExtent, 0.);
369+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
370+ QCOMPARE(lvwph->m_clipItem->clip(), false);
371+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
372+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
373+ QCOMPARE(lvwph->contentY(), 0.);
374+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
375+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
376+ }
377+
378+ void testIndex0GrowOffScreen()
379+ {
380+ changeContentY(375);
381+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
382+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
383+ verifyItem(0, -325., 190., true, "Agressive", true);
384+ verifyItem(1, -135, 240., false, "Regular", true);
385+ verifyItem(2, 105, 390., false, "Mild", false);
386+ verifyItem(3, 495, 390., false, "Bold", false);
387+ QCOMPARE(lvwph->m_minYExtent, 0.);
388+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
389+ QCOMPARE(lvwph->m_clipItem->clip(), false);
390+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
391+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
392+ QCOMPARE(lvwph->contentY(), 375.);
393+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
394+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
395+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
396+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
397+
398+ model->setProperty(0, "size", 400);
399+
400+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
401+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
402+ verifyItem(0, -575., 440., true, "Agressive", true);
403+ verifyItem(1, -135, 240., false, "Regular", true);
404+ verifyItem(2, 105, 390., false, "Mild", false);
405+ verifyItem(3, 495, 390., false, "Bold", false);
406+ QCOMPARE(lvwph->m_minYExtent, 250.);
407+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
408+ QCOMPARE(lvwph->m_clipItem->clip(), false);
409+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
410+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
411+ QCOMPARE(lvwph->contentY(), 375.);
412+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
413+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
414+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
415+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
416+
417+ scrollToTop();
418+
419+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
420+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
421+ verifyItem(0, 50., 440., false, "Agressive", false);
422+ verifyItem(1, 490, 240., false, "Regular", false);
423+ verifyItem(2, 730, 390., true, "Mild", true);
424+ QCOMPARE(lvwph->m_minYExtent, 250.);
425+ QCOMPARE(lvwph->m_clipItem->y(), -250.);
426+ QCOMPARE(lvwph->m_clipItem->clip(), false);
427+ QCOMPARE(lvwph->m_headerItem->y(), -250.);
428+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
429+ QCOMPARE(lvwph->contentY(), -250.);
430+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
431+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
432+
433+ changeContentY(30);
434+
435+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
436+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
437+ verifyItem(0, 20., 440., false, "Agressive", false);
438+ verifyItem(1, 460, 240., false, "Regular", false);
439+ verifyItem(2, 700, 390., true, "Mild", true);
440+ QCOMPARE(lvwph->m_minYExtent, 250.);
441+ QCOMPARE(lvwph->m_clipItem->y(), -220.);
442+ QCOMPARE(lvwph->m_clipItem->clip(), false);
443+ QCOMPARE(lvwph->m_headerItem->y(), -250.);
444+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
445+ QCOMPARE(lvwph->contentY(), -220.);
446+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
447+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
448+ }
449+
450+ void testIndex0GrowNotCreated()
451+ {
452+ changeContentY(520);
453+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
454+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
455+ verifyItem(0, -280., 240., true, "Regular", true);
456+ verifyItem(1, -40, 390., false, "Mild", true);
457+ verifyItem(2, 350, 390., false, "Bold", false);
458+ verifyItem(3, 740, 350., true, QString(), true);
459+ QCOMPARE(lvwph->m_minYExtent, 152.5);
460+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
461+ QCOMPARE(lvwph->m_clipItem->clip(), false);
462+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
463+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
464+ QCOMPARE(lvwph->contentY(), 520.);
465+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
466+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
467+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
468+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
469+
470+ model->setProperty(0, "size", 400);
471+
472+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
473+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
474+ verifyItem(0, -280., 240., true, "Regular", true);
475+ verifyItem(1, -40, 390., false, "Mild", true);
476+ verifyItem(2, 350, 390., false, "Bold", false);
477+ verifyItem(3, 740, 350., true, QString(), true);
478+ QCOMPARE(lvwph->m_minYExtent, 152.5);
479+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
480+ QCOMPARE(lvwph->m_clipItem->clip(), false);
481+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
482+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
483+ QCOMPARE(lvwph->contentY(), 520.);
484+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
485+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
486+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
487+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
488+
489+ scrollToTop();
490+
491+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
492+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
493+ verifyItem(0, 50., 440., false, "Agressive", false);
494+ verifyItem(1, 490, 240., false, "Regular", false);
495+ verifyItem(2, 730, 390., true, "Mild", true);
496+ QCOMPARE(lvwph->m_minYExtent, 250.);
497+ QCOMPARE(lvwph->m_clipItem->y(), -250.);
498+ QCOMPARE(lvwph->m_clipItem->clip(), false);
499+ QCOMPARE(lvwph->m_headerItem->y(), -250.);
500+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
501+ QCOMPARE(lvwph->contentY(), -250.);
502+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
503+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
504+ }
505+
506+ void testShowHideShowHeaderAtBottom()
507+ {
508+ scrollToBottom();
509+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
510+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
511+ verifyItem(0, -588., 390., true, "Bold", true);
512+ verifyItem(1, -198, 350., false, QString(), true);
513+ verifyItem(2, 152, 390., false, "Lazy", false);
514+ QCOMPARE(lvwph->m_minYExtent, 310.);
515+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
516+ QCOMPARE(lvwph->m_clipItem->clip(), false);
517+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
518+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
519+ QCOMPARE(lvwph->contentY(), 1458.);
520+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
521+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
522+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
523+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
524+
525+ changeContentY(-30);
526+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
527+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
528+ verifyItem(0, -588., 390., true, "Bold", true);
529+ verifyItem(1, -198, 350., false, QString(), true);
530+ verifyItem(2, 152, 390., false, "Lazy", false);
531+ QCOMPARE(lvwph->m_minYExtent, 310.);
532+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
533+ QCOMPARE(lvwph->m_clipItem->clip(), true);
534+ QCOMPARE(lvwph->m_headerItem->y(), 1408.);
535+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
536+ QCOMPARE(lvwph->contentY(), 1428.);
537+ QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
538+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
539+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
540+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
541+
542+ changeContentY(30);
543+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
544+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
545+ verifyItem(0, -588., 390., true, "Bold", true);
546+ verifyItem(1, -198, 350., false, QString(), true);
547+ verifyItem(2, 152, 390., false, "Lazy", false);
548+ QCOMPARE(lvwph->m_minYExtent, 310.);
549+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
550+ QCOMPARE(lvwph->m_clipItem->clip(), false);
551+ QCOMPARE(lvwph->m_headerItem->y(), -310.);
552+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
553+ QCOMPARE(lvwph->contentY(), 1458.);
554+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
555+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
556+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
557+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
558+
559+ changeContentY(-30);
560+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
561+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
562+ verifyItem(0, -588., 390., true, "Bold", true);
563+ verifyItem(1, -198, 350., false, QString(), true);
564+ verifyItem(2, 152, 390., false, "Lazy", false);
565+ QCOMPARE(lvwph->m_minYExtent, 310.);
566+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
567+ QCOMPARE(lvwph->m_clipItem->clip(), true);
568+ QCOMPARE(lvwph->m_headerItem->y(), 1408.);
569+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
570+ QCOMPARE(lvwph->contentY(), 1428.);
571+ QCOMPARE(lvwph->m_headerItemShownHeight, 30.);
572+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
573+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
574+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
575+ }
576+
577+ void testChangeDelegateAtBottom()
578+ {
579+ scrollToBottom();
580+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
581+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
582+ verifyItem(0, -588., 390., true, "Bold", true);
583+ verifyItem(1, -198, 350., false, QString(), true);
584+ verifyItem(2, 152, 390., false, "Lazy", false);
585+ QCOMPARE(lvwph->m_minYExtent, 310.);
586+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
587+ QCOMPARE(lvwph->m_clipItem->clip(), false);
588+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
589+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
590+ QCOMPARE(lvwph->contentY(), 1458.);
591+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
592+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
593+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
594+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
595+
596+ lvwph->setDelegate(otherDelegate);
597+
598+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 6);
599+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
600+ verifyItem(0, 50., 75., false, "Agressive", false);
601+ verifyItem(1, 125, 75., false, "Regular", false);
602+ verifyItem(2, 200, 75., false, "Mild", false);
603+ verifyItem(3, 275, 75., false, "Bold", false);
604+ verifyItem(4, 350, 35., false, QString(), true);
605+ verifyItem(5, 385, 75., false, "Lazy", false);
606+ QCOMPARE(lvwph->m_minYExtent, 0.);
607+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
608+ QCOMPARE(lvwph->m_clipItem->clip(), false);
609+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
610+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
611+ QCOMPARE(lvwph->contentY(), 0.);
612+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
613+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
614+ }
615+
616+ void testSetEmptyHeaderAtTop()
617+ {
618+ lvwph->setHeader(nullptr);
619+
620+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
621+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
622+ verifyItem(0, 0., 190., false, "Agressive", false);
623+ verifyItem(1, 190., 240., false, "Regular", false);
624+ verifyItem(2, 430., 390., false, "Mild", false);
625+ QCOMPARE(lvwph->m_minYExtent, 0.);
626+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
627+ QCOMPARE(lvwph->m_clipItem->clip(), false);
628+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
629+ QCOMPARE(lvwph->contentY(), 0.);
630+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
631+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
632+ }
633+
634+ void testSetEmptyHeaderAtBottom()
635+ {
636+ scrollToBottom();
637+ lvwph->setHeader(nullptr);
638+
639+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
640+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
641+ verifyItem(0, -588., 390., true, "Bold", true);
642+ verifyItem(1, -198, 350., false, QString(), true);
643+ verifyItem(2, 152, 390., false, "Lazy", false);
644+ QCOMPARE(lvwph->m_minYExtent, 260.);
645+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
646+ QCOMPARE(lvwph->m_clipItem->clip(), false);
647+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
648+ QCOMPARE(lvwph->contentY(), 1458.);
649+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
650+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
651+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
652+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
653+
654+ scrollToTop();
655+
656+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
657+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
658+ verifyItem(0, 0., 190., false, "Agressive", false);
659+ verifyItem(1, 190., 240., false, "Regular", false);
660+ verifyItem(2, 430., 390., false, "Mild", false);
661+ QCOMPARE(lvwph->m_minYExtent, -50.);
662+ QCOMPARE(lvwph->m_clipItem->y(), 50.);
663+ QCOMPARE(lvwph->m_clipItem->clip(), false);
664+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
665+ QCOMPARE(lvwph->contentY(), 50.);
666+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
667+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
668+ }
669+
670+ void testSetEmptyHeaderWhenPartlyShownClipped()
671+ {
672+ scrollToBottom();
673+ changeContentY(-30);
674+ lvwph->setHeader(nullptr);
675+
676+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
677+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
678+ verifyItem(0, -588., 390., true, "Bold", true);
679+ verifyItem(1, -198, 350., false, QString(), true);
680+ verifyItem(2, 152, 390., false, "Lazy", false);
681+ QCOMPARE(lvwph->m_minYExtent, 290.);
682+ QCOMPARE(lvwph->m_clipItem->y(), 1428.);
683+ QCOMPARE(lvwph->m_clipItem->clip(), false);
684+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
685+ QCOMPARE(lvwph->contentY(), 1428.);
686+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
687+ QTRY_VERIFY(lvwph->isAtYEnd());
688+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
689+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
690+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
691+
692+ scrollToTop();
693+
694+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
695+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
696+ verifyItem(0, 0., 190., false, "Agressive", false);
697+ verifyItem(1, 190., 240., false, "Regular", false);
698+ verifyItem(2, 430., 390., false, "Mild", false);
699+ QCOMPARE(lvwph->m_minYExtent, -20.);
700+ QCOMPARE(lvwph->m_clipItem->y(), 20.);
701+ QCOMPARE(lvwph->m_clipItem->clip(), false);
702+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
703+ QCOMPARE(lvwph->contentY(), 20.);
704+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
705+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
706+ }
707+
708+ void testSetEmptyHeaderWhenPartlyShownNotClipped()
709+ {
710+ changeContentY(30);
711+ lvwph->setHeader(nullptr);
712+
713+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
714+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
715+ verifyItem(0, -30., 190., false, "Agressive", true);
716+ verifyItem(1, 160., 240., false, "Regular", false);
717+ verifyItem(2, 400., 390., false, "Mild", false);
718+ QCOMPARE(lvwph->m_minYExtent, 0.);
719+ QCOMPARE(lvwph->m_clipItem->y(), 30.);
720+ QCOMPARE(lvwph->m_clipItem->clip(), false);
721+ QCOMPARE(lvwph->m_headerItem, (QQuickItem*)nullptr);
722+ QCOMPARE(lvwph->contentY(), 30.);
723+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
724+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
725+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
726+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
727+ }
728+
729+ void testSetNullDelegate()
730+ {
731+ lvwph->setDelegate(nullptr);
732+
733+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 0);
734+ QCOMPARE(lvwph->m_firstVisibleIndex, -1);
735+ QCOMPARE(lvwph->m_minYExtent, 0.);
736+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
737+ QCOMPARE(lvwph->m_clipItem->clip(), false);
738+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
739+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
740+ QCOMPARE(lvwph->contentY(), 0.);
741+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
742+ QTRY_COMPARE(lvwph->contentHeight(), 50.);
743+ QVERIFY(lvwph->isAtYBeginning());
744+ QVERIFY(lvwph->isAtYEnd());
745+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
746+ }
747+
748+ void testInsertItems()
749+ {
750+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
751+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125), Q_ARG(QVariant, "Regular"));
752+
753+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
754+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
755+ verifyItem(0, 50., 190., false, "Agressive", false);
756+ verifyItem(1, 240., 165., false, "Regular", false);
757+ verifyItem(2, 405., 140., false, "Agressive", false);
758+ verifyItem(3, 545., 240., true, "Regular", true);
759+ verifyItem(4, 785., 390., true, "Mild", true);
760+ QCOMPARE(lvwph->m_minYExtent, 0.);
761+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
762+ QCOMPARE(lvwph->m_clipItem->clip(), false);
763+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
764+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
765+ QCOMPARE(lvwph->contentY(), 0.);
766+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
767+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
768+ }
769+
770+ void testInsertItemsStealSectionItem()
771+ {
772+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125), Q_ARG(QVariant, "Regular"));
773+
774+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
775+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
776+ verifyItem(0, 50., 190., false, "Agressive", false);
777+ verifyItem(1, 240., 165., false, "Regular", false);
778+ verifyItem(2, 405., 200., false, QString(), true);
779+ verifyItem(3, 605., 390., true, "Mild", true);
780+ QCOMPARE(lvwph->m_minYExtent, 0.);
781+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
782+ QCOMPARE(lvwph->m_clipItem->clip(), false);
783+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
784+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
785+ QCOMPARE(lvwph->contentY(), 0.);
786+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
787+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
788+ }
789+
790+
791+ void testInsertItemsOnNotShownPosition()
792+ {
793+ changeContentY(800);
794+
795+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
796+ QTRY_COMPARE(lvwph->m_firstVisibleIndex, 2);
797+ verifyItem(0, -320., 390., false, "Mild", true);
798+ verifyItem(1, 70, 390., false, "Bold", false);
799+ verifyItem(2, 460, 350., false, QString(), false);
800+ verifyItem(3, 810, 390., true, "Lazy", true);
801+ QCOMPARE(lvwph->m_minYExtent, 330.);
802+ QCOMPARE(lvwph->m_clipItem->y(), 800.);
803+ QCOMPARE(lvwph->m_clipItem->clip(), false);
804+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
805+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
806+ QCOMPARE(lvwph->contentY(), 800.);
807+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
808+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
809+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
810+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
811+
812+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
813+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125), Q_ARG(QVariant, "Regular"));
814+
815+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
816+ QCOMPARE(lvwph->m_firstVisibleIndex, 4);
817+ verifyItem(0, -320., 390., false, "Mild", true);
818+ verifyItem(1, 70, 390., false, "Bold", false);
819+ verifyItem(2, 460, 350., false, QString(), false);
820+ verifyItem(3, 810, 390., true, "Lazy", true);
821+ QCOMPARE(lvwph->m_minYExtent, 1090.);
822+ QCOMPARE(lvwph->m_clipItem->y(), 800.);
823+ QCOMPARE(lvwph->m_clipItem->clip(), false);
824+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
825+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
826+ QCOMPARE(lvwph->contentY(), 800.);
827+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
828+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
829+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
830+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
831+
832+ scrollToTop();
833+
834+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
835+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
836+ verifyItem(0, 50., 190., false, "Agressive", false);
837+ verifyItem(1, 240., 165., false, "Regular", false);
838+ verifyItem(2, 405., 140., false, "Agressive", false);
839+ verifyItem(3, 545., 240., true, "Regular", true);
840+ verifyItem(4, 785., 390., true, "Mild", true);
841+ QCOMPARE(lvwph->m_minYExtent, 305.);
842+ QCOMPARE(lvwph->m_clipItem->y(), -305.);
843+ QCOMPARE(lvwph->m_clipItem->clip(), false);
844+ QCOMPARE(lvwph->m_headerItem->y(), -305.);
845+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
846+ QCOMPARE(lvwph->contentY(), -305.);
847+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
848+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
849+ }
850+
851+ void testInsertItemsAtEndOfViewport()
852+ {
853+ changeContentY(60);
854+
855+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
856+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
857+ verifyItem(0, -10., 190., false, "Agressive", true);
858+ verifyItem(1, 180., 240., false, "Regular", false);
859+ verifyItem(2, 420., 390., false, "Mild", false);
860+ verifyItem(3, 810., 390., true, "Bold", true);
861+ QCOMPARE(lvwph->m_minYExtent, 0.);
862+ QCOMPARE(lvwph->m_clipItem->y(), 60.);
863+ QCOMPARE(lvwph->m_clipItem->clip(), false);
864+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
865+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
866+ QCOMPARE(lvwph->contentY(), 60.);
867+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
868+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
869+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
870+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
871+
872+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 3), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
873+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 3), Q_ARG(QVariant, 125), Q_ARG(QVariant, "Regular"));
874+
875+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
876+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
877+ verifyItem(0, -10., 190., false, "Agressive", true);
878+ verifyItem(1, 180., 240., false, "Regular", false);
879+ verifyItem(2, 420., 390., false, "Mild", false);
880+ verifyItem(3, 810., 165., true, "Regular", true);
881+ QCOMPARE(lvwph->m_minYExtent, 0.);
882+ QCOMPARE(lvwph->m_clipItem->y(), 60.);
883+ QCOMPARE(lvwph->m_clipItem->clip(), false);
884+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
885+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
886+ QCOMPARE(lvwph->contentY(), 60.);
887+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
888+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
889+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
890+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
891+ }
892+
893+ void testInsertItemsBeforeValidIndex()
894+ {
895+ changeContentY(520);
896+
897+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
898+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
899+ verifyItem(0, -280., 240., true, "Regular", true);
900+ verifyItem(1, -40, 390., false, "Mild", true);
901+ verifyItem(2, 350, 390., false, "Bold", false);
902+ verifyItem(3, 740, 350., true, QString(), true);
903+ QCOMPARE(lvwph->m_minYExtent, 152.5);
904+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
905+ QCOMPARE(lvwph->m_clipItem->clip(), false);
906+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
907+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
908+ QCOMPARE(lvwph->contentY(), 520.);
909+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
910+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
911+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
912+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
913+
914+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
915+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125), Q_ARG(QVariant, "Regular"));
916+
917+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
918+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
919+ verifyItem(0, -280., 240., true, "Regular", true);
920+ verifyItem(1, -40, 390., false, "Mild", true);
921+ verifyItem(2, 350, 390., false, "Bold", false);
922+ verifyItem(3, 740, 350., true, QString(), true);
923+ QCOMPARE(lvwph->m_minYExtent, 837.5);
924+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
925+ QCOMPARE(lvwph->m_clipItem->clip(), false);
926+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
927+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
928+ QCOMPARE(lvwph->contentY(), 520.);
929+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
930+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
931+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
932+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
933+ }
934+
935+ void testInsertItemsBeforeViewport()
936+ {
937+ changeContentY(375);
938+
939+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
940+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
941+ verifyItem(0, -325., 190., true, "Agressive", true);
942+ verifyItem(1, -135, 240., false, "Regular", true);
943+ verifyItem(2, 105, 390., false, "Mild", false);
944+ verifyItem(3, 495, 390., false, "Bold", false);
945+ QCOMPARE(lvwph->m_minYExtent, 0.);
946+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
947+ QCOMPARE(lvwph->m_clipItem->clip(), false);
948+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
949+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
950+ QCOMPARE(lvwph->contentY(), 375.);
951+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
952+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
953+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
954+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
955+
956+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
957+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125), Q_ARG(QVariant, "Regular"));
958+
959+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
960+ QCOMPARE(lvwph->m_firstVisibleIndex, 2);
961+ verifyItem(0, -275., 140., true, "Agressive", true);
962+ verifyItem(1, -135., 240., false, "Regular", true);
963+ verifyItem(2, 105, 390., false, "Mild", false);
964+ verifyItem(3, 495, 390., false, "Bold", false);
965+ QCOMPARE(lvwph->m_minYExtent, 530.);
966+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
967+ QCOMPARE(lvwph->m_clipItem->clip(), false);
968+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
969+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
970+ QCOMPARE(lvwph->contentY(), 375.);
971+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
972+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
973+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
974+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
975+
976+ scrollToTop();
977+
978+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
979+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
980+ verifyItem(0, 50., 190., false, "Agressive", false);
981+ verifyItem(1, 240., 165., false, "Regular", false);
982+ verifyItem(2, 405., 140., false, "Agressive", false);
983+ verifyItem(3, 545., 240., true, "Regular", true);
984+ verifyItem(4, 785., 390., true, "Mild", true);
985+ QCOMPARE(lvwph->m_minYExtent, 305.);
986+ QCOMPARE(lvwph->m_clipItem->y(), -305.);
987+ QCOMPARE(lvwph->m_clipItem->clip(), false);
988+ QCOMPARE(lvwph->m_headerItem->y(), -305.);
989+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
990+ QCOMPARE(lvwph->contentY(), -305.);
991+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
992+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
993+ }
994+
995+ void testInsertItemsAtBottom()
996+ {
997+ scrollToBottom();
998+
999+ QVERIFY(lvwph->isAtYEnd());
1000+
1001+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
1002+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 125), Q_ARG(QVariant, "Regular"));
1003+
1004+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1005+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
1006+ verifyItem(0, -588., 390., true, "Bold", true);
1007+ verifyItem(1, -198, 350., false, QString(), true);
1008+ verifyItem(2, 152, 390., false, "Lazy", false);
1009+ verifyItem(3, 542, 165., true, "Regular", true);
1010+ verifyItem(4, 707, 140., true, "Agressive", true);
1011+ QCOMPARE(lvwph->m_minYExtent, 41.);
1012+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
1013+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1014+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1015+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1016+ QCOMPARE(lvwph->contentY(), 1458.);
1017+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1018+ QVERIFY(!lvwph->isAtYEnd());
1019+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1020+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1021+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1022+
1023+ scrollToBottom();
1024+
1025+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1026+ QCOMPARE(lvwph->m_firstVisibleIndex, 4);
1027+ verifyItem(0, -503., 350., true, QString(), true);
1028+ verifyItem(1, -153, 390., false, "Lazy", true);
1029+ verifyItem(2, 237, 165., false, "Regular", false);
1030+ verifyItem(3, 402, 140., false, "Agressive", false);
1031+ QCOMPARE(lvwph->m_minYExtent, -165.);
1032+ QCOMPARE(lvwph->m_clipItem->y(), 1763.);
1033+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1034+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1035+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1036+ QCOMPARE(lvwph->contentY(), 1763.);
1037+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1038+ QVERIFY(lvwph->isAtYEnd());
1039+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1040+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Lazy"));
1041+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1042+ }
1043+
1044+ void testInsertItemAtTop()
1045+ {
1046+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Agressive"));
1047+
1048+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1049+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1050+ verifyItem(0, 50., 115., false, "Agressive", false);
1051+ verifyItem(1, 165., 150., false, QString(), false);
1052+ verifyItem(2, 315., 240., false, "Regular", false);
1053+ verifyItem(3, 555., 390., true, "Mild", true);
1054+ QCOMPARE(lvwph->m_minYExtent, 0.);
1055+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1056+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1057+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1058+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1059+ QCOMPARE(lvwph->contentY(), 0.);
1060+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1061+ QVERIFY(lvwph->isAtYBeginning());
1062+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1063+ }
1064+
1065+ void testInsertItem10SmallItemsAtTopWhenAtBottom()
1066+ {
1067+ scrollToBottom();
1068+
1069+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Agressive"));
1070+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Agressive"));
1071+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Agressive"));
1072+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Regular"));
1073+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Regular"));
1074+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Regular"));
1075+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Agressive"));
1076+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Agressive"));
1077+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Regular"));
1078+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 75), Q_ARG(QVariant, "Agressive"));
1079+
1080+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1081+ QCOMPARE(lvwph->m_firstVisibleIndex, 13);
1082+ verifyItem(0, -588., 390., true, "Bold", true);
1083+ verifyItem(1, -198, 350., false, QString(), true);
1084+ verifyItem(2, 152, 390., false, "Lazy", false);
1085+ QCOMPARE(lvwph->m_minYExtent, 12230./3.);
1086+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
1087+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1088+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1089+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1090+ QCOMPARE(lvwph->contentY(), 1458.);
1091+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1092+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1093+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1094+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1095+
1096+ changeContentY(-1700);
1097+
1098+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 10);
1099+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
1100+ verifyItem(0, -323., 75., true, QString(), true);
1101+ verifyItem(1, -248., 115., true, "Regular", true);
1102+ verifyItem(2, -133., 75., true, QString(), true);
1103+ verifyItem(3, -58., 75., false, QString(), true);
1104+ verifyItem(4, 17., 115., false, "Agressive", false);
1105+ verifyItem(5, 132., 75., false, QString(), true);
1106+ verifyItem(6, 207., 75., false, QString(), true);
1107+ verifyItem(7, 282., 150., false, QString(), true);
1108+ verifyItem(8, 432., 240., false, "Regular", false);
1109+ QCOMPARE(lvwph->m_minYExtent, 980.5);
1110+ QCOMPARE(lvwph->m_clipItem->y(), -192.);
1111+ QCOMPARE(lvwph->m_clipItem->clip(), true);
1112+ QCOMPARE(lvwph->m_headerItem->y(), -242.);
1113+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1114+ QCOMPARE(lvwph->contentY(), -242.);
1115+ QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1116+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1117+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1118+ QCOMPARE(lvwph->m_topSectionItem->y(), -23.);
1119+ }
1120+
1121+ void testRemoveItemsAtTop()
1122+ {
1123+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 2));
1124+
1125+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 2);
1126+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1127+ verifyItem(0, 50., 390., false, "Mild", false);
1128+ verifyItem(1, 440., 390., false, "Bold", false);
1129+ QCOMPARE(lvwph->m_minYExtent, 0.);
1130+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1131+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1132+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1133+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1134+ QCOMPARE(lvwph->contentY(), 0.);
1135+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1136+ QVERIFY(lvwph->isAtYBeginning());
1137+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1138+ }
1139+
1140+ void testRemoveNonCreatedItemsAtTopWhenAtBottom()
1141+ {
1142+ scrollToBottom();
1143+
1144+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 2));
1145+
1146+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1147+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1148+ verifyItem(0, -588., 390., true, "Bold", true);
1149+ verifyItem(1, -198, 350., false, QString(), true);
1150+ verifyItem(2, 152, 390., false, "Lazy", false);
1151+ QCOMPARE(lvwph->m_minYExtent, -1330./3.);
1152+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
1153+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1154+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1155+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1156+ QCOMPARE(lvwph->contentY(), 1458.);
1157+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1158+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1159+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1160+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1161+ }
1162+
1163+ void testRemoveLastItemsAtBottom()
1164+ {
1165+ scrollToBottom();
1166+
1167+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 4), Q_ARG(QVariant, 2));
1168+
1169+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1170+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1171+ verifyItem(0, -478., 240., true, "Regular", true);
1172+ verifyItem(1, -238, 390., false, "Mild", true);
1173+ verifyItem(2, 152, 390., false, "Bold", false);
1174+ QCOMPARE(lvwph->m_minYExtent, 150.);
1175+ QCOMPARE(lvwph->m_clipItem->y(), 718.);
1176+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1177+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1178+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1179+ QCOMPARE(lvwph->contentY(), 718.);
1180+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1181+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1182+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1183+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1184+ }
1185+
1186+ void testRemoveItemOutOfViewport()
1187+ {
1188+ changeContentY(520);
1189+
1190+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1191+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1192+ verifyItem(0, -280., 240., true, "Regular", true);
1193+ verifyItem(1, -40, 390., false, "Mild", true);
1194+ verifyItem(2, 350, 390., false, "Bold", false);
1195+ verifyItem(3, 740, 350., true, QString(), true);
1196+ QCOMPARE(lvwph->m_minYExtent, 152.5);
1197+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
1198+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1199+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1200+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1201+ QCOMPARE(lvwph->contentY(), 520.);
1202+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1203+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1204+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1205+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1206+
1207+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 1), Q_ARG(QVariant, 1));
1208+
1209+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1210+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1211+ verifyItem(0, -230., 190., true, "Agressive", true);
1212+ verifyItem(1, -40, 390., false, "Mild", true);
1213+ verifyItem(2, 350, 390., false, "Bold", false);
1214+ verifyItem(3, 740, 350., true, QString(), true);
1215+ QCOMPARE(lvwph->m_minYExtent, -240.);
1216+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
1217+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1218+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1219+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1220+ QCOMPARE(lvwph->contentY(), 520.);
1221+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1222+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1223+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1224+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1225+ }
1226+
1227+ void testRemoveFirstOfCategory()
1228+ {
1229+ changeContentY(520);
1230+
1231+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1232+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1233+ verifyItem(0, -280., 240., true, "Regular", true);
1234+ verifyItem(1, -40, 390., false, "Mild", true);
1235+ verifyItem(2, 350, 390., false, "Bold", false);
1236+ verifyItem(3, 740, 350., true, QString(), true);
1237+ QCOMPARE(lvwph->m_minYExtent, 152.5);
1238+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
1239+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1240+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1241+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1242+ QCOMPARE(lvwph->contentY(), 520.);
1243+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1244+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1245+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1246+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1247+
1248+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 3), Q_ARG(QVariant, 1));
1249+
1250+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1251+ QCOMPARE(lvwph->m_firstVisibleIndex, 1);
1252+ verifyItem(0, -280., 240., true, "Regular", true);
1253+ verifyItem(1, -40, 390., false, "Mild", true);
1254+ verifyItem(2, 350, 390., false, "Bold", false);
1255+ verifyItem(3, 740, 390., true, "Lazy", true);
1256+ QCOMPARE(lvwph->m_minYExtent, 162.5);
1257+ QCOMPARE(lvwph->m_clipItem->y(), 520.);
1258+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1259+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1260+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1261+ QCOMPARE(lvwph->contentY(), 520.);
1262+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1263+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1264+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1265+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1266+ }
1267+
1268+ void testAddSecondToCulledCategoryOfTwo()
1269+ {
1270+ // Do some setup
1271+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 25), Q_ARG(QVariant, "Agressive"));
1272+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 25), Q_ARG(QVariant, "Agressive"));
1273+
1274+ changeContentY(200);
1275+
1276+ // Very the items are culled
1277+ verifyItem(0, -150., 65., true, "Agressive", true);
1278+ verifyItem(1, -85, 25., true, QString(), true);
1279+
1280+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 25), Q_ARG(QVariant, "Agressive"));
1281+
1282+ // Very the new item is there correctly
1283+ verifyItem(0, -175., 65., true, "Agressive", true);
1284+ verifyItem(1, -110, 25., true, QString(), true);
1285+ verifyItem(2, -85, 25., true, QString(), true);
1286+ }
1287+
1288+ void testMoveFirstItems()
1289+ {
1290+ QMetaObject::invokeMethod(model, "moveItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 1), Q_ARG(QVariant, 1));
1291+
1292+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1293+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1294+ verifyItem(0, 50., 240., false, "Regular", false);
1295+ verifyItem(1, 290., 190., false, "Agressive", false);
1296+ verifyItem(2, 480., 390., false, "Mild", false);
1297+ QCOMPARE(lvwph->m_minYExtent, 0.);
1298+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1299+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1300+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1301+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1302+ QCOMPARE(lvwph->contentY(), 0.);
1303+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1304+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1305+ }
1306+
1307+ void testMoveFirstOutOfVisibleItems()
1308+ {
1309+ QMetaObject::invokeMethod(model, "moveItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 4), Q_ARG(QVariant, 1));
1310+
1311+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1312+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1313+ verifyItem(0, 50., 240., false, "Regular", false);
1314+ verifyItem(1, 290., 390., false, "Mild", false);
1315+ verifyItem(2, 680., 390., true, "Bold", true);
1316+ QCOMPARE(lvwph->m_minYExtent, 0.);
1317+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1318+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1319+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1320+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1321+ QCOMPARE(lvwph->contentY(), 0.);
1322+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1323+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1324+ }
1325+
1326+ void testMoveFirstToLastAtBottom()
1327+ {
1328+ scrollToBottom();
1329+
1330+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1331+ QCOMPARE(lvwph->m_firstVisibleIndex, 3);
1332+ verifyItem(0, -588., 390., true, "Bold", true);
1333+ verifyItem(1, -198, 350., false, QString(), true);
1334+ verifyItem(2, 152, 390., false, "Lazy", false);
1335+ QCOMPARE(lvwph->m_minYExtent, 310.);
1336+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
1337+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1338+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1339+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1340+ QCOMPARE(lvwph->contentY(), 1458.);
1341+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1342+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1343+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1344+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1345+
1346+ QMetaObject::invokeMethod(model, "moveItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 5), Q_ARG(QVariant, 1));
1347+
1348+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1349+ QCOMPARE(lvwph->m_firstVisibleIndex, 2);
1350+ verifyItem(0, -588., 390., true, "Bold", true);
1351+ verifyItem(1, -198, 350., false, QString(), true);
1352+ verifyItem(2, 152, 390., false, "Lazy", false);
1353+ verifyItem(3, 542, 190., true, "Agressive", true);
1354+ QCOMPARE(lvwph->m_minYExtent, -160.);
1355+ QCOMPARE(lvwph->m_clipItem->y(), 1458.);
1356+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1357+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1358+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1359+ QCOMPARE(lvwph->contentY(), 1458.);
1360+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1361+ QVERIFY(!lvwph->isAtYEnd());
1362+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1363+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Bold"));
1364+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1365+ }
1366+
1367+ void testChangeSizeVisibleItemNotOnViewport()
1368+ {
1369+ changeContentY(490);
1370+
1371+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1372+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1373+ verifyItem(0, -440., 190., true, "Agressive", true);
1374+ verifyItem(1, -250., 240., true, "Regular", true);
1375+ verifyItem(2, -10, 390., false, "Mild", true);
1376+ verifyItem(3, 380, 390., false, "Bold", false);
1377+ verifyItem(4, 770, 350., true, QString(), true);
1378+ QCOMPARE(lvwph->m_minYExtent, 0.);
1379+ QCOMPARE(lvwph->m_clipItem->y(), 490.);
1380+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1381+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1382+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1383+ QCOMPARE(lvwph->contentY(), 490.);
1384+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1385+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1386+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1387+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1388+
1389+ model->setProperty(1, "size", 100);
1390+
1391+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1392+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1393+ verifyItem(0, -340., 190., true, "Agressive", true);
1394+ verifyItem(1, -150., 140., true, "Regular", true);
1395+ verifyItem(2, -10, 390., false, "Mild", true);
1396+ verifyItem(3, 380, 390., false, "Bold", false);
1397+ verifyItem(4, 770, 350., true, QString(), true);
1398+ QCOMPARE(lvwph->m_minYExtent, -100.);
1399+ QCOMPARE(lvwph->m_clipItem->y(), 490.);
1400+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1401+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1402+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1403+ QCOMPARE(lvwph->contentY(), 490.);
1404+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1405+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1406+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Mild"));
1407+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1408+ }
1409+
1410+ void testShowHeaderCloseToTheTop()
1411+ {
1412+ changeContentY(375);
1413+
1414+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1415+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1416+ verifyItem(0, -325., 190., true, "Agressive", true);
1417+ verifyItem(1, -135, 240., false, "Regular", true);
1418+ verifyItem(2, 105, 390., false, "Mild", false);
1419+ verifyItem(3, 495, 390., false, "Bold", false);
1420+ QCOMPARE(lvwph->m_minYExtent, 0.);
1421+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
1422+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1423+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1424+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1425+ QCOMPARE(lvwph->contentY(), 375.);
1426+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);;
1427+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1428+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1429+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1430+
1431+ lvwph->showHeader();
1432+
1433+ QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1434+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1435+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1436+ verifyItem(0, -375., 190., true, "Agressive", true);
1437+ verifyItem(1, -185, 240., false, "Regular", true);
1438+ verifyItem(2, 55, 390., false, "Mild", false);
1439+ verifyItem(3, 445, 390., false, "Bold", false);
1440+ QCOMPARE(lvwph->m_minYExtent, 50.);
1441+ QCOMPARE(lvwph->m_clipItem->y(), 375.);
1442+ QCOMPARE(lvwph->m_clipItem->clip(), true);
1443+ QCOMPARE(lvwph->m_headerItem->y(), 325.);
1444+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1445+ QCOMPARE(lvwph->contentY(), 325.);
1446+ QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1447+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1448+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Regular"));
1449+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1450+
1451+ scrollToTop();
1452+
1453+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1454+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1455+ verifyItem(0, 50., 190., false, "Agressive", false);
1456+ verifyItem(1, 240., 240., false, "Regular", false);
1457+ verifyItem(2, 480., 390., false, "Mild", false);
1458+ QCOMPARE(lvwph->m_minYExtent, 50.);
1459+ QCOMPARE(lvwph->m_clipItem->y(), -50.);
1460+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1461+ QCOMPARE(lvwph->m_headerItem->y(), -50.);
1462+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1463+ QCOMPARE(lvwph->contentY(), -50.);
1464+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1465+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1466+ }
1467+
1468+ void testShowHeaderAtBottom()
1469+ {
1470+ scrollToBottom();
1471+
1472+ lvwph->showHeader();
1473+
1474+ QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1475+ QTRY_VERIFY (lvwph->isAtYEnd());
1476+ }
1477+
1478+ void growWindow()
1479+ {
1480+ view->rootObject()->setHeight(850);
1481+
1482+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1483+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1484+ verifyItem(0, 50., 190., false, "Agressive", false);
1485+ verifyItem(1, 240., 240., false, "Regular", false);
1486+ verifyItem(2, 480., 390., false, "Mild", false);
1487+ verifyItem(3, 870., 390., true, "Bold", true);
1488+ verifyItem(4, 1260., 350., true, QString(), true);
1489+ QCOMPARE(lvwph->m_minYExtent, 0.);
1490+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1491+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1492+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1493+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1494+ QCOMPARE(lvwph->contentY(), 0.);
1495+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1496+ }
1497+
1498+ void growWindowAtBottom()
1499+ {
1500+ // Need a bunch small items at the bottom to trigger the problem
1501+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1502+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1503+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1504+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1505+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1506+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1507+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Regular"));
1508+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Regular"));
1509+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Regular"));
1510+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Regular"));
1511+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Regular"));
1512+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Regular"));
1513+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1514+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1515+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1516+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1517+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1518+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1519+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1520+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 6), Q_ARG(QVariant, 50), Q_ARG(QVariant, "Agressive"));
1521+
1522+ scrollToBottom();
1523+
1524+ view->rootObject()->setHeight(850);
1525+
1526+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 21);
1527+ QCOMPARE(lvwph->m_firstVisibleIndex, 5);
1528+ verifyItem(0, -660., 390., true, "Lazy", true);
1529+ verifyItem(1, -270., 90., true, "Agressive", true);
1530+ verifyItem(2, -180, 50., true, QString(), true);
1531+ verifyItem(3, -130, 50., true, QString(), true);
1532+ verifyItem(4, -80, 50., true, QString(), true);
1533+ verifyItem(5, -30, 50., false, QString(), true);
1534+ verifyItem(6, 20, 50., false, QString(), true);
1535+ verifyItem(7, 70, 50., false, QString(), true);
1536+ verifyItem(8, 120, 50., false, QString(), true);
1537+ verifyItem(9, 170, 90., false, "Regular", false);
1538+ verifyItem(10, 260, 50., false, QString(), true);
1539+ verifyItem(11, 310, 50., false, QString(), true);
1540+ verifyItem(12, 360, 50., false, QString(), true);
1541+ verifyItem(13, 410, 50., false, QString(), true);
1542+ verifyItem(14, 460, 50., false, QString(), true);
1543+ verifyItem(15, 510, 90., false, "Agressive", false);
1544+ verifyItem(16, 600, 50., false, QString(), true);
1545+ verifyItem(17, 650, 50., false, QString(), true);
1546+ verifyItem(18, 700, 50., false, QString(), true);
1547+ verifyItem(19, 750, 50., false, QString(), true);
1548+ verifyItem(20, 800, 50., false, QString(), true);
1549+ QCOMPARE(lvwph->m_minYExtent, 5 * 1510./21. + 660 - 1970 + 50);
1550+ QCOMPARE(lvwph->m_clipItem->y(), 1970.);
1551+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1552+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1553+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1554+ QCOMPARE(lvwph->contentY(), 1970.);
1555+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1556+ }
1557+
1558+private:
1559+ QQuickView *view;
1560+ ListViewWithPageHeader *lvwph;
1561+ QQuickListModel *model;
1562+ QQmlComponent *otherDelegate;
1563+};
1564+
1565+QTEST_MAIN(ListViewWithPageHeaderTestSection)
1566+
1567+#include "listviewwithpageheadertestsection.moc"
tests/plugins/ListViewWithPageHeader/test.qmlnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import ListViewWithPageHeader 0.1
19+
20+Rectangle {
21+ width: 300
22+ height: 542
23+ color: "lightblue"
24+
25+ ListModel {
26+ id: model
27+
28+ function insertItem(index, size) {
29+ insert(index, { size: size });
30+ }
31+
32+ function removeItems(index, count) {
33+ remove(index, count);
34+ }
35+
36+ function moveItems(indexFrom, indexTo, count) {
37+ move(indexFrom, indexTo, count);
38+ }
39+
40+ ListElement { size: 150 }
41+ ListElement { size: 200 }
42+ ListElement { size: 350 }
43+ ListElement { size: 350 }
44+ ListElement { size: 350 }
45+ ListElement { size: 350 }
46+ }
47+
48+ Component {
49+ id: otherRect
50+ Rectangle {
51+ height: 35
52+ width: parent.width
53+ color: index % 2 == 0 ? "yellow" : "purple"
54+ }
55+ }
56+
57+ ListViewWithPageHeader {
58+ id: listView
59+ width: parent.width
60+ anchors.top: parent.top
61+ anchors.bottom: parent.bottom
62+ model: model
63+ delegate: Rectangle {
64+ property bool timerDone: false
65+ width: parent.width - 20
66+ x: 10
67+ color: index % 2 == 0 ? "red" : "blue"
68+ height: timerDone ? size : 350
69+ Text {
70+ text: index
71+ }
72+ Timer {
73+ id: sizeTimer
74+ interval: 10;
75+ onTriggered: {
76+ timerDone = true
77+ }
78+ }
79+ Component.onCompleted: {
80+ sizeTimer.start()
81+ }
82+ }
83+
84+ pageHeader: Rectangle {
85+ color: "transparent"
86+ width: parent.width
87+ height: 50
88+ implicitHeight: 50
89+ Text {
90+ anchors.fill: parent
91+ text: "APPS"
92+ font.pixelSize: 40
93+ }
94+ }
95+ }
96+}
tests/plugins/ListViewWithPageHeader/test_section.qmlnew file+106
@@ -0,0 +1,106 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import ListViewWithPageHeader 0.1
19+
20+Rectangle {
21+ width: 300
22+ height: 542
23+ color: "lightblue"
24+
25+ ListModel {
26+ id: model
27+
28+ function insertItem(index, size, type) {
29+ insert(index, { size: size, type: type });
30+ }
31+
32+ function removeItems(index, count) {
33+ remove(index, count);
34+ }
35+
36+ function moveItems(indexFrom, indexTo, count) {
37+ move(indexFrom, indexTo, count);
38+ }
39+
40+ ListElement { type: "Agressive"; size: 150 }
41+ ListElement { type: "Regular"; size: 200 }
42+ ListElement { type: "Mild"; size: 350 }
43+ ListElement { type: "Bold"; size: 350 }
44+ ListElement { type: "Bold"; size: 350 }
45+ ListElement { type: "Lazy"; size: 350 }
46+ }
47+
48+ Component {
49+ id: otherRect
50+ Rectangle {
51+ height: 35
52+ width: parent.width
53+ color: index % 2 == 0 ? "yellow" : "purple"
54+ }
55+ }
56+
57+ ListViewWithPageHeader {
58+ id: listView
59+ width: parent.width
60+ anchors.top: parent.top
61+ anchors.bottom: parent.bottom
62+ model: model
63+ delegate: Rectangle {
64+ property bool timerDone: false
65+ width: parent.width - 20
66+ x: 10
67+ color: index % 2 == 0 ? "red" : "blue"
68+ height: timerDone ? size : 350
69+ Text {
70+ text: index
71+ }
72+ Timer {
73+ id: sizeTimer
74+ interval: 10;
75+ onTriggered: {
76+ timerDone = true
77+ }
78+ }
79+ Component.onCompleted: {
80+ sizeTimer.start()
81+ }
82+ }
83+
84+ pageHeader: Rectangle {
85+ color: "transparent"
86+ width: parent.width
87+ height: 50
88+ implicitHeight: 50
89+ Text {
90+ anchors.fill: parent
91+ text: "APPS"
92+ font.pixelSize: 40
93+ }
94+ }
95+
96+ sectionProperty: "type"
97+ sectionDelegate: Component {
98+ Rectangle {
99+ color: "green"
100+ height: 40
101+ Text { text: section; font.pixelSize: 34 }
102+ anchors { left: parent.left; right: parent.right }
103+ }
104+ }
105+ }
106+}
tests/plugins/Ubuntu/Gestures/tst_AxisVelocityCalculator.cpp+40−28
@@ -20,7 +20,7 @@
2020
2121#include <AxisVelocityCalculator.h>
2222
23−class FakeTimeSource : public AxisVelocityCalculator::TimeSource {
23+class FakeTimeSource : public UbuntuGestures::TimeSource {
2424public:
2525 FakeTimeSource() : m_value(0) {}
2626
@@ -44,71 +44,85 @@ class tst_AxisVelocityCalculator : public QObject
4444{
4545 Q_OBJECT
4646private Q_SLOTS:
47+ void init(); // called right before each and every test function is executed
48+ void cleanup(); // called right after each and every test function is executed
49+
4750 void simpleSamples();
4851 void noSamples();
4952 void overflowSamples();
5053 void average();
54+
55+private:
56+ AxisVelocityCalculator *velCalc;
57+ FakeTimeSource *fakeTimeSource;
5158};
5259
60+void tst_AxisVelocityCalculator::init()
61+{
62+ fakeTimeSource = new FakeTimeSource;
63+
64+ velCalc = new AxisVelocityCalculator;
65+ velCalc->setTimeSource(fakeTimeSource);
66+}
67+
68+void tst_AxisVelocityCalculator::cleanup()
69+{
70+ delete velCalc;
71+ delete fakeTimeSource;
72+}
73+
5374void tst_AxisVelocityCalculator::simpleSamples()
5475{
55− FakeTimeSource *fakeTimeSource = new FakeTimeSource;
56− AxisVelocityCalculator velCalc(fakeTimeSource);
5776 qreal pos = 0;
5877
59− velCalc.setTrackedPosition(pos);
60− velCalc.reset();
78+ velCalc->setTrackedPosition(pos);
79+ velCalc->reset();
6180
6281 fakeTimeSource->setMsecsSinceReference(10);
6382 pos += 20;
64− velCalc.setTrackedPosition(pos);
83+ velCalc->setTrackedPosition(pos);
6584
6685 fakeTimeSource->setMsecsSinceReference(20);
6786 pos += 20;
68− velCalc.setTrackedPosition(pos);
87+ velCalc->setTrackedPosition(pos);
6988
7089 fakeTimeSource->setMsecsSinceReference(30);
7190 pos += 20;
72− velCalc.setTrackedPosition(pos);
91+ velCalc->setTrackedPosition(pos);
7392
74− qreal velocity = velCalc.calculate();
93+ qreal velocity = velCalc->calculate();
7594
7695 QCOMPARE(velocity, 2.0f);
7796}
7897
7998void tst_AxisVelocityCalculator::noSamples()
8099{
81− FakeTimeSource *fakeTimeSource = new FakeTimeSource;
82− AxisVelocityCalculator velCalc(fakeTimeSource);
83−
84− float velocity = velCalc.calculate();
100+ float velocity = velCalc->calculate();
85101
86102 QCOMPARE(velocity, 0.0f);
87103}
88104
89105void tst_AxisVelocityCalculator::overflowSamples()
90106{
91− FakeTimeSource *fakeTimeSource = new FakeTimeSource;
92− AxisVelocityCalculator velCalc(fakeTimeSource);
93107 qreal pos = 0;
94108
95− velCalc.setTrackedPosition(pos);
96− velCalc.reset();
109+ velCalc->setTrackedPosition(pos);
110+ velCalc->reset();
97111
98112 for (int i = 0; i < 1000; ++i) {
99113 fakeTimeSource->increaseMsecsSinceReference(10);
100114 pos += 20;
101− velCalc.setTrackedPosition(pos);
115+ velCalc->setTrackedPosition(pos);
102116 }
103117
104118 /* overwrite all existing samples with faster ones */
105119 for (int i = 0; i < AxisVelocityCalculator::MAX_SAMPLES; ++i) {
106120 fakeTimeSource->increaseMsecsSinceReference(10);
107121 pos += 40;
108− velCalc.setTrackedPosition(pos);
122+ velCalc->setTrackedPosition(pos);
109123 }
110124
111− float velocity = velCalc.calculate();
125+ float velocity = velCalc->calculate();
112126
113127 /* check that the calculated velocity correspond to the latest, faster, samples */
114128 QCOMPARE(velocity, 4.0f);
@@ -116,28 +130,26 @@ void tst_AxisVelocityCalculator::overflowSamples()
116130
117131void tst_AxisVelocityCalculator::average()
118132{
119− FakeTimeSource *fakeTimeSource = new FakeTimeSource;
120− AxisVelocityCalculator velCalc(fakeTimeSource);
121133 qreal pos = 0;
122134
123− velCalc.setTrackedPosition(pos);
124− velCalc.reset();
135+ velCalc->setTrackedPosition(pos);
136+ velCalc->reset();
125137
126138 fakeTimeSource->increaseMsecsSinceReference(10);
127139 pos += 20;
128− velCalc.setTrackedPosition(pos);
140+ velCalc->setTrackedPosition(pos);
129141
130142 fakeTimeSource->increaseMsecsSinceReference(10);
131143 pos += 20;
132− velCalc.setTrackedPosition(pos);
144+ velCalc->setTrackedPosition(pos);
133145
134146 /* the last sample is an erratic one and would yield a big velocity if
135147 considered isolatedly */
136148 fakeTimeSource->increaseMsecsSinceReference(10);
137149 pos += 100;
138− velCalc.setTrackedPosition(pos);
150+ velCalc->setTrackedPosition(pos);
139151
140− float velocity = velCalc.calculate();
152+ float velocity = velCalc->calculate();
141153
142154 /* calculated velocity is lower than the one from the last sample */
143155 QVERIFY(velocity < 9.0f);
tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp+99−11
@@ -38,7 +38,7 @@ private:
3838 int m_duration;
3939};
4040
41−class FakeTimeSource : public AxisVelocityCalculator::TimeSource
41+class FakeTimeSource : public UbuntuGestures::TimeSource
4242{
4343public:
4444 FakeTimeSource() { m_msecsSinceReference = 0; }
@@ -65,6 +65,9 @@ private Q_SLOTS:
6565 void minSpeed_data();
6666 void recognitionTimerUsage();
6767 void maxSilenceTime();
68+ void sceneXAndX();
69+ void sceneYAndY();
70+ void emitDraggingChangedOnDirectRecognition();
6871
6972private:
7073 QQuickView *createView();
@@ -72,7 +75,6 @@ private:
7275 QTouchDevice *device;
7376 FakeTimer *fakeTimer;
7477 FakeTimeSource *fakeTimeSource;
75− AxisVelocityCalculator *velCalcWithFakeTiming;
7678};
7779
7880void tst_DirectionalDragArea::initTestCase()
@@ -101,7 +103,6 @@ void tst_DirectionalDragArea::init()
101103
102104 fakeTimer = new FakeTimer;
103105 fakeTimeSource = new FakeTimeSource;
104− velCalcWithFakeTiming = new AxisVelocityCalculator(fakeTimeSource);
105106}
106107
107108void tst_DirectionalDragArea::cleanup()
@@ -112,10 +113,8 @@ void tst_DirectionalDragArea::cleanup()
112113 delete fakeTimer;
113114 fakeTimer = 0;
114115
115− // will bring fakeTimeSource down with it
116− delete velCalcWithFakeTiming;
116+ delete fakeTimeSource;
117117 fakeTimeSource = 0;
118− velCalcWithFakeTiming = 0;
119118}
120119
121120QQuickView *tst_DirectionalDragArea::createView()
@@ -187,7 +186,7 @@ void tst_DirectionalDragArea::edgeDrag()
187186 view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
188187 QVERIFY(edgeDragArea != 0);
189188 edgeDragArea->setRecognitionTimer(fakeTimer);
190− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
189+ edgeDragArea->setTimeSource(fakeTimeSource);
191190
192191 QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
193192
@@ -292,7 +291,7 @@ void tst_DirectionalDragArea::dragWithShortDirectionChange()
292291 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
293292 QVERIFY(edgeDragArea != 0);
294293 edgeDragArea->setRecognitionTimer(fakeTimer);
295− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
294+ edgeDragArea->setTimeSource(fakeTimeSource);
296295
297296 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
298297 QPointF touchPoint = initialTouchPos;
@@ -337,7 +336,7 @@ void tst_DirectionalDragArea::minSpeed()
337336 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
338337 QVERIFY(edgeDragArea != 0);
339338 edgeDragArea->setRecognitionTimer(fakeTimer);
340− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
339+ edgeDragArea->setTimeSource(fakeTimeSource);
341340
342341 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
343342 QPointF touchPoint = initialTouchPos;
@@ -390,7 +389,7 @@ void tst_DirectionalDragArea::recognitionTimerUsage()
390389 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
391390 QVERIFY(edgeDragArea != 0);
392391 edgeDragArea->setRecognitionTimer(fakeTimer);
393− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
392+ edgeDragArea->setTimeSource(fakeTimeSource);
394393
395394 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
396395 QPointF touchPoint = initialTouchPos;
@@ -431,7 +430,7 @@ void tst_DirectionalDragArea::maxSilenceTime()
431430 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
432431 QVERIFY(edgeDragArea != 0);
433432 edgeDragArea->setRecognitionTimer(fakeTimer);
434− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
433+ edgeDragArea->setTimeSource(fakeTimeSource);
435434
436435 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
437436 QPointF touchPoint = initialTouchPos;
@@ -458,6 +457,95 @@ void tst_DirectionalDragArea::maxSilenceTime()
458457 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Rejected);
459458}
460459
460+/*
461+ Checks that it informs the X coordinate of the touch point in local and scene coordinates
462+ correctly.
463+ */
464+void tst_DirectionalDragArea::sceneXAndX()
465+{
466+ DirectionalDragArea *edgeDragArea =
467+ view->rootObject()->findChild<DirectionalDragArea*>("hnDragArea");
468+ QVERIFY(edgeDragArea != 0);
469+ edgeDragArea->setRecognitionTimer(fakeTimer);
470+ edgeDragArea->setTimeSource(fakeTimeSource);
471+
472+ QPointF touchScenePos(view->width() - (edgeDragArea->width()/2.0f), view->height()/2.0f);
473+
474+ fakeTimeSource->m_msecsSinceReference = 0;
475+ QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
476+
477+ QSignalSpy touchXSpy(edgeDragArea, SIGNAL(touchXChanged(qreal)));
478+ QSignalSpy touchSceneXSpy(edgeDragArea, SIGNAL(touchSceneXChanged(qreal)));
479+
480+ touchScenePos.rx() = view->width() / 2;
481+ QTest::touchEvent(view, device).move(0, touchScenePos.toPoint());
482+
483+ QCOMPARE(touchXSpy.count(), 1);
484+ QCOMPARE(touchSceneXSpy.count(), 1);
485+ QCOMPARE(edgeDragArea->touchX(), touchScenePos.x() - edgeDragArea->x());
486+ QCOMPARE(edgeDragArea->touchSceneX(), touchScenePos.x());
487+}
488+
489+/*
490+ Checks that it informs the Y coordinate of the touch point in local and scene coordinates
491+ correctly.
492+ */
493+void tst_DirectionalDragArea::sceneYAndY()
494+{
495+ DirectionalDragArea *edgeDragArea =
496+ view->rootObject()->findChild<DirectionalDragArea*>("vnDragArea");
497+ QVERIFY(edgeDragArea != 0);
498+ edgeDragArea->setRecognitionTimer(fakeTimer);
499+ edgeDragArea->setTimeSource(fakeTimeSource);
500+
501+ QPointF touchScenePos(view->width()/2.0f, view->height() - (edgeDragArea->height()/2.0f));
502+
503+ fakeTimeSource->m_msecsSinceReference = 0;
504+ QTest::touchEvent(view, device).press(0, touchScenePos.toPoint());
505+
506+ QSignalSpy touchYSpy(edgeDragArea, SIGNAL(touchYChanged(qreal)));
507+ QSignalSpy touchSceneYSpy(edgeDragArea, SIGNAL(touchSceneYChanged(qreal)));
508+
509+ touchScenePos.ry() = view->height() / 2;
510+ QTest::touchEvent(view, device).move(0, touchScenePos.toPoint());
511+
512+ QCOMPARE(touchYSpy.count(), 1);
513+ QCOMPARE(touchSceneYSpy.count(), 1);
514+ QCOMPARE(edgeDragArea->touchY(), touchScenePos.y() - edgeDragArea->y());
515+ QCOMPARE(edgeDragArea->touchSceneY(), touchScenePos.y());
516+}
517+
518+/*
519+ Emit draggingChanged() when status change from WaitingForTouch directly to Recognized.
520+ This happens when the gesture recognition is effectively disabled (e.g. by setting a
521+ distanceThreshold of zero)
522+ */
523+void tst_DirectionalDragArea::emitDraggingChangedOnDirectRecognition()
524+{
525+ DirectionalDragArea *edgeDragArea =
526+ view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
527+ QVERIFY(edgeDragArea != 0);
528+ edgeDragArea->setRecognitionTimer(fakeTimer);
529+ edgeDragArea->setTimeSource(fakeTimeSource);
530+
531+ QPointF touchPos = calculateInitialTouchPos(edgeDragArea, view);
532+
533+ QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
534+
535+ // That will make it completetly skip the recognition phase ("Undecided" status).
536+ edgeDragArea->setDistanceThreshold(0.0);
537+
538+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::WaitingForTouch);
539+ QCOMPARE(edgeDragArea->dragging(), false);
540+
541+ fakeTimeSource->m_msecsSinceReference = 0;
542+ QTest::touchEvent(view, device).press(0, touchPos.toPoint());
543+
544+ QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Recognized);
545+ QCOMPARE(draggingSpy.count(), 1);
546+ QCOMPARE(edgeDragArea->dragging(), true);
547+}
548+
461549QTEST_MAIN(tst_DirectionalDragArea)
462550
463551#include "tst_DirectionalDragArea.moc"
tests/qmltests/CMakeLists.txt+2−1
@@ -2,6 +2,7 @@
22include(QmlTest)
33
44add_subdirectory(plugins)
5+add_subdirectory(Components)
56
67set(qmltest_DEFAULT_IMPORT_PATHS
78 ${CMAKE_CURRENT_BINARY_DIR}/plugins
@@ -25,9 +26,9 @@ add_qml_test(utils/Unity/Test UnityTest)
2526set(qmltest_DEFAULT_TARGETS qmluitests)
2627set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
2728set(qmltest_DEFAULT_PROPERTIES "")
29+add_manual_qml_test(Components DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
2830add_qml_test(Components DraggingArea)
2931add_qml_test(Components FilterGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
30−add_qml_test(Components ListViewWithPageHeader)
3132add_qml_test(Components ResponsiveFlowView)
3233add_qml_test(Components ResponsiveGridView)
3334add_qml_test(Components Revealer)
tests/qmltests/Components/CMakeLists.txtnew file+23
@@ -0,0 +1,23 @@
1+########## tst_DragHandle
2+
3+include_directories(
4+ ${CMAKE_SOURCE_DIR}/plugins/Ubuntu/Gestures
5+ ${CMAKE_CURRENT_BINARY_DIR}
6+ )
7+
8+set(testCommand
9+ LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures
10+ ${CMAKE_CURRENT_BINARY_DIR}/DragHandleTestExec
11+ -o ${CMAKE_BINARY_DIR}/DragHandleTest.xml,xunitxml
12+ -o -,txt)
13+
14+add_custom_target(testDragHandle ${testCommand})
15+add_dependencies(qmluitests testDragHandle)
16+add_dependencies(testDragHandle DragHandleTestExec)
17+
18+add_executable(DragHandleTestExec tst_DragHandle.cpp)
19+qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
20+target_link_libraries(DragHandleTestExec UbuntuGestureQml)
21+
22+add_definitions(-DUBUNTU_GESTURES_PLUGIN_DIR="${CMAKE_BINARY_DIR}/plugins")
23+add_definitions(-DTEST_DIR="${CMAKE_CURRENT_LIST_DIR}")
tests/qmltests/Components/tst_DragHandle.cppnew file+395
@@ -0,0 +1,395 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include <functional>
18+#include <QtTest/QtTest>
19+#include <QtCore/QObject>
20+#include <qpa/qwindowsysteminterface.h>
21+#include <QtQuick/QQuickView>
22+#include <QtQml/QQmlEngine>
23+
24+#include <DirectionalDragArea.h>
25+
26+class FakeTimer : public UbuntuGestures::AbstractTimer
27+{
28+ Q_OBJECT
29+public:
30+ FakeTimer(QObject *parent = 0)
31+ : UbuntuGestures::AbstractTimer(parent)
32+ {}
33+
34+ virtual int interval() const { return m_duration; }
35+ virtual void setInterval(int msecs) { m_duration = msecs; }
36+private:
37+ int m_duration;
38+};
39+
40+class FakeTimeSource : public UbuntuGestures::TimeSource
41+{
42+public:
43+ FakeTimeSource() { m_msecsSinceReference = 0; }
44+ virtual qint64 msecsSinceReference() {return m_msecsSinceReference;}
45+ qint64 m_msecsSinceReference;
46+};
47+
48+class tst_DragHandle: public QObject
49+{
50+ Q_OBJECT
51+public:
52+ tst_DragHandle() : m_device(0) { }
53+private Q_SLOTS:
54+ void initTestCase(); // will be called before the first test function is executed
55+ void cleanupTestCase(); // will be called after the last test function was executed.
56+
57+ void init(); // called right before each and every test function is executed
58+ void cleanup(); // called right after each and every test function is executed
59+
60+ void dragThreshold_horizontal();
61+ void dragThreshold_vertical();
62+ void stretch_horizontal();
63+ void stretch_vertical();
64+ void hintingAnimation();
65+
66+private:
67+ void flickAndHold(DirectionalDragArea *dragHandle, qreal distance);
68+ DirectionalDragArea *fetchAndSetupDragHandle(const char *objectName);
69+ qreal fetchDragThreshold(DirectionalDragArea *dragHandle);
70+ void tryCompare(std::function<qreal ()> actualFunc, qreal expectedValue);
71+
72+ QQuickView *createView();
73+ QQuickView *m_view;
74+ QTouchDevice *m_device;
75+ FakeTimer *m_fakeTimer;
76+ FakeTimeSource *m_fakeTimeSource;
77+};
78+
79+
80+void tst_DragHandle::initTestCase()
81+{
82+ if (!m_device) {
83+ m_device = new QTouchDevice;
84+ m_device->setType(QTouchDevice::TouchScreen);
85+ QWindowSystemInterface::registerTouchDevice(m_device);
86+ }
87+
88+ m_view = 0;
89+}
90+
91+void tst_DragHandle::cleanupTestCase()
92+{
93+}
94+
95+void tst_DragHandle::init()
96+{
97+ m_view = createView();
98+ m_view->setSource(QUrl::fromLocalFile(TEST_DIR"/tst_DragHandle.qml"));
99+ m_view->show();
100+ QVERIFY(QTest::qWaitForWindowExposed(m_view));
101+ QVERIFY(m_view->rootObject() != 0);
102+ qApp->processEvents();
103+
104+ m_fakeTimer = new FakeTimer;
105+ m_fakeTimeSource = new FakeTimeSource;
106+}
107+
108+void tst_DragHandle::cleanup()
109+{
110+ delete m_view;
111+ m_view = 0;
112+
113+ delete m_fakeTimer;
114+ m_fakeTimer = 0;
115+
116+ delete m_fakeTimeSource;
117+ m_fakeTimeSource = 0;
118+}
119+
120+QQuickView *tst_DragHandle::createView()
121+{
122+ QQuickView *window = new QQuickView(0);
123+ window->setResizeMode(QQuickView::SizeRootObjectToView);
124+ window->resize(600, 600);
125+ window->engine()->addImportPath(QLatin1String(UBUNTU_GESTURES_PLUGIN_DIR));
126+ window->engine()->addImportPath(QLatin1String(TEST_DIR));
127+
128+ return window;
129+}
130+
131+void tst_DragHandle::tryCompare(std::function<qreal ()> actualFunc,
132+ qreal expectedValue)
133+{
134+ int waitCount = 0;
135+ while (actualFunc() != expectedValue && waitCount < 100) {
136+ QTest::qWait(50);
137+ ++waitCount;
138+ }
139+ QCOMPARE(actualFunc(), expectedValue);
140+}
141+
142+namespace {
143+QPointF calculateDirectionVector(DirectionalDragArea *edgeDragArea)
144+{
145+
146+ switch (edgeDragArea->direction()) {
147+ case Direction::Upwards:
148+ return QPointF(0, -1);
149+ case Direction::Downwards:
150+ return QPointF(0, 1);
151+ case Direction::Leftwards:
152+ return QPointF(-1, 0);
153+ default: // Direction::Rightwards:
154+ return QPointF(1, 0);
155+ }
156+}
157+}
158+
159+void tst_DragHandle::flickAndHold(DirectionalDragArea *dragHandle,
160+ qreal distance)
161+{
162+ QPointF initialTouchPos = dragHandle->mapToScene(
163+ QPointF(dragHandle->width() / 2.0, dragHandle->height() / 2.0));
164+ QPointF touchPoint = initialTouchPos;
165+ int numSteps = 10;
166+ qint64 flickTimeMs = 500;
167+ qint64 timeStep = flickTimeMs / numSteps;
168+
169+ QPointF dragDirectionVector = calculateDirectionVector(dragHandle);
170+ QPointF touchMovement = dragDirectionVector * (distance / (qreal)numSteps);
171+
172+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
173+
174+ for (int i = 0; i < numSteps; ++i) {
175+ touchPoint += touchMovement;
176+ m_fakeTimeSource->m_msecsSinceReference += timeStep;
177+ QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
178+ }
179+
180+ // Wait for quite a bit before finally releasing to make a very low flick/release
181+ // speed.
182+ m_fakeTimeSource->m_msecsSinceReference += 5000;
183+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
184+}
185+
186+DirectionalDragArea *tst_DragHandle::fetchAndSetupDragHandle(const char *objectName)
187+{
188+ DirectionalDragArea *dragHandle =
189+ m_view->rootObject()->findChild<DirectionalDragArea*>(objectName);
190+ Q_ASSERT(dragHandle != 0);
191+ dragHandle->setRecognitionTimer(m_fakeTimer);
192+ dragHandle->setTimeSource(m_fakeTimeSource);
193+
194+ AxisVelocityCalculator *edgeDragEvaluator =
195+ dragHandle->findChild<AxisVelocityCalculator*>("edgeDragEvaluator");
196+ Q_ASSERT(edgeDragEvaluator != 0);
197+ edgeDragEvaluator->setTimeSource(m_fakeTimeSource);
198+
199+ return dragHandle;
200+}
201+
202+qreal tst_DragHandle::fetchDragThreshold(DirectionalDragArea *dragHandle)
203+{
204+ AxisVelocityCalculator *edgeDragEvaluator =
205+ dragHandle->findChild<AxisVelocityCalculator*>("edgeDragEvaluator");
206+ Q_ASSERT(edgeDragEvaluator != 0);
207+
208+ return edgeDragEvaluator->property("dragThreshold").toReal();
209+}
210+
211+/*
212+ Checks that ending a low-speed drag before dragThreshold results in the
213+ Showable getting back to its original position, whereas ending after dragThreshold
214+ results in Showable continuing until reaching its new states (shown or hidden)
215+ */
216+void tst_DragHandle::dragThreshold_horizontal()
217+{
218+ DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("rightwardsDragHandle");
219+
220+ qreal dragThreshold = fetchDragThreshold(dragHandle);
221+
222+ // end before the threshold
223+ flickAndHold(dragHandle, dragThreshold * 0.7);
224+
225+ // should rollback
226+ QQuickItem *parentItem = dragHandle->parentItem();
227+ tryCompare([&](){ return parentItem->x(); }, -parentItem->width());
228+ QCOMPARE(parentItem->property("shown").toBool(), false);
229+
230+ // end after the threshold
231+ flickAndHold(dragHandle, dragThreshold * 1.2);
232+
233+ // should keep going until completion
234+ tryCompare([&](){ return parentItem->x(); }, 0);
235+ QCOMPARE(parentItem->property("shown").toBool(), true);
236+
237+ dragHandle = fetchAndSetupDragHandle("leftwardsDragHandle");
238+
239+ dragThreshold = fetchDragThreshold(dragHandle);
240+
241+ // end before the threshold
242+ flickAndHold(dragHandle, dragThreshold * 0.7);
243+
244+ // should rollback
245+ tryCompare([&](){ return parentItem->x(); }, 0);
246+ QCOMPARE(parentItem->property("shown").toBool(), true);
247+
248+ // end after the threshold
249+ flickAndHold(dragHandle, dragThreshold * 1.2);
250+
251+ // should keep going until completion
252+ tryCompare([&](){ return parentItem->x(); }, -parentItem->width());
253+ QCOMPARE(parentItem->property("shown").toBool(), false);
254+}
255+
256+void tst_DragHandle::dragThreshold_vertical()
257+{
258+ DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
259+
260+ qreal dragThreshold = fetchDragThreshold(dragHandle);
261+
262+ // end before the threshold
263+ flickAndHold(dragHandle, dragThreshold * 0.7);
264+
265+ // should rollback
266+ QQuickItem *parentItem = dragHandle->parentItem();
267+ tryCompare([&](){ return parentItem->y(); }, -parentItem->height());
268+ QCOMPARE(parentItem->property("shown").toBool(), false);
269+
270+ // end after the threshold
271+ flickAndHold(dragHandle, dragThreshold * 1.2);
272+
273+ // should keep going until completion
274+ tryCompare([&](){ return parentItem->y(); }, 0);
275+ QCOMPARE(parentItem->property("shown").toBool(), true);
276+
277+ dragHandle = fetchAndSetupDragHandle("upwardsDragHandle");
278+
279+ dragThreshold = fetchDragThreshold(dragHandle);
280+
281+ // end before the threshold
282+ flickAndHold(dragHandle, dragThreshold * 0.7);
283+
284+ // should rollback
285+ tryCompare([&](){ return parentItem->y(); }, 0);
286+ QCOMPARE(parentItem->property("shown").toBool(), true);
287+
288+ // end after the threshold
289+ flickAndHold(dragHandle, dragThreshold * 1.2);
290+
291+ // should keep going until completion
292+ tryCompare([&](){ return parentItem->y(); }, -parentItem->height());
293+ QCOMPARE(parentItem->property("shown").toBool(), false);
294+}
295+
296+/*
297+ Checks that when the stretch property is true, dragging the DragHandle increases
298+ the width or height (depending on its direction) of its parent Showable
299+ */
300+void tst_DragHandle::stretch_horizontal()
301+{
302+ DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("rightwardsDragHandle");
303+ qreal totalDragDistance = dragHandle->property("maxTotalDragDistance").toReal();
304+ QQuickItem *parentItem = dragHandle->parentItem();
305+
306+ // enable strech mode
307+ m_view->rootObject()->setProperty("stretch", QVariant(true));
308+
309+ QCOMPARE(parentItem->width(), 0.0);
310+
311+ // flick all the way
312+ flickAndHold(dragHandle, totalDragDistance);
313+
314+ // should keep going until completion
315+ // Parent item should now have its full height
316+ tryCompare([&](){ return parentItem->width(); }, totalDragDistance);
317+ QCOMPARE(parentItem->property("shown").toBool(), true);
318+
319+ dragHandle = fetchAndSetupDragHandle("leftwardsDragHandle");
320+
321+ // flick all the way
322+ flickAndHold(dragHandle, totalDragDistance);
323+
324+ // should keep going until completion
325+ // Parent item should now have its full height
326+ tryCompare([&](){ return parentItem->width(); }, 0.0);
327+ QCOMPARE(parentItem->property("shown").toBool(), false);
328+}
329+
330+void tst_DragHandle::stretch_vertical()
331+{
332+ DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
333+ qreal totalDragDistance = dragHandle->property("maxTotalDragDistance").toReal();
334+ QQuickItem *parentItem = dragHandle->parentItem();
335+
336+ // enable strech mode
337+ m_view->rootObject()->setProperty("stretch", QVariant(true));
338+
339+ QCOMPARE(parentItem->height(), 0.0);
340+
341+ // flick all the way
342+ flickAndHold(dragHandle, totalDragDistance);
343+
344+ // should keep going until completion
345+ // Parent item should now have its full height
346+ tryCompare([&](){ return parentItem->height(); }, totalDragDistance);
347+ QCOMPARE(parentItem->property("shown").toBool(), true);
348+
349+ dragHandle = fetchAndSetupDragHandle("upwardsDragHandle");
350+
351+ // flick all the way
352+ flickAndHold(dragHandle, totalDragDistance);
353+
354+ // should keep going until completion
355+ // Parent item should now have its full height
356+ tryCompare([&](){ return parentItem->height(); }, 0.0);
357+ QCOMPARE(parentItem->property("shown").toBool(), false);
358+}
359+
360+/*
361+ Set DragHandle.hintDisplacement to a value bigger than zero.
362+ Then lay a finger on the DragHandle.
363+ The expected behavior is that it will move or strech its parent Showable
364+ by hintDisplacement pixels.
365+ */
366+void tst_DragHandle::hintingAnimation()
367+{
368+ DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
369+ QQuickItem *parentItem = dragHandle->parentItem();
370+ qreal hintDisplacement = 100.0;
371+
372+ // enable hinting animations and stretch mode
373+ m_view->rootObject()->setProperty("hintDisplacement", QVariant(hintDisplacement));
374+ m_view->rootObject()->setProperty("stretch", QVariant(true));
375+
376+ QCOMPARE(parentItem->height(), 0.0);
377+
378+ QPointF initialTouchPos = dragHandle->mapToScene(
379+ QPointF(dragHandle->width() / 2.0, dragHandle->height() / 2.0));
380+ QPointF touchPoint = initialTouchPos;
381+
382+ // Pressing causes the Showable to be stretched by hintDisplacement pixels
383+ QTest::touchEvent(m_view, m_device).press(0, touchPoint.toPoint());
384+ tryCompare([&](){ return parentItem->height(); }, hintDisplacement);
385+
386+ // Releasing causes the Showable to shrink back to 0 pixels.
387+ QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
388+ tryCompare([&](){ return parentItem->height(); }, 0.0);
389+
390+ QCOMPARE(parentItem->property("shown").toBool(), false);
391+}
392+
393+QTEST_MAIN(tst_DragHandle)
394+
395+#include "tst_DragHandle.moc"
tests/qmltests/Components/tst_DragHandle.qmlnew file+146
@@ -0,0 +1,146 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import "../../../Components"
19+import "tst_DragHandle"
20+import Ubuntu.Components 0.1
21+import Ubuntu.Gestures 0.1
22+
23+/*
24+ Two blue fullscreen Showables (a vertical and a horizontal one) with red handles you
25+ can use to drag them away and green handles to drag them in.
26+
27+ A black vertical line marks the point where a drag needs no forward velocity to
28+ achieve auto-completion (i.e., get Showable.show() called after touch release).
29+ */
30+Item {
31+ id: root
32+ width: 700
33+ height: 500
34+
35+ property var dragHandle
36+
37+ property bool stretch: false
38+ property real hintDisplacement: 0
39+
40+ VerticalShowable {
41+ onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
42+ stretch: root.stretch
43+ hintDisplacement: root.hintDisplacement
44+ }
45+
46+ HorizontalShowable {
47+ onDragHandleRecognizedGesture: { root.dragHandle = dragHandle }
48+ stretch: root.stretch
49+ hintDisplacement: root.hintDisplacement
50+ }
51+
52+ // Visually mark drag threshold
53+ Rectangle {
54+ color: "black"
55+ width: 2
56+ height: parent.height
57+
58+ visible: dragHandle !== undefined && Direction.isHorizontal(dragHandle.direction)
59+
60+ x: {
61+ if (dragHandle) {
62+ if (dragHandle.direction === Direction.Rightwards) {
63+ dragHandle.edgeDragEvaluator.dragThreshold;
64+ } else {
65+ parent.width - dragHandle.edgeDragEvaluator.dragThreshold;
66+ }
67+ } else {
68+ 0
69+ }
70+ }
71+ }
72+ Rectangle {
73+ color: "black";
74+ height: 2
75+ width: parent.width
76+
77+ visible: dragHandle !== undefined && Direction.isVertical(dragHandle.direction)
78+
79+ y: {
80+ if (dragHandle) {
81+ if (dragHandle.direction === Direction.Downwards) {
82+ dragHandle.edgeDragEvaluator.dragThreshold;
83+ } else {
84+ parent.height - dragHandle.edgeDragEvaluator.dragThreshold;
85+ }
86+ } else {
87+ 0
88+ }
89+ }
90+ }
91+
92+ // Display velocities
93+ Rectangle {
94+ width: childrenRect.width
95+ height: childrenRect.height
96+ color: "white"
97+ opacity: 0.4
98+ Text {
99+ id: velocityText
100+ font.pixelSize: units.gu(2)
101+ text: {
102+ if (dragHandle !== undefined) {
103+ "Velocity: " + (dragHandle.edgeDragEvaluator.velocity * 1000);
104+ } else {
105+ "Velocity: -";
106+ }
107+ }
108+ }
109+ Text {
110+ anchors.top: velocityText.bottom
111+ font.pixelSize: units.gu(2)
112+ text: {
113+ if (dragHandle !== undefined) {
114+ "Minimum velocity: " + (dragHandle.edgeDragEvaluator.minVelocity * 1000);
115+ } else {
116+ "Minimum velocity: -";
117+ }
118+ }
119+ }
120+ }
121+
122+ TestButton {
123+ id: stretchButton
124+ anchors.bottom: parent.bottom
125+ anchors.left: parent.left
126+ anchors.margins: units.gu(1)
127+
128+ text: root.stretch ? "stretch" : "move"
129+ onClicked: { root.stretch = !root.stretch; }
130+ }
131+
132+ TestButton {
133+ anchors.bottom: parent.bottom
134+ anchors.left: stretchButton.right
135+ anchors.margins: units.gu(1)
136+
137+ text: root.hintDisplacement > 0 ? "hint" : "no hint"
138+ onClicked: {
139+ if (root.hintDisplacement > 0) {
140+ root.hintDisplacement = 0;
141+ } else {
142+ root.hintDisplacement = units.gu(6);
143+ }
144+ }
145+ }
146+}
tests/qmltests/Components/tst_DragHandle/HorizontalShowable.qmlnew file+100
@@ -0,0 +1,100 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import "../../../../Components"
19+import Ubuntu.Components 0.1
20+import Ubuntu.Gestures 0.1
21+
22+Showable {
23+ id: showable
24+ x: stretch ? 0 : -width
25+ width: stretch ? 0 : parent.width
26+ height: parent.height
27+
28+ property bool stretch
29+ property real hintDisplacement
30+
31+ onStretchChanged: {
32+ if (stretch) {
33+ x = 0;
34+ width = 0;
35+ } else {
36+ x = -parent.width;
37+ width = parent.width;
38+ }
39+ }
40+
41+ shown: false
42+
43+ signal dragHandleRecognizedGesture(var dragHandle)
44+
45+ property string animatedProp: stretch ? "width" : "x"
46+ property real propValueWhenShown: stretch ? parent.width : 0
47+ property real propValueWhenHidden: stretch ? 0 : -width
48+
49+ showAnimation: StandardAnimation { property: animatedProp; to: propValueWhenShown }
50+ hideAnimation: StandardAnimation { property: animatedProp; to: propValueWhenHidden }
51+
52+ Image { source: "UnityLogo.png"; anchors.fill: parent }
53+
54+ DragHandle {
55+ objectName: "leftwardsDragHandle"
56+ id: leftwardsDragHandle
57+ anchors.top: parent.top
58+ anchors.bottom: parent.bottom
59+ anchors.right: parent.right
60+
61+ width: units.gu(2)
62+
63+ direction: Direction.Leftwards
64+ stretch: showable.stretch
65+ maxTotalDragDistance: showable.parent.width
66+ hintDisplacement: showable.hintDisplacement
67+
68+ onStatusChanged: {
69+ if (status === DirectionalDragArea.Recognized) {
70+ dragHandleRecognizedGesture(leftwardsDragHandle);
71+ }
72+ }
73+
74+ Rectangle { color: "red"; anchors.fill: parent }
75+ }
76+
77+ DragHandle {
78+ objectName: "rightwardsDragHandle"
79+ id: rightwardsDragHandle
80+ anchors.top: parent.top
81+ anchors.bottom: parent.bottom
82+ anchors.left: parent.right
83+
84+ width: units.gu(2)
85+
86+ direction: Direction.Rightwards
87+ stretch: showable.stretch
88+ maxTotalDragDistance: showable.parent.width
89+ hintDisplacement: showable.hintDisplacement
90+
91+ onStatusChanged: {
92+ if (status === DirectionalDragArea.Recognized) {
93+ dragHandleRecognizedGesture(rightwardsDragHandle);
94+ }
95+ }
96+
97+ Rectangle { color: "green"; anchors.fill: parent }
98+ }
99+
100+}
tests/qmltests/Components/tst_DragHandle/TestButton.qmlnew file+41
@@ -0,0 +1,41 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+
20+Rectangle {
21+ id: rect
22+ width: childrenRect.width
23+ height: childrenRect.height
24+
25+ property alias text: textComponent.text
26+
27+ signal clicked
28+
29+ color: "yellow"
30+ Text {
31+ id: textComponent
32+ font.pixelSize: units.gu(2)
33+ text: root.stretch ? "stretch" : "move"
34+ MouseArea {
35+ anchors.fill: parent
36+ onClicked: {
37+ rect.clicked()
38+ }
39+ }
40+ }
41+}
tests/qmltests/Components/tst_DragHandle/UnityLogo.pngnew file

Binary file not shown.

tests/qmltests/Components/tst_DragHandle/VerticalShowable.qmlnew file+100
@@ -0,0 +1,100 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import "../../../../Components"
19+import Ubuntu.Components 0.1
20+import Ubuntu.Gestures 0.1
21+
22+Showable {
23+ id: showable
24+ y: stretch ? 0 : -height
25+ width: parent.width
26+ height: stretch ? 0 : parent.height
27+
28+ property bool stretch
29+ property real hintDisplacement
30+
31+ onStretchChanged: {
32+ if (stretch) {
33+ y = 0;
34+ height = 0;
35+ } else {
36+ y = -parent.height;
37+ height = parent.height;
38+ }
39+ }
40+
41+ shown: false
42+
43+ signal dragHandleRecognizedGesture(var dragHandle)
44+
45+ property string animatedProp: stretch ? "height" : "y"
46+ property real propValueWhenShown: stretch ? parent.height : 0
47+ property real propValueWhenHidden: stretch ? 0 : -height
48+
49+ showAnimation: StandardAnimation { property: animatedProp; to: propValueWhenShown }
50+ hideAnimation: StandardAnimation { property: animatedProp; to: propValueWhenHidden }
51+
52+ Image { source: "UnityLogo.png"; anchors.fill: parent }
53+
54+ DragHandle {
55+ objectName: "upwardsDragHandle"
56+ id: upwardsDragHandle
57+ anchors.left: parent.left
58+ anchors.right: parent.right
59+ anchors.bottom: parent.bottom
60+
61+ height: units.gu(2)
62+
63+ direction: Direction.Upwards
64+ stretch: showable.stretch
65+ maxTotalDragDistance: showable.parent.height
66+ hintDisplacement: showable.hintDisplacement
67+
68+ onStatusChanged: {
69+ if (status === DirectionalDragArea.Recognized) {
70+ dragHandleRecognizedGesture(upwardsDragHandle);
71+ }
72+ }
73+
74+ Rectangle { color: "red"; anchors.fill: parent }
75+ }
76+
77+ DragHandle {
78+ objectName: "downwardsDragHandle"
79+ id: downwardsDragHandle
80+ anchors.left: parent.left
81+ anchors.right: parent.right
82+ anchors.top: parent.bottom
83+
84+ height: units.gu(2)
85+
86+ direction: Direction.Downwards
87+ stretch: showable.stretch
88+ maxTotalDragDistance: showable.parent.height
89+ hintDisplacement: showable.hintDisplacement
90+
91+ onStatusChanged: {
92+ if (status === DirectionalDragArea.Recognized) {
93+ dragHandleRecognizedGesture(downwardsDragHandle);
94+ }
95+ }
96+
97+ Rectangle { color: "green"; anchors.fill: parent }
98+ }
99+
100+}
tests/qmltests/Components/tst_ListViewWithPageHeader.qmldeleted−351
@@ -1,351 +0,0 @@
1−/*
2− * Copyright 2013 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import ".."
20−import "../../../Components"
21−import Ubuntu.Components.ListItems 0.1 as ListItem
22−import Ubuntu.Components 0.1
23−import Unity.Test 0.1 as UT
24−
25−Item {
26− id: root
27− width: units.gu(40)
28− height: units.gu(80)
29−
30− ListModel {
31− id: animalsModel
32− ListElement { name: "Parrot"; size: "Small" }
33− ListElement { name: "Guinea pig"; size: "Small" }
34− ListElement { name: "Mouse"; size: "Small" }
35− ListElement { name: "Sparrow"; size: "Small" }
36− ListElement { name: "Dog"; size: "Medium" }
37− ListElement { name: "Cat"; size: "Medium" }
38− ListElement { name: "Dolphin"; size: "Medium" }
39− ListElement { name: "Seal"; size: "Medium" }
40− ListElement { name: "Elephant"; size: "Large" }
41− ListElement { name: "Blue whale"; size: "Large" }
42− ListElement { name: "Rhino"; size: "Large" }
43− ListElement { name: "Ostrich"; size: "Large" }
44− ListElement { name: "Sperm whale"; size: "Large" }
45− ListElement { name: "Giraffe"; size: "Large" }
46− ListElement { name: "Parrot"; size: "Small" }
47− ListElement { name: "Guinea pig"; size: "Small" }
48− ListElement { name: "Mouse"; size: "Small" }
49− ListElement { name: "Sparrow"; size: "Small" }
50− ListElement { name: "Dog"; size: "Medium" }
51− ListElement { name: "Cat"; size: "Medium" }
52− ListElement { name: "Dolphin"; size: "Medium" }
53− ListElement { name: "Seal"; size: "Medium" }
54− ListElement { name: "Elephant"; size: "Large" }
55− ListElement { name: "Blue whale"; size: "Large" }
56− ListElement { name: "Rhino"; size: "Large" }
57− ListElement { name: "Ostrich"; size: "Large" }
58− ListElement { name: "Sperm whale"; size: "Large" }
59− ListElement { name: "Giraffe"; size: "Large" }
60− ListElement { name: "Parrot"; size: "Small" }
61− ListElement { name: "Guinea pig"; size: "Small" }
62− ListElement { name: "Mouse"; size: "Small" }
63− ListElement { name: "Sparrow"; size: "Small" }
64− ListElement { name: "Dog"; size: "Medium" }
65− ListElement { name: "Cat"; size: "Medium" }
66− ListElement { name: "Dolphin"; size: "Medium" }
67− ListElement { name: "Seal"; size: "Medium" }
68− ListElement { name: "Elephant"; size: "Large" }
69− ListElement { name: "Blue whale"; size: "Large" }
70− ListElement { name: "Rhino"; size: "Large" }
71− ListElement { name: "Ostrich"; size: "Large" }
72− ListElement { name: "Sperm whale"; size: "Large" }
73− ListElement { name: "Giraffe"; size: "Large" }
74− ListElement { name: "Parrot"; size: "Small" }
75− ListElement { name: "Guinea pig"; size: "Small" }
76− ListElement { name: "Mouse"; size: "Small" }
77− ListElement { name: "Sparrow"; size: "Small" }
78− ListElement { name: "Dog"; size: "Medium" }
79− ListElement { name: "Cat"; size: "Medium" }
80− ListElement { name: "Dolphin"; size: "Medium" }
81− ListElement { name: "Seal"; size: "Medium" }
82− ListElement { name: "Elephant"; size: "Large" }
83− ListElement { name: "Blue whale"; size: "Large" }
84− ListElement { name: "Rhino"; size: "Large" }
85− ListElement { name: "Ostrich"; size: "Large" }
86− ListElement { name: "Sperm whale"; size: "Large" }
87− ListElement { name: "Giraffe"; size: "Large" }
88− }
89−
90− ListViewWithPageHeader {
91− id: listView
92− anchors.fill: parent
93− model: animalsModel
94−
95− delegate: Item {
96− height: units.gu(6)
97− anchors {
98− left: parent.left
99− right: parent.right
100− }
101−
102− Label {
103− id: label
104− anchors.fill: parent
105− text: name
106− verticalAlignment: Text.AlignVCenter
107− }
108− }
109−
110− sectionProperty: "size"
111− sectionDelegate: Rectangle {
112− anchors {
113− left: (parent) ? parent.left : undefined
114− right: (parent) ? parent.right : undefined
115− }
116− height: units.gu(5)
117− color: "lightsteelblue"
118−
119− Label {
120− id: label
121− anchors.fill: parent
122− text: section
123− verticalAlignment: Text.AlignVCenter
124− }
125− }
126−
127− pageHeader: PageHeader {
128− id: pageHeader
129− anchors {
130− left: parent.left
131− right: parent.right
132− }
133− text: "Animals"
134− }
135− }
136−
137−
138−
139−
140− UT.UnityTestCase {
141− name: "ListViewWithPageHeader"
142− when: windowShown
143−
144− readonly property real xPos: listView.width / 2
145− readonly property real headerHeight: pageHeader.height
146−
147− /**************************** Helper functions ****************************/
148− function listViewFirstSectionHeaderYPosition() {
149− return Math.round(listView.pageHeader.mapToItem(listView).y); //round as using floats
150− }
151−
152− function firstSectionHeaderYPosition() {
153− return Math.round(listView.view.children[0].mapToItem(listView).y);
154− }
155−
156− function cleanup() {
157− listView.positionAtBeginning();
158− // wait for list position to reset
159− tryCompareFunction(listViewFirstSectionHeaderYPosition, 0);
160− tryCompare(listView.view.contentY, 0);
161− }
162−
163− // these functions are hand-crafted to move the Flickable down/up one pixel
164− function swipeDown1Pixel(item) {
165− mousePress(item, xPos, 15);
166− mouseMove(item, xPos, 14, 100);
167− mouseMove(item, xPos, 10, 100);
168− mouseMove(item, xPos, 6, 100);
169− mouseMove(item, xPos, 3, 100);
170− mouseMove(item, xPos, 1, 100);
171− mouseMove(item, xPos, 0, 100);
172− mouseRelease(item, xPos, 0);
173− }
174−
175− function swipeUp1Pixel(item) {
176− mousePress(item, xPos, 0);
177− mouseMove(item, xPos, 1, 100);
178− mouseMove(item, xPos, 5, 100);
179− mouseMove(item, xPos, 9, 100);
180− mouseMove(item, xPos, 12, 100);
181− mouseMove(item, xPos, 14, 100);
182− mouseMove(item, xPos, 15, 100);
183− mouseRelease(item, xPos, 15);
184− }
185−
186− /******************************* Test cases *******************************/
187−
188− /* Check the initial positions of components are correct */
189− function test_initialState() {
190− compare(listViewFirstSectionHeaderYPosition(), 0);
191− compare(listView.view.contentY, 0);
192−
193− // Check that the section delegate is positioned underneath the header
194− // First section delegate is the first child of the view
195− tryCompareFunction(firstSectionHeaderYPosition, headerHeight);
196− }
197−
198− /* Check the header moves up one pixel when the view is moved up by one pixel */
199− function test_headerPositionAfterDownMoveByOnePixel() {
200− swipeDown1Pixel(listView)
201−
202− tryCompareFunction(listViewFirstSectionHeaderYPosition, -1);
203− tryCompareFunction(firstSectionHeaderYPosition, headerHeight - 1);
204− tryCompare(listView.view.contentY, -1);
205− }
206−
207− /* Check the header position is y=0 when view moved up and then down by one pixel */
208− function test_headerPositionAfterDownAndThenUpMoveByOne() {
209− swipeDown1Pixel(listView)
210−
211− tryCompareFunction(listViewFirstSectionHeaderYPosition, -1);
212− tryCompare(listView.view.contentY, -1);
213−
214− // these operations move the Flickabe up one pixel
215− swipeUp1Pixel(listView);
216−
217− tryCompare(listView.view.contentY, 0);
218− // tryCompareFunction(listViewFirstSectionHeaderYPosition, 0) //FIXME - this fails due to bug in LVWPH
219− tryCompareFunction(firstSectionHeaderYPosition, headerHeight)
220− }
221−
222− /* Check after a big flick the header is moved off-screen, with the header bottom
223− placed just above the view */
224− function test_headerPositionAfterDownMove() {
225− // move the Flickabe up to hide header
226− listView.flick(0, -10000);
227−
228− // wait for flick to finish
229− tryCompare(listView.moving, false);
230−
231− tryCompareFunction(listViewFirstSectionHeaderYPosition, -headerHeight);
232− }
233−
234− /* Check when header off-screen, moving down the view by one pixel moves the header
235− down by one pixel */
236− function test_hiddenHeaderPositionAfterUpMoveByOnePixel() {
237− // move the Flickabe up to hide header
238− listView.flick(0, -10000);
239−
240− // wait for flick to fully hide header
241− tryCompareFunction(listViewFirstSectionHeaderYPosition, -headerHeight);
242−
243− swipeUp1Pixel(listView);
244−
245− tryCompareFunction( function() {
246− return Math.floor( listViewFirstSectionHeaderYPosition() ); // need to round to make test more robust
247− }, -headerHeight + 1);
248− }
249−
250− /* Check if up swipe causes list to bounces at the bottom, header stays hidden */
251− function test_upSwipeCausingBounceKeepsHeaderHidden() {
252− // move list to the bottom (will bounce)
253− listView.flick(0, -1000000);
254−
255− // wait for bounce to complete
256− tryCompare(listView.moving, false);
257− tryCompare(listView.view.atYEnd, true);
258−
259− tryCompareFunction(listViewFirstSectionHeaderYPosition, -headerHeight);
260− }
261−
262− /* Check if up swipe causes list to bounces at the bottom, header stays hidden */
263− function test_downSwipeCausingBounceKeepsHeaderVisible() {
264− // move list to the bottom (will bounce)
265− listView.flick(0, -1000000);
266−
267− // wait for bounce to complete
268− tryCompare(listView.moving, false);
269− tryCompare(listView.view.atYBeginning, true);
270−
271− tryCompareFunction(listViewFirstSectionHeaderYPosition, 0);
272− }
273−
274− /* Check if list at top is pulled down further, that the list contents move but the
275− header remains at the top of the view */
276− function test_topDragOverBoundsKeepsHeaderVisible() {
277− // drag list up - but don't release yet
278− mouseFlick(listView,
279− xPos, // from_x
280− 0, // from_y
281− xPos, // to_x
282− 100, true, false, 0.2);
283−
284− // wait for gesture to occur
285− tryCompareFunction(function() { return listView.view.contentY < 20; }, true);
286− tryCompareFunction(listViewFirstSectionHeaderYPosition, 0);
287−
288− mouseRelease(listView, xPos, 400);
289−
290− // ensure list moving to recover from over-bound drag keeps header unchanged
291− tryCompare(listView.view.contentY, 0);
292− tryCompareFunction(listViewFirstSectionHeaderYPosition, 0);
293− }
294−
295− /* Check if list at top is pulled down further, that the list contents move but the
296− header remains at the top of the view */
297− function test_bottomDragOverBoundsKeepsHeaderHidden() {
298− // move list to the bottom (will bounce)
299− listView.flick(0, -1000000);
300−
301− // wait for bounce to complete
302− tryCompare(listView.moving, false);
303− tryCompare(listView.view.atYEnd, true);
304−
305− // drag list up but don't release
306− mouseFlick(listView,
307− xPos, // from_x
308− 0, // from_y
309− xPos, // to_x
310− -listView.height, true, false);
311−
312− tryCompareFunction(listViewFirstSectionHeaderYPosition, -headerHeight);
313−
314− mouseRelease(listView, xPos, -listView.height);
315− // wait for list to reset position
316− tryCompare(listView.moving, false);
317− tryCompare(listView.view.atYEnd, true);
318−
319− // ensure list moving to recover from over-bound drag keeps header unchanged
320− tryCompareFunction(listViewFirstSectionHeaderYPosition, -headerHeight);
321− }
322−
323− /* Check positionAtBeginning() works resets list and header position */
324− function test_positionAtBeginning() {
325− // move the Flickabe up to hide header
326− listView.flick(0, -10000);
327−
328− // wait for gesture to complete
329− tryCompare(listView.moving, false);
330−
331− listView.positionAtBeginning();
332− tryCompareFunction(listViewFirstSectionHeaderYPosition, 0);
333− tryCompare(listView.view.contentY, 0);
334− }
335−
336− /* Check showHeader forces header to appear but list position remains unchanged */
337− function test_showHeader() {
338− // move the Flickabe up to hide header
339− listView.flick(0, -10000);
340−
341− // wait for gesture to complete
342− tryCompare(listView.moving, false);
343−
344− var listContentY = listView.view.contentY;
345−
346− listView.showHeader();
347− tryCompareFunction(listViewFirstSectionHeaderYPosition, 0);
348− tryCompare(listView.view.contentY, listContentY);
349− }
350− }
351−}
tests/qmltests/Components/tst_Stage.qml+1−2
@@ -233,8 +233,7 @@ Rectangle {
233233
234234 var touchX = stage.width - (stage.rightEdgeDraggingAreaWidth / 2)
235235 var touchY = stage.height / 2
236− touchFlick(stage, touchX, touchY,
237− touchX - units.gu(5), touchY)
236+ touchFlick(stage, touchX, touchY, stage.width * 0.25, touchY)
238237
239238 // wait until animations end, if any
240239 tryCompare(stage, "usingScreenshots", false)
tests/qmltests/Greeter/tst_Phone.qml+40−1
@@ -28,7 +28,17 @@ Item {
2828
2929 Greeter {
3030 id: greeter
31− anchors.fill: parent
31+ width: parent.width
32+ height: parent.height
33+ x: 0; y: 0
34+
35+ property int minX: 0
36+
37+ onXChanged: {
38+ if (x < minX) {
39+ minX = x;
40+ }
41+ }
3242 }
3343
3444 SignalSpy {
@@ -63,5 +73,34 @@ Item {
6373 tryCompare(greeter, "leftTeaserPressed", false)
6474 tryCompare(greeter, "rightTeaserPressed", false)
6575 }
76+
77+ function test_teaseLockedUnlocked_data() {
78+ return [
79+ {tag: "unlocked", locked: false},
80+ {tag: "locked", locked: true}
81+ ];
82+ }
83+
84+ function test_teaseLockedUnlocked(data) {
85+ tryCompare(greeter, "rightTeaserPressed", false);
86+ tryCompare(greeter, "x", 0);
87+ greeter.locked = data.locked;
88+
89+ mouseClick(greeter, greeter.width - units.gu(5), greeter.height - units.gu(1));
90+ greeter.minX = 0; // This is needed because the transition actually makes x jump once before animating
91+
92+ if (!data.locked) {
93+ // Check if it has been moved over by 2 GUs. Give it a 2 pixel grace area
94+ // because animation duration and teaseTimer are the same duration and
95+ // might cause slight offsets
96+ tryCompareFunction(function() { return greeter.minX <= -units.gu(2) + 2}, true);
97+ } else {
98+ // waiting 100ms to make sure nothing moves
99+ wait(100);
100+ compare(greeter.minX, 0, "Greeter moved even tho its locked");
101+ }
102+ // Wait until we're back to 0
103+ tryCompareFunction(function() { return greeter.x;}, 0);
104+ }
66105 }
67106}
tests/qmltests/Launcher/tst_Launcher.qml+40
@@ -43,6 +43,18 @@ Item {
4343 onDashItemSelected: {
4444 dashItemSelected_count++;
4545 }
46+
47+ property int maxPanelX: 0
48+ }
49+
50+ Connections {
51+ target: testCase.findChild(launcher, "launcherPanel")
52+
53+ onXChanged: {
54+ if (target.x > launcher.maxPanelX) {
55+ launcher.maxPanelX = target.x;
56+ }
57+ }
4658 }
4759
4860 UT.UnityTestCase {
@@ -126,5 +138,33 @@ Item {
126138 var panel = findChild(launcher, "launcherPanel")
127139 tryCompare(panel, "x", -panel.width, 1000)
128140 }
141+
142+
143+ function test_teaseLauncher_data() {
144+ return [
145+ {tag: "available", available: true},
146+ {tag: "not available", available: false}
147+ ];
148+ }
149+
150+ function test_teaseLauncher(data) {
151+ launcher.available = data.available;
152+ launcher.maxPanelX = -launcher.panelWidth;
153+ launcher.tease();
154+
155+ if (data.available) {
156+ // Check if the launcher slides in for units.gu(2). However, as the animation is 200ms
157+ // and the teaseTimer's timeout too, give it a 2 pixels grace distance
158+ tryCompareFunction(
159+ function(){
160+ return launcher.maxPanelX >= -launcher.panelWidth + units.gu(2) - 2;
161+ },
162+ true)
163+ } else {
164+ wait(100)
165+ compare(launcher.maxPanelX, -launcher.panelWidth, "Launcher moved even if it shouldn't")
166+ }
167+ waitUntilLauncherDisappears();
168+ }
129169 }
130170}