on xenial help sign in
Merged trunk.
925013ePawel Stolowski
.bazaar/plugins/makecheck_unity_phablet.py+15−6
@@ -23,12 +23,21 @@ def execute_makecheck(local_branch, master_branch, old_revision_number, old_revi
23
23
24 os.chdir(local_path_from_url(master_branch.base))
24 os.chdir(local_path_from_url(master_branch.base))
25
25
26− print "Executing 'make check'.."
26+ print "Executing 'make -C builddir test'.."
27+ os.environ['CTEST_OUTPUT_ON_FAILURE'] = "1"
27− if (subprocess.call("make check", shell=True) != 0):
28+ if (subprocess.call("make -C builddir test", shell=True) != 0):
28− raise errors.BzrError("Unit tests failed, fix them before committing!")
29
29
30− print "Executing 'make qmluitests'.."
30+ print("\n\n*** Warning ***\n\nBasic tests failed. This commit will not pass continuous integration.")
31− if (subprocess.call("make qmluitests", shell=True) != 0):
31+
32− raise errors.BzrError("QML UI tests failed, fix them before committing!")
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")
33
42
34branch.Branch.hooks.install_named_hook('pre_commit', execute_makecheck, 'make check pre-commit')
43branch.Branch.hooks.install_named_hook('pre_commit', execute_makecheck, 'make check pre-commit')
.bzrignore+1
@@ -7,3 +7,4 @@
7/.cproject
7/.cproject
8/.settings
8/.settings
9/.pydevproject
9/.pydevproject
10+message.txt
Bottombar/Bottombar.qml+41−82
@@ -18,38 +18,42 @@ import QtQuick 2.0
18import "../Components"
18import "../Components"
19import "../Components/Math.js" as MathLocal
19import "../Components/Math.js" as MathLocal
20import Unity 0.1
20import Unity 0.1
21+import Ubuntu.Gestures 0.1
21
22
22Item {
23Item {
23 id: bottombar
24 id: bottombar
24− width: shell.width
25+
25− height: shell.height
26+ // Whether there's an application on foreground (as opposed to have shell's Dash on foreground)
27+ property bool applicationIsOnForeground
26
28
27 property variant theHud
29 property variant theHud
28 property bool enabled: false
30 property bool enabled: false
29 readonly property real bottomEdgeButtonCenterDistance: units.gu(34)
31 readonly property real bottomEdgeButtonCenterDistance: units.gu(34)
30− readonly property real bottomEdgeShowButtonDistance: units.gu(2)
31−
32− property bool __applicationInFocus: false
33
32
34− state: "hidden"
33+ state: dragArea.status === DirectionalDragArea.Recognized ? "shown" : "hidden"
35
34
36 HudButton {
35 HudButton {
37 id: hudButton
36 id: hudButton
38
37
39− x: MathLocal.clamp(hudButtonRevealer.pressedX - width / 2, 0, bottombar.width - width)
38+ x: MathLocal.clamp(dragArea.touchStartX - (width / 2), 0, bottombar.width - width)
40− y: bottombar.height - bottomEdgeButtonCenterDistance - height / 2 - bottomMargin
39+ y: bottombar.height - bottomEdgeButtonCenterDistance - (height / 2) - bottomMargin
41− Behavior on bottomMargin {
40+
42− NumberAnimation{duration: hudButton.opacity < 0.01 ? 200 : 70; easing.type: Easing.OutQuart}
41+ mouseOver: {
43− }
42+ if (dragArea.status === DirectionalDragArea.Recognized) {
44− mouse: {
43+ var touchLocal = mapFromItem(dragArea, dragArea.touchX, dragArea.touchY)
45− if (hudButtonRevealer.draggingArea.pressed) {
44+ return touchLocal.x > 0 && touchLocal.x < width
46− var mapped = mapFromItem(hudButtonRevealer.draggingArea, hudButtonRevealer.draggingArea.mouseX, hudButtonRevealer.draggingArea.mouseY)
45+ && touchLocal.y > 0 && touchLocal.y < height
47− return Qt.point(mapped.x, mapped.y)
48 } else {
46 } else {
49− return mouse
47+ return false
50 }
48 }
51 }
49 }
52
50
51+ onClicked: theHud.show()
52+
53+ Behavior on bottomMargin {
54+ NumberAnimation{duration: hudButton.opacity < 0.01 ? 200 : 70; easing.type: Easing.OutQuart}
55+ }
56+
53 Behavior on opacity {
57 Behavior on opacity {
54 NumberAnimation{ duration: 200; easing.type: Easing.OutCubic}
58 NumberAnimation{ duration: 200; easing.type: Easing.OutCubic}
55 }
59 }
@@ -60,74 +64,29 @@ Item {
60 onShownChanged: bottomBarVisibilityCommunicatorShell.forceHidden = theHud.shown
64 onShownChanged: bottomBarVisibilityCommunicatorShell.forceHidden = theHud.shown
61 }
65 }
62
66
63− function updateApplicationInFocus() {
67+ EdgeDragArea {
64− if (shell.applicationManager.mainStageFocusedApplication || shell.applicationManager.sideStageFocusedApplication) {
68+ id: dragArea
65− __applicationInFocus = true
66− } else {
67− __applicationInFocus = false
68− }
69− }
70−
71− Connections {
72− target: shell.applicationManager
73− ignoreUnknownSignals: true
74− onMainStageFocusedApplicationChanged: updateApplicationInFocus()
75− onSideStageFocusedApplicationChanged: updateApplicationInFocus()
76− }
77−
78− Showable {
79− id: hudButtonShowable
80−
81− opacity: 1.0
82 width: parent.width
69 width: parent.width
83− height: bottomEdgeShowButtonDistance
70+ height: distanceThreshold
84− shown: false
85− showAnimation: StandardAnimation { property: "y"; duration: 350; to: hudButtonRevealer.openedValue; easing.type: Easing.OutCubic }
86− hideAnimation: StandardAnimation { property: "y"; duration: 350; to: hudButtonRevealer.closedValue; easing.type: Easing.OutCubic }
87− onYChanged: {
88− if (y == hudButtonRevealer.openedValue)
89− bottombar.state = "shown"
90− }
91−
92− // eater
93− MouseArea {
94− anchors.fill: parent
71+ anchors.bottom: parent.bottom
95− }
72+
96− }
97−
98− Revealer {
99− id: hudButtonRevealer
100−
101− property double pressedX
102−
103− enabled: !theHud.shown && bottombar.enabled && __applicationInFocus
73+ enabled: !theHud.shown && bottombar.enabled && applicationIsOnForeground
104− direction: Qt.RightToLeft
74+ direction: Direction.Upwards
105− openedValue: bottombar.height - height
75+
106− closedValue: bottombar.height
76+ property int previousStatus: -1
107− target: hudButtonShowable
77+ property real touchStartX: -1
108− width: hudButtonShowable.width
78+
109− height: hudButtonShowable.height
79+ onStatusChanged: {
110− anchors.bottom: bottombar.bottom
80+ if (status === DirectionalDragArea.WaitingForTouch) {
111− onOpenPressed: {
81+ if (previousStatus == DirectionalDragArea.Recognized) {
112− pressedX = mouseX
113− }
114−
115− onOpenReleased: {
116− if (hudButton.opacity != 0 && hudButton.mouseOver) {
82+ if (hudButton.mouseOver) {
117− hudButtonShowable.hide()
83+ hudButton.clicked()
118− theHud.show()
84+ }
119− } else {
85+ }
120− hudButtonShowable.hide()
86+ } else if (status === DirectionalDragArea.Undecided) {
121− }
87+ touchStartX = touchX
122− }
123− }
124−
125− Connections {
126− target: hudButtonShowable.hideAnimation
127− onRunningChanged: {
128− if (hudButtonShowable.hideAnimation.running) {
129− bottombar.state = "hidden"
130 }
88 }
89+ previousStatus = status
131 }
90 }
132 }
91 }
133
92
Bottombar/HudButton.qml+3−2
@@ -20,10 +20,11 @@ import Ubuntu.Components 0.1
20Item {
20Item {
21 id: item
21 id: item
22
22
23+ property bool mouseOver
24+
23 property int bottomMargin: units.gu(2)
25 property int bottomMargin: units.gu(2)
24− property bool mouseOver: contains(mouse)
25
26
26− property point mouse: Qt.point(-1,-1)
27+ signal clicked()
27
28
28 readonly property real scaleOnMouseOver: 1.2
29 readonly property real scaleOnMouseOver: 1.2
29
30
Bottombar/graphics/hud_invoke_button_active@20.png

Binary file not shown.

CMakeLists.txt+1
@@ -57,6 +57,7 @@ find_package(Qt5DBus)
57include(GNUInstallDirs)
57include(GNUInstallDirs)
58
58
59set(SHELL_APP_DIR ${CMAKE_INSTALL_DATADIR}/unity8)
59set(SHELL_APP_DIR ${CMAKE_INSTALL_DATADIR}/unity8)
60+set(SHELL_PRIVATE_LIBDIR ${CMAKE_INSTALL_LIBDIR}/unity8)
60
61
61configure_file(paths.h.in ${CMAKE_CURRENT_BINARY_DIR}/paths.h @ONLY)
62configure_file(paths.h.in ${CMAKE_CURRENT_BINARY_DIR}/paths.h @ONLY)
62
63
CODING+75−29
@@ -1,43 +1,64 @@
1Building Unity 8
1Building Unity 8
2================
2================
3
3
4+Only Ubuntu 13.10 (saucy) is supported as a developement environment.
5+
4download source
6download source
5---------------
7---------------
6−- the build requires some additional dependencies, so create the parent folder to not pollute your setup
8+- create a parent folder to not pollute your setup. so that you can have different unity
9+ branches there (trunk, WIP etc)
10+
7− $ mkdir ~/unity
11+ $ mkdir ~/unity8
8
12
9- fetch Unity 8 source
13- fetch Unity 8 source
10 $ sudo apt-get install bzr
14 $ sudo apt-get install bzr
11− $ bzr branch lp:unity/8.0 ~/unity/unity8
15+ $ bzr branch lp:unity8 ~/unity8/trunk
12− $ cd ~/unity/unity8
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
13
24
14−build dependencies
15−------------------
16−If its your first time, download & build deps
17−$ ./build -s
18 this will:
25 this will:
26+ - add the following PPA's
27+ - ppa:phablet-team/desktop-deps
19− - add ppa:phablet-team/desktop-deps, ppa:canonical-qt5-edgers/qt5-proper, ppa:ubuntu-sdk-team
28+ - ppa:canonical-qt5-edgers/qt5-proper
20− - build and install lp:libunity/phablet, lp:unity/phablet-mods, lp:hud/phablet locally
29+ - ppa:ubuntu-sdk-team
21− - install build dependencies
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+
22
38
23build Unity 8
39build Unity 8
24-------------
40-------------
25−$ ./build
26
41
27−subsequent updates of the dependencies
42+$ cd ~/unity8/trunk
28−--------------------------------------
43+$ ./build
29−$ ./build_unity -u
30−$ ./build_unity
31
44
45+You may also rebuild with the -c for clean, which just deletes the build
46+directory.
32
47
33Running Unity 8 on your desktop
48Running Unity 8 on your desktop
34===============================
49===============================
35
50
36run the Unity 8 shell
51run the Unity 8 shell
37---------------------
52---------------------
38−$ cd ~/unity/unity8
53+$ cd ~/unity8/trunk
39$ ./run
54$ ./run
40
55
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+
41Notes
62Notes
42-----
63-----
43- to navigate, utilize the mouse left button as you would your finger
64- to navigate, utilize the mouse left button as you would your finger
@@ -45,17 +66,29 @@ Notes
45 put the *.mo files into correct structure. We'll look for a better solution
66 put the *.mo files into correct structure. We'll look for a better solution
46 later.
67 later.
47 $ cd builddir; make install
68 $ 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
48
75
49Running Unity 8 on devices
76Running Unity 8 on devices
50==========================
77==========================
51- Ubuntu Touch builds are currently only available in 13.10 flavour
78- 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
79+- supported hardware should match one those listed here
80+ 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
81+- follow the Ubuntu Touch install instructions for your chosen device
82+ https://wiki.ubuntu.com/Touch/Install
54- make sure your device is connected to a WiFi network
83- make sure your device is connected to a WiFi network
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
55−- also make sure you have your SSH key in ~/.ssh/id_rsa.pub (or install one on the device yourself)
87+- also make sure you have your SSH key in ~/.ssh/id_rsa.pub (or install one
56−
88+ on the device yourself)
89+
57−$ cd ~/unity/unity8
90+$ cd ~/unity/trunk
58−$ ./run_on_device -s
91+$ ./run_on_device --setup
59 this will:
92 this will:
60 - install your public SSH key on the device
93 - install your public SSH key on the device
61 - add ppa:canonical-qt5-edgers/qt5-proper and ppa:phablet-team
94 - add ppa:canonical-qt5-edgers/qt5-proper and ppa:phablet-team
@@ -67,19 +100,27 @@ $ ./run_on_device
67 - build on the device
100 - build on the device
68 - replace the running shell
101 - replace the running shell
69
102
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+
70Notes
109Notes
71-----
110-----
72- using adb over TCP has some advantages, Google will be of help here
111- using adb over TCP has some advantages, Google will be of help here
73 - TL;DR: `adb tcpip 5555; adb connect $your_device_ip`
112 - TL;DR: `adb tcpip 5555; adb connect $your_device_ip`
74 - you can persist the above via `adb shell setprop persist.adb.tcp.port 5555`
113 - you can persist the above via `adb shell setprop persist.adb.tcp.port 5555`
75 - it's unsafe - anyone can connect to your device
114 - 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
115+ - with TCP the Nexus 10 doesn't drop the adb connection when locking
116+ the screen
77−- exporting ANDROID_SERIAL=$your_device_serial or ANDROID_SERIAL=$your_device_ip:5555
117+- exporting ANDROID_SERIAL=$your_device_serial or
78− will make adb not complain about multiple devices
118+ ANDROID_SERIAL=$your_device_ip:5555 will make adb not complain about
119+ multiple devices
79- you can export TARGET_IP=$your_device_ip TARGET_SSH_PORT=22 for run_on_device
120- you can export TARGET_IP=$your_device_ip TARGET_SSH_PORT=22 for run_on_device
80 to not use adb forwarding - useful if you use multiple devices
121 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
122+- using Ninja (package ninja-build - run_on_device -s installs this now)
82− build times (especially in the nothing-to-build case)
123+ will improve build times (especially in the nothing-to-build case)
83
124
84
125
85Coding guidelines
126Coding guidelines
@@ -90,4 +131,9 @@ https://launchpad.net/canonical-client-development-guidelines
90
131
91Development Environment
132Development Environment
92=======================
133=======================
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+
COPYING.LGPLnew file+514
@@ -0,0 +1,514 @@
1+ GNU LESSER GENERAL PUBLIC LICENSE
2+
3+ The Qt Toolkit is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4+ Contact: http://www.qt-project.org/legal
5+
6+ You may use, distribute and copy the Qt GUI Toolkit under the terms of
7+ GNU Lesser General Public License version 2.1, which is displayed below.
8+
9+-------------------------------------------------------------------------
10+
11+ GNU LESSER GENERAL PUBLIC LICENSE
12+ Version 2.1, February 1999
13+
14+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
15+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16+ Everyone is permitted to copy and distribute verbatim copies
17+ of this license document, but changing it is not allowed.
18+
19+[This is the first released version of the Lesser GPL. It also counts
20+ as the successor of the GNU Library Public License, version 2, hence
21+ the version number 2.1.]
22+
23+ Preamble
24+
25+ The licenses for most software are designed to take away your
26+freedom to share and change it. By contrast, the GNU General Public
27+Licenses are intended to guarantee your freedom to share and change
28+free software--to make sure the software is free for all its users.
29+
30+ This license, the Lesser General Public License, applies to some
31+specially designated software packages--typically libraries--of the
32+Free Software Foundation and other authors who decide to use it. You
33+can use it too, but we suggest you first think carefully about whether
34+this license or the ordinary General Public License is the better
35+strategy to use in any particular case, based on the explanations below.
36+
37+ When we speak of free software, we are referring to freedom of use,
38+not price. Our General Public Licenses are designed to make sure that
39+you have the freedom to distribute copies of free software (and charge
40+for this service if you wish); that you receive source code or can get
41+it if you want it; that you can change the software and use pieces of
42+it in new free programs; and that you are informed that you can do
43+these things.
44+
45+ To protect your rights, we need to make restrictions that forbid
46+distributors to deny you these rights or to ask you to surrender these
47+rights. These restrictions translate to certain responsibilities for
48+you if you distribute copies of the library or if you modify it.
49+
50+ For example, if you distribute copies of the library, whether gratis
51+or for a fee, you must give the recipients all the rights that we gave
52+you. You must make sure that they, too, receive or can get the source
53+code. If you link other code with the library, you must provide
54+complete object files to the recipients, so that they can relink them
55+with the library after making changes to the library and recompiling
56+it. And you must show them these terms so they know their rights.
57+
58+ We protect your rights with a two-step method: (1) we copyright the
59+library, and (2) we offer you this license, which gives you legal
60+permission to copy, distribute and/or modify the library.
61+
62+ To protect each distributor, we want to make it very clear that
63+there is no warranty for the free library. Also, if the library is
64+modified by someone else and passed on, the recipients should know
65+that what they have is not the original version, so that the original
66+author's reputation will not be affected by problems that might be
67+introduced by others.
68+
69+ Finally, software patents pose a constant threat to the existence of
70+any free program. We wish to make sure that a company cannot
71+effectively restrict the users of a free program by obtaining a
72+restrictive license from a patent holder. Therefore, we insist that
73+any patent license obtained for a version of the library must be
74+consistent with the full freedom of use specified in this license.
75+
76+ Most GNU software, including some libraries, is covered by the
77+ordinary GNU General Public License. This license, the GNU Lesser
78+General Public License, applies to certain designated libraries, and
79+is quite different from the ordinary General Public License. We use
80+this license for certain libraries in order to permit linking those
81+libraries into non-free programs.
82+
83+ When a program is linked with a library, whether statically or using
84+a shared library, the combination of the two is legally speaking a
85+combined work, a derivative of the original library. The ordinary
86+General Public License therefore permits such linking only if the
87+entire combination fits its criteria of freedom. The Lesser General
88+Public License permits more lax criteria for linking other code with
89+the library.
90+
91+ We call this license the "Lesser" General Public License because it
92+does Less to protect the user's freedom than the ordinary General
93+Public License. It also provides other free software developers Less
94+of an advantage over competing non-free programs. These disadvantages
95+are the reason we use the ordinary General Public License for many
96+libraries. However, the Lesser license provides advantages in certain
97+special circumstances.
98+
99+ For example, on rare occasions, there may be a special need to
100+encourage the widest possible use of a certain library, so that it becomes
101+a de-facto standard. To achieve this, non-free programs must be
102+allowed to use the library. A more frequent case is that a free
103+library does the same job as widely used non-free libraries. In this
104+case, there is little to gain by limiting the free library to free
105+software only, so we use the Lesser General Public License.
106+
107+ In other cases, permission to use a particular library in non-free
108+programs enables a greater number of people to use a large body of
109+free software. For example, permission to use the GNU C Library in
110+non-free programs enables many more people to use the whole GNU
111+operating system, as well as its variant, the GNU/Linux operating
112+system.
113+
114+ Although the Lesser General Public License is Less protective of the
115+users' freedom, it does ensure that the user of a program that is
116+linked with the Library has the freedom and the wherewithal to run
117+that program using a modified version of the Library.
118+
119+ The precise terms and conditions for copying, distribution and
120+modification follow. Pay close attention to the difference between a
121+"work based on the library" and a "work that uses the library". The
122+former contains code derived from the library, whereas the latter must
123+be combined with the library in order to run.
124+
125+ GNU LESSER GENERAL PUBLIC LICENSE
126+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
127+
128+ 0. This License Agreement applies to any software library or other
129+program which contains a notice placed by the copyright holder or
130+other authorized party saying it may be distributed under the terms of
131+this Lesser General Public License (also called "this License").
132+Each licensee is addressed as "you".
133+
134+ A "library" means a collection of software functions and/or data
135+prepared so as to be conveniently linked with application programs
136+(which use some of those functions and data) to form executables.
137+
138+ The "Library", below, refers to any such software library or work
139+which has been distributed under these terms. A "work based on the
140+Library" means either the Library or any derivative work under
141+copyright law: that is to say, a work containing the Library or a
142+portion of it, either verbatim or with modifications and/or translated
143+straightforwardly into another language. (Hereinafter, translation is
144+included without limitation in the term "modification".)
145+
146+ "Source code" for a work means the preferred form of the work for
147+making modifications to it. For a library, complete source code means
148+all the source code for all modules it contains, plus any associated
149+interface definition files, plus the scripts used to control compilation
150+and installation of the library.
151+
152+ Activities other than copying, distribution and modification are not
153+covered by this License; they are outside its scope. The act of
154+running a program using the Library is not restricted, and output from
155+such a program is covered only if its contents constitute a work based
156+on the Library (independent of the use of the Library in a tool for
157+writing it). Whether that is true depends on what the Library does
158+and what the program that uses the Library does.
159+
160+ 1. You may copy and distribute verbatim copies of the Library's
161+complete source code as you receive it, in any medium, provided that
162+you conspicuously and appropriately publish on each copy an
163+appropriate copyright notice and disclaimer of warranty; keep intact
164+all the notices that refer to this License and to the absence of any
165+warranty; and distribute a copy of this License along with the
166+Library.
167+
168+ You may charge a fee for the physical act of transferring a copy,
169+and you may at your option offer warranty protection in exchange for a
170+fee.
171+
172+ 2. You may modify your copy or copies of the Library or any portion
173+of it, thus forming a work based on the Library, and copy and
174+distribute such modifications or work under the terms of Section 1
175+above, provided that you also meet all of these conditions:
176+
177+ a) The modified work must itself be a software library.
178+
179+ b) You must cause the files modified to carry prominent notices
180+ stating that you changed the files and the date of any change.
181+
182+ c) You must cause the whole of the work to be licensed at no
183+ charge to all third parties under the terms of this License.
184+
185+ d) If a facility in the modified Library refers to a function or a
186+ table of data to be supplied by an application program that uses
187+ the facility, other than as an argument passed when the facility
188+ is invoked, then you must make a good faith effort to ensure that,
189+ in the event an application does not supply such function or
190+ table, the facility still operates, and performs whatever part of
191+ its purpose remains meaningful.
192+
193+ (For example, a function in a library to compute square roots has
194+ a purpose that is entirely well-defined independent of the
195+ application. Therefore, Subsection 2d requires that any
196+ application-supplied function or table used by this function must
197+ be optional: if the application does not supply it, the square
198+ root function must still compute square roots.)
199+
200+These requirements apply to the modified work as a whole. If
201+identifiable sections of that work are not derived from the Library,
202+and can be reasonably considered independent and separate works in
203+themselves, then this License, and its terms, do not apply to those
204+sections when you distribute them as separate works. But when you
205+distribute the same sections as part of a whole which is a work based
206+on the Library, the distribution of the whole must be on the terms of
207+this License, whose permissions for other licensees extend to the
208+entire whole, and thus to each and every part regardless of who wrote
209+it.
210+
211+Thus, it is not the intent of this section to claim rights or contest
212+your rights to work written entirely by you; rather, the intent is to
213+exercise the right to control the distribution of derivative or
214+collective works based on the Library.
215+
216+In addition, mere aggregation of another work not based on the Library
217+with the Library (or with a work based on the Library) on a volume of
218+a storage or distribution medium does not bring the other work under
219+the scope of this License.
220+
221+ 3. You may opt to apply the terms of the ordinary GNU General Public
222+License instead of this License to a given copy of the Library. To do
223+this, you must alter all the notices that refer to this License, so
224+that they refer to the ordinary GNU General Public License, version 2,
225+instead of to this License. (If a newer version than version 2 of the
226+ordinary GNU General Public License has appeared, then you can specify
227+that version instead if you wish.) Do not make any other change in
228+these notices.
229+
230+ Once this change is made in a given copy, it is irreversible for
231+that copy, so the ordinary GNU General Public License applies to all
232+subsequent copies and derivative works made from that copy.
233+
234+ This option is useful when you wish to copy part of the code of
235+the Library into a program that is not a library.
236+
237+ 4. You may copy and distribute the Library (or a portion or
238+derivative of it, under Section 2) in object code or executable form
239+under the terms of Sections 1 and 2 above provided that you accompany
240+it with the complete corresponding machine-readable source code, which
241+must be distributed under the terms of Sections 1 and 2 above on a
242+medium customarily used for software interchange.
243+
244+ If distribution of object code is made by offering access to copy
245+from a designated place, then offering equivalent access to copy the
246+source code from the same place satisfies the requirement to
247+distribute the source code, even though third parties are not
248+compelled to copy the source along with the object code.
249+
250+ 5. A program that contains no derivative of any portion of the
251+Library, but is designed to work with the Library by being compiled or
252+linked with it, is called a "work that uses the Library". Such a
253+work, in isolation, is not a derivative work of the Library, and
254+therefore falls outside the scope of this License.
255+
256+ However, linking a "work that uses the Library" with the Library
257+creates an executable that is a derivative of the Library (because it
258+contains portions of the Library), rather than a "work that uses the
259+library". The executable is therefore covered by this License.
260+Section 6 states terms for distribution of such executables.
261+
262+ When a "work that uses the Library" uses material from a header file
263+that is part of the Library, the object code for the work may be a
264+derivative work of the Library even though the source code is not.
265+Whether this is true is especially significant if the work can be
266+linked without the Library, or if the work is itself a library. The
267+threshold for this to be true is not precisely defined by law.
268+
269+ If such an object file uses only numerical parameters, data
270+structure layouts and accessors, and small macros and small inline
271+functions (ten lines or less in length), then the use of the object
272+file is unrestricted, regardless of whether it is legally a derivative
273+work. (Executables containing this object code plus portions of the
274+Library will still fall under Section 6.)
275+
276+ Otherwise, if the work is a derivative of the Library, you may
277+distribute the object code for the work under the terms of Section 6.
278+Any executables containing that work also fall under Section 6,
279+whether or not they are linked directly with the Library itself.
280+
281+ 6. As an exception to the Sections above, you may also combine or
282+link a "work that uses the Library" with the Library to produce a
283+work containing portions of the Library, and distribute that work
284+under terms of your choice, provided that the terms permit
285+modification of the work for the customer's own use and reverse
286+engineering for debugging such modifications.
287+
288+ You must give prominent notice with each copy of the work that the
289+Library is used in it and that the Library and its use are covered by
290+this License. You must supply a copy of this License. If the work
291+during execution displays copyright notices, you must include the
292+copyright notice for the Library among them, as well as a reference
293+directing the user to the copy of this License. Also, you must do one
294+of these things:
295+
296+ a) Accompany the work with the complete corresponding
297+ machine-readable source code for the Library including whatever
298+ changes were used in the work (which must be distributed under
299+ Sections 1 and 2 above); and, if the work is an executable linked
300+ with the Library, with the complete machine-readable "work that
301+ uses the Library", as object code and/or source code, so that the
302+ user can modify the Library and then relink to produce a modified
303+ executable containing the modified Library. (It is understood
304+ that the user who changes the contents of definitions files in the
305+ Library will not necessarily be able to recompile the application
306+ to use the modified definitions.)
307+
308+ b) Use a suitable shared library mechanism for linking with the
309+ Library. A suitable mechanism is one that (1) uses at run time a
310+ copy of the library already present on the user's computer system,
311+ rather than copying library functions into the executable, and (2)
312+ will operate properly with a modified version of the library, if
313+ the user installs one, as long as the modified version is
314+ interface-compatible with the version that the work was made with.
315+
316+ c) Accompany the work with a written offer, valid for at
317+ least three years, to give the same user the materials
318+ specified in Subsection 6a, above, for a charge no more
319+ than the cost of performing this distribution.
320+
321+ d) If distribution of the work is made by offering access to copy
322+ from a designated place, offer equivalent access to copy the above
323+ specified materials from the same place.
324+
325+ e) Verify that the user has already received a copy of these
326+ materials or that you have already sent this user a copy.
327+
328+ For an executable, the required form of the "work that uses the
329+Library" must include any data and utility programs needed for
330+reproducing the executable from it. However, as a special exception,
331+the materials to be distributed need not include anything that is
332+normally distributed (in either source or binary form) with the major
333+components (compiler, kernel, and so on) of the operating system on
334+which the executable runs, unless that component itself accompanies
335+the executable.
336+
337+ It may happen that this requirement contradicts the license
338+restrictions of other proprietary libraries that do not normally
339+accompany the operating system. Such a contradiction means you cannot
340+use both them and the Library together in an executable that you
341+distribute.
342+
343+ 7. You may place library facilities that are a work based on the
344+Library side-by-side in a single library together with other library
345+facilities not covered by this License, and distribute such a combined
346+library, provided that the separate distribution of the work based on
347+the Library and of the other library facilities is otherwise
348+permitted, and provided that you do these two things:
349+
350+ a) Accompany the combined library with a copy of the same work
351+ based on the Library, uncombined with any other library
352+ facilities. This must be distributed under the terms of the
353+ Sections above.
354+
355+ b) Give prominent notice with the combined library of the fact
356+ that part of it is a work based on the Library, and explaining
357+ where to find the accompanying uncombined form of the same work.
358+
359+ 8. You may not copy, modify, sublicense, link with, or distribute
360+the Library except as expressly provided under this License. Any
361+attempt otherwise to copy, modify, sublicense, link with, or
362+distribute the Library is void, and will automatically terminate your
363+rights under this License. However, parties who have received copies,
364+or rights, from you under this License will not have their licenses
365+terminated so long as such parties remain in full compliance.
366+
367+ 9. You are not required to accept this License, since you have not
368+signed it. However, nothing else grants you permission to modify or
369+distribute the Library or its derivative works. These actions are
370+prohibited by law if you do not accept this License. Therefore, by
371+modifying or distributing the Library (or any work based on the
372+Library), you indicate your acceptance of this License to do so, and
373+all its terms and conditions for copying, distributing or modifying
374+the Library or works based on it.
375+
376+ 10. Each time you redistribute the Library (or any work based on the
377+Library), the recipient automatically receives a license from the
378+original licensor to copy, distribute, link with or modify the Library
379+subject to these terms and conditions. You may not impose any further
380+restrictions on the recipients' exercise of the rights granted herein.
381+You are not responsible for enforcing compliance by third parties with
382+this License.
383+
384+ 11. If, as a consequence of a court judgment or allegation of patent
385+infringement or for any other reason (not limited to patent issues),
386+conditions are imposed on you (whether by court order, agreement or
387+otherwise) that contradict the conditions of this License, they do not
388+excuse you from the conditions of this License. If you cannot
389+distribute so as to satisfy simultaneously your obligations under this
390+License and any other pertinent obligations, then as a consequence you
391+may not distribute the Library at all. For example, if a patent
392+license would not permit royalty-free redistribution of the Library by
393+all those who receive copies directly or indirectly through you, then
394+the only way you could satisfy both it and this License would be to
395+refrain entirely from distribution of the Library.
396+
397+If any portion of this section is held invalid or unenforceable under any
398+particular circumstance, the balance of the section is intended to apply,
399+and the section as a whole is intended to apply in other circumstances.
400+
401+It is not the purpose of this section to induce you to infringe any
402+patents or other property right claims or to contest validity of any
403+such claims; this section has the sole purpose of protecting the
404+integrity of the free software distribution system which is
405+implemented by public license practices. Many people have made
406+generous contributions to the wide range of software distributed
407+through that system in reliance on consistent application of that
408+system; it is up to the author/donor to decide if he or she is willing
409+to distribute software through any other system and a licensee cannot
410+impose that choice.
411+
412+This section is intended to make thoroughly clear what is believed to
413+be a consequence of the rest of this License.
414+
415+ 12. If the distribution and/or use of the Library is restricted in
416+certain countries either by patents or by copyrighted interfaces, the
417+original copyright holder who places the Library under this License may add
418+an explicit geographical distribution limitation excluding those countries,
419+so that distribution is permitted only in or among countries not thus
420+excluded. In such case, this License incorporates the limitation as if
421+written in the body of this License.
422+
423+ 13. The Free Software Foundation may publish revised and/or new
424+versions of the Lesser General Public License from time to time.
425+Such new versions will be similar in spirit to the present version,
426+but may differ in detail to address new problems or concerns.
427+
428+Each version is given a distinguishing version number. If the Library
429+specifies a version number of this License which applies to it and
430+"any later version", you have the option of following the terms and
431+conditions either of that version or of any later version published by
432+the Free Software Foundation. If the Library does not specify a
433+license version number, you may choose any version ever published by
434+the Free Software Foundation.
435+
436+ 14. If you wish to incorporate parts of the Library into other free
437+programs whose distribution conditions are incompatible with these,
438+write to the author to ask for permission. For software which is
439+copyrighted by the Free Software Foundation, write to the Free
440+Software Foundation; we sometimes make exceptions for this. Our
441+decision will be guided by the two goals of preserving the free status
442+of all derivatives of our free software and of promoting the sharing
443+and reuse of software generally.
444+
445+ NO WARRANTY
446+
447+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
448+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
449+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
450+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
451+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
452+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
453+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
454+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
455+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
456+
457+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
458+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
459+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
460+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
461+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
462+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
463+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
464+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
465+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
466+DAMAGES.
467+
468+ END OF TERMS AND CONDITIONS
469+
470+ How to Apply These Terms to Your New Libraries
471+
472+ If you develop a new library, and you want it to be of the greatest
473+possible use to the public, we recommend making it free software that
474+everyone can redistribute and change. You can do so by permitting
475+redistribution under these terms (or, alternatively, under the terms of the
476+ordinary General Public License).
477+
478+ To apply these terms, attach the following notices to the library. It is
479+safest to attach them to the start of each source file to most effectively
480+convey the exclusion of warranty; and each file should have at least the
481+"copyright" line and a pointer to where the full notice is found.
482+
483+ <one line to give the library's name and a brief idea of what it does.>
484+ Copyright (C) <year> <name of author>
485+
486+ This library is free software; you can redistribute it and/or
487+ modify it under the terms of the GNU Lesser General Public
488+ License as published by the Free Software Foundation; either
489+ version 2.1 of the License, or (at your option) any later version.
490+
491+ This library is distributed in the hope that it will be useful,
492+ but WITHOUT ANY WARRANTY; without even the implied warranty of
493+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
494+ Lesser General Public License for more details.
495+
496+ You should have received a copy of the GNU Lesser General Public
497+ License along with this library; if not, write to the Free Software
498+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
499+
500+Also add information on how to contact you by electronic and paper mail.
501+
502+You should also get your employer (if you work as a programmer) or your
503+school, if any, to sign a "copyright disclaimer" for the library, if
504+necessary. Here is a sample; alter the names:
505+
506+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
507+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
508+
509+ <signature of Ty Coon>, 1 April 1990
510+ Ty Coon, President of Vice
511+
512+That's all there is to it!
513+
514+
Components/Carousel.qml+2
@@ -24,6 +24,8 @@ import "carousel.js" as CarouselJS
24Item {
24Item {
25 id: carousel
25 id: carousel
26
26
27+ clip: true // Don't leak horizontally to other dashes
28+
27 /// The component to be used as delegate. This component has to be derived from BaseCarouselDelegate
29 /// The component to be used as delegate. This component has to be derived from BaseCarouselDelegate
28 property Component itemComponent
30 property Component itemComponent
29 /// Model for the Carousel, which has to be a model usable by a ListView
31 /// Model for the Carousel, which has to be a model usable by a ListView
Components/DragHandle.qmlnew file+212
@@ -0,0 +1,212 @@
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+ // Disable gesture detection by default when hinting is used.
52+ // It doesn't make sense to have both.
53+ distanceThreshold: hintDisplacement > 0 ? 0 : units.gu(1.5)
54+
55+ property bool stretch: false
56+
57+ property alias autoCompleteDragThreshold: dragEvaluator.dragThreshold
58+
59+ // How far you can drag
60+ property real maxTotalDragDistance: {
61+ if (stretch) {
62+ 0; // not enough context information to set a sensible default
63+ } else {
64+ Direction.isHorizontal(direction) ? parent.width : parent.height;
65+ }
66+ }
67+
68+ property real hintDisplacement: 0
69+ SmoothedAnimation {
70+ id: hintingAnimation
71+ target: hintingAnimation
72+ property: "targetValue"
73+ duration: 150
74+ velocity: -1
75+ to: Direction.isPositive(direction) ? d.startValue + hintDisplacement
76+ : d.startValue - hintDisplacement
77+ property real targetValue
78+ onTargetValueChanged: {
79+ if (!running) {
80+ return;
81+ }
82+
83+ if (Direction.isPositive(direction)) {
84+ if (parent[d.targetProp] < targetValue) {
85+ parent[d.targetProp] = targetValue;
86+ }
87+ } else {
88+ if (parent[d.targetProp] > targetValue) {
89+ parent[d.targetProp] = targetValue;
90+ }
91+ }
92+ }
93+ }
94+
95+ // Private stuff
96+ QtObject {
97+ id: d
98+ property var previousStatus: undefined
99+ property real startValue
100+ property real minValue: Direction.isPositive(direction) ? startValue
101+ : startValue - maxTotalDragDistance
102+ property real maxValue: Direction.isPositive(direction) ? startValue + maxTotalDragDistance
103+ : startValue
104+
105+ property var dragParent: dragArea.parent
106+
107+ // The property of DragHandle's parent that will be modified
108+ property string targetProp: {
109+ if (stretch) {
110+ Direction.isHorizontal(direction) ? "width" : "height";
111+ } else {
112+ Direction.isHorizontal(direction) ? "x" : "y";
113+ }
114+ }
115+
116+ function limitMovement(step) {
117+ var targetValue = MathLocal.clamp(dragParent[targetProp] + step, minValue, maxValue);
118+ var step = targetValue - dragParent[targetProp];
119+
120+ if (hintDisplacement == 0) {
121+ return step;
122+ }
123+
124+ // we should not go behind hintingAnimation's current value
125+ if (Direction.isPositive(direction)) {
126+ if (dragParent[targetProp] + step < hintingAnimation.targetValue) {
127+ step = hintingAnimation.targetValue - dragParent[targetProp];
128+ }
129+ } else {
130+ if (dragParent[targetProp] + step > hintingAnimation.targetValue) {
131+ step = hintingAnimation.targetValue - dragParent[targetProp];
132+ }
133+ }
134+
135+ return step;
136+ }
137+
138+ function onFinishedRecognizedGesture() {
139+ if (dragEvaluator.shouldAutoComplete()) {
140+ completeDrag();
141+ } else {
142+ rollbackDrag();
143+ }
144+ }
145+
146+ function completeDrag() {
147+ if (dragParent.shown) {
148+ dragParent.hide();
149+ } else {
150+ dragParent.show();
151+ }
152+ }
153+
154+ function rollbackDrag() {
155+ if (dragParent.shown) {
156+ dragParent.show();
157+ } else {
158+ dragParent.hide();
159+ }
160+ }
161+ }
162+
163+ property alias edgeDragEvaluator: dragEvaluator
164+
165+ EdgeDragEvaluator {
166+ objectName: "edgeDragEvaluator"
167+ id: dragEvaluator
168+ trackedPosition: sceneDistance
169+ maxDragDistance: maxTotalDragDistance
170+ direction: dragArea.direction
171+ }
172+
173+ onDistanceChanged: {
174+ if (status === DirectionalDragArea.Recognized) {
175+ // don't go the whole distance in order to smooth out the movement
176+ var step = distance * 0.3;
177+
178+ step = d.limitMovement(step);
179+
180+ parent[d.targetProp] += step;
181+ }
182+ }
183+
184+ onDraggingChanged: {
185+ if (dragging) {
186+ if (hintDisplacement > 0) {
187+ hintingAnimation.targetValue = d.startValue;
188+ hintingAnimation.start();
189+ }
190+ } else {
191+ hintingAnimation.stop();
192+ }
193+ }
194+
195+ onStatusChanged: {
196+ if (status === DirectionalDragArea.WaitingForTouch) {
197+ if (d.previousStatus === DirectionalDragArea.Recognized) {
198+ d.onFinishedRecognizedGesture();
199+ }
200+ d.startValue = parent[d.targetProp];
201+ }
202+
203+ if (d.previousStatus === DirectionalDragArea.WaitingForTouch ||
204+ d.previousStatus === undefined) {
205+ dragEvaluator.reset();
206+ d.startValue = parent[d.targetProp];
207+ }
208+
209+ d.previousStatus = status;
210+ }
211+
212+}
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 {
108
108
109 anchors.fill: parent
109 anchors.fill: parent
110 radius: "small"
110 radius: "small"
111− borderSource: ItemStyle.style.borderPressed
111+ borderSource: "radius_pressed.sci"
112 opacity: button.pressed ? 1.0 : 0.0
112 opacity: button.pressed ? 1.0 : 0.0
113 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
113 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
114 }
114 }
Components/IconUtil.js+5−5
@@ -26,17 +26,17 @@ function from_gicon(name) {
26 var base_icon_re = /'base-icon':.+?'(.+?)'/;
26 var base_icon_re = /'base-icon':.+?'(.+?)'/;
27 var base_icon = name.toString().match(base_icon_re);
27 var base_icon = name.toString().match(base_icon_re);
28 icon_name = base_icon[1];
28 icon_name = base_icon[1];
29− }
30− else {
29+ } else {
31 var themed_re = /^. GThemedIcon\s*([^\s]+)\s*/;
30 var themed_re = /^. GThemedIcon\s*([^\s]+)\s*/;
32 var themed = name.match(themed_re);
31 var themed = name.match(themed_re);
33 if (themed) {
32 if (themed) {
34 return "image://gicon/" + themed[1];
33 return "image://gicon/" + themed[1];
35 }
34 }
36 }
35 }
37− var remote_re = /^http/;
36+ var name_re = /^[a-z0-9\._-]+$/;
38− if (remote_re.test(icon_name)) {
37+ if (name_re.test(icon_name)) {
38+ return "image://gicon/" + icon_name;
39+ } else {
39 return icon_name;
40 return icon_name;
40 }
41 }
41− return "image://gicon/" + icon_name;
42}
42}
Components/ListItems/Base.qml+19−21
@@ -54,35 +54,33 @@ AbstractButton {
54 */
54 */
55 function __showDivider() {
55 function __showDivider() {
56 // if we're not in ListView, always show a thin dividing line at the bottom
56 // if we're not in ListView, always show a thin dividing line at the bottom
57− if (ListView.view !== null) {
57+ var model = null;
58−
58+ if (typeof ListViewWithPageHeader !== 'undefined') {
59− // if we're last item in ListView don't show divider
59+ if (typeof ListViewWithPageHeader.model !== 'undefined') {
60− if (index === ListView.view.model.count - 1) return false;
60+ model = ListViewWithPageHeader.model;
61+ }
62+ } else if (ListView.view !== null) {
63+ model = ListView.view.model;
61 }
64 }
65+ // if we're last item in ListView don't show divider
66+ if (model && index === model.count - 1) return false;
67+
62 return true;
68 return true;
63 }
69 }
64
70
65− property bool __clippingRequired: ListView.view !== null
71+ /* Relevant really only for ListViewWithPageHeader case: specify how many pixels we can overlap with the section header */
66− && ListView.view.section.labelPositioning & ViewSection.CurrentLabelAtStart
72+ readonly property int allowedOverlap: units.dp(1)
67−
68− property real __yPositionRelativeToListView: ListView.view ? y - ListView.view.contentY : y
69
73
70 property real __heightToClip: {
74 property real __heightToClip: {
71 // Check this is in position where clipping is needed
75 // Check this is in position where clipping is needed
72− if (__clippingRequired && __yPositionRelativeToListView <= __sectionDelegateHeight
76+ if (typeof ListViewWithPageHeader !== 'undefined') {
73− && __yPositionRelativeToListView > -height) {
77+ if (typeof heightToClip !== 'undefined') {
74− return Math.min(__sectionDelegateHeight - __yPositionRelativeToListView, height);
78+ if (heightToClip >= allowedOverlap) {
75− } else {
79+ return heightToClip - allowedOverlap;
76− return 0;
80+ }
77− }
81+ }
78− }
79−
80− property int __sectionDelegateHeight: {
81− if (__clippingRequired && ListView.view.hasOwnProperty("__sectionDelegateHeight")) {
82− return ListView.view.__sectionDelegateHeight;
83− } else {
84− return 0;
85 }
82 }
83+ return 0;
86 }
84 }
87
85
88 /*!
86 /*!
Components/ListItems/Header.qml−6
@@ -25,12 +25,6 @@ Item {
25 */
25 */
26 property alias text: label.text
26 property alias text: label.text
27
27
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−
34 height: units.gu(4.5)
28 height: units.gu(4.5)
35
29
36 Item {
30 Item {
Components/ListItems/ThinDivider.qml−4
@@ -23,9 +23,5 @@ Image {
23 }
23 }
24 height: (visible) ? units.dp(2) : 0
24 height: (visible) ? units.dp(2) : 0
25
25
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−
30 source: "graphics/ListItemDividerHorizontal.png"
26 source: "graphics/ListItemDividerHorizontal.png"
31}
27}
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−4
@@ -147,9 +147,8 @@ Item {
147
147
148 hasClearButton: false
148 hasClearButton: false
149
149
150− primaryItem: Button {
150+ primaryItem: AbstractButton {
151 enabled: searchField.text != ""
151 enabled: searchField.text != ""
152− ItemStyle.class: "transparent-button"
153 onClicked: {
152 onClicked: {
154 if (searchField.text != "") {
153 if (searchField.text != "") {
155 searchHistory.addQuery(searchField.text)
154 searchHistory.addQuery(searchField.text)
@@ -271,8 +270,7 @@ Item {
271
270
272 // FIXME: this should go into the first item below, but enable: false
271 // FIXME: this should go into the first item below, but enable: false
273 // prevents mouse events propagation
272 // prevents mouse events propagation
274− Button {
273+ AbstractButton {
275− ItemStyle.class: "transparent-button"
276 anchors {
274 anchors {
277 top: parent.top
275 top: parent.top
278 right: parent.right
276 right: parent.right
Components/Stage.qml+8−10
@@ -416,12 +416,14 @@ Showable {
416 }
416 }
417 }
417 }
418
418
419− AxisVelocityCalculator {
419+ EdgeDragEvaluator {
420− id: dragVelocityCalculator
420+ id: dragEvaluator
421− trackedPosition: rightEdgeDraggingArea.distance
421+ trackedPosition: rightEdgeDraggingArea.touchX
422+ direction: rightEdgeDraggingArea.direction
423+ maxDragDistance: stage.width
422 }
424 }
423
425
424− DirectionalDragArea {
426+ EdgeDragArea {
425 id: rightEdgeDraggingArea
427 id: rightEdgeDraggingArea
426
428
427 enabled: {
429 enabled: {
@@ -439,10 +441,6 @@ Showable {
439 anchors.right: parent.right
441 anchors.right: parent.right
440
442
441 direction: Direction.Leftwards
443 direction: Direction.Leftwards
442− maxDeviation: units.gu(1)
443− wideningAngle: 20
444− distanceThreshold: units.gu(3)
445− minSpeed: units.gu(5)
446
444
447 onDistanceChanged: {
445 onDistanceChanged: {
448 if (status !== DirectionalDragArea.Recognized)
446 if (status !== DirectionalDragArea.Recognized)
@@ -478,7 +476,7 @@ Showable {
478 }
476 }
479
477
480 function onUndecided() {
478 function onUndecided() {
481− dragVelocityCalculator.reset()
479+ dragEvaluator.reset();
482
480
483 var nextApplication = null;
481 var nextApplication = null;
484 if (stage.applications.count > 1) {
482 if (stage.applications.count > 1) {
@@ -491,7 +489,7 @@ Showable {
491 }
489 }
492
490
493 function onGestureEnded() {
491 function onGestureEnded() {
494− if (stage.applications.count > 1 && dragVelocityCalculator.calculate() < 0) {
492+ if (stage.applications.count > 1 && dragEvaluator.shouldAutoComplete()) {
495 switchToApplicationAnimationController.completeToEndWithSignal();
493 switchToApplicationAnimationController.completeToEndWithSignal();
496 } else {
494 } else {
497 switchToApplicationAnimationController.completeToBeginningWithSignal();
495 switchToApplicationAnimationController.completeToBeginningWithSignal();
Components/Tile.qml+1−1
@@ -51,7 +51,7 @@ AbstractButton {
51
51
52 anchors.fill: icon
52 anchors.fill: icon
53 radius: "medium"
53 radius: "medium"
54− borderSource: ItemStyle.style.borderPressed
54+ borderSource: "radius_pressed.sci"
55 opacity: root.pressed ? 1.0 : 0.0
55 opacity: root.pressed ? 1.0 : 0.0
56 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
56 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
57 }
57 }
Components/UbuntuShapeForItem.qml+12−56
@@ -15,7 +15,7 @@
15 */
15 */
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18−import Ubuntu.Components 0.1 as Theming
18+import Ubuntu.Components 0.1
19
19
20/* FIXME: This component is duplicating the UbuntuShape from the SDK, but shapes more
20/* FIXME: This component is duplicating the UbuntuShape from the SDK, but shapes more
21 * general (Item-based) components. This ability should be incorporated into the SDK's
21 * general (Item-based) components. This ability should be incorporated into the SDK's
@@ -24,66 +24,22 @@ import Ubuntu.Components 0.1 as Theming
24 */
24 */
25
25
26Item {
26Item {
27− id: shape
27+ id: root
28
28
29− Theming.ItemStyle.class: "UbuntuShape-radius-" + radius
29+ property alias radius: shape.radius
30+ property alias image: source.sourceItem
30
31
31− property string radius: "small"
32+ ShaderEffectSource {
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
33+ id: source
59− visible: false
34+ width: 1
60− }
35+ height: 1
61− }
36+ hideSource: true
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− "
81 }
37 }
82
38
83− BorderImage {
39+ Shape {
84− id: border
40+ id: shape
41+ image: source
85
42
86 anchors.fill: parent
43 anchors.fill: parent
87− source: shape.borderSource
88 }
44 }
89}
45}
Components/WrongPasswordAnimation.qml+3−3
@@ -26,14 +26,14 @@ SequentialAnimation {
26 property: "anchors.horizontalCenterOffset"
26 property: "anchors.horizontalCenterOffset"
27 duration: 50
27 duration: 50
28 easing.type: Easing.InQuad
28 easing.type: Easing.InQuad
29− to: units.gu(2)
29+ to: units.gu(1)
30 }
30 }
31 NumberAnimation {
31 NumberAnimation {
32 target: root.target
32 target: root.target
33 property: "anchors.horizontalCenterOffset"
33 property: "anchors.horizontalCenterOffset"
34 duration: 100
34 duration: 100
35 easing.type: Easing.InOutQuad
35 easing.type: Easing.InOutQuad
36− to: -units.gu(2)
36+ to: -units.gu(1)
37 }
37 }
38 NumberAnimation {
38 NumberAnimation {
39 target: root.target
39 target: root.target
@@ -41,6 +41,6 @@ SequentialAnimation {
41 properties: "anchors.horizontalCenterOffset"
41 properties: "anchors.horizontalCenterOffset"
42 to: 0
42 to: 0
43 duration: 400
43 duration: 400
44− easing.overshoot: units.gu(2)
44+ easing.overshoot: units.gu(1)
45 }
45 }
46}
46}
Components/graphics/icon_star_off@20.png

Binary file not shown.

Components/graphics/icon_star_on@20.png

Binary file not shown.

Components/graphics/non-selected@18.png

Binary file not shown.

Dash/Apps/ApplicationsFilterGrid.qml+3−2
@@ -17,11 +17,12 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import "../../Components"
18import "../../Components"
19import "../../Applications"
19import "../../Applications"
20+import "../../Components/IconUtil.js" as IconUtil
20
21
21FilterGrid {
22FilterGrid {
22 id: filterGrid
23 id: filterGrid
23
24
24− filter: true
25+ filter: false
25 expandable: false
26 expandable: false
26 minimumHorizontalSpacing: units.gu(0.5)
27 minimumHorizontalSpacing: units.gu(0.5)
27 maximumNumberOfColumns: 6
28 maximumNumberOfColumns: 6
@@ -50,7 +51,7 @@ FilterGrid {
50 text: model.column_5 ? model.column_5 : application.name // FIXME: this is temporary
51 text: model.column_5 ? model.column_5 : application.name // FIXME: this is temporary
51 imageWidth: units.gu(8)
52 imageWidth: units.gu(8)
52 imageHeight: units.gu(7.5)
53 imageHeight: units.gu(7.5)
53− source: icon.indexOf("/") == -1 ? "image://gicon/" + icon : icon
54+ source: IconUtil.from_gicon(icon)
54 onClicked: filterGrid.clicked(index, application.desktopFile);
55 onClicked: filterGrid.clicked(index, application.desktopFile);
55 }
56 }
56}
57}
Dash/Apps/RunningApplicationTile.qml+1−1
@@ -87,7 +87,7 @@ AbstractButton {
87
87
88 anchors.fill: shapedApplicationImage
88 anchors.fill: shapedApplicationImage
89 radius: "medium"
89 radius: "medium"
90− borderSource: ItemStyle.style.borderPressed
90+ borderSource: "radius_pressed.sci"
91 opacity: root.pressed ? 1.0 : 0.0
91 opacity: root.pressed ? 1.0 : 0.0
92 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
92 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
93 }
93 }
Dash/Apps/graphics/close_btn@9.png

Binary file not shown.

Dash/DashApps.qml+2−3
@@ -99,7 +99,7 @@ ScopeView {
99 When using Loader to load external QML file in the list deelgate, the ListView has
99 When using Loader to load external QML file in the list deelgate, the ListView has
100 a bug where it can position the delegate content to overlap the section header
100 a bug where it can position the delegate content to overlap the section header
101 of the ListView - a workaround is to use sourceComponent of Loader instead */
101 of the ListView - a workaround is to use sourceComponent of Loader instead */
102− Component { id: runningApplicationsGrid; RunningApplicationsGrid {} }
102+ Component { id: runningApplicationsGrid; RunningApplicationsGrid { clip: true } }
103 Component {
103 Component {
104 id: applicationsFilterGrid;
104 id: applicationsFilterGrid;
105 ApplicationsFilterGrid {
105 ApplicationsFilterGrid {
@@ -112,7 +112,7 @@ ScopeView {
112 "ApplicationsFilterGrid": applicationsFilterGrid,
112 "ApplicationsFilterGrid": applicationsFilterGrid,
113 }
113 }
114
114
115− ListViewWithPageHeader {
115+ ScopeListView {
116 id: categoryView
116 id: categoryView
117 anchors.fill: parent
117 anchors.fill: parent
118 model: SortFilterProxyModel {
118 model: SortFilterProxyModel {
@@ -150,7 +150,6 @@ ScopeView {
150 item.model = categoryModels[modelName]
150 item.model = categoryModels[modelName]
151 }
151 }
152 }
152 }
153− asynchronous: true
154 }
153 }
155
154
156 ListView.onRemove: SequentialAnimation {
155 ListView.onRemove: SequentialAnimation {
Dash/DashHome.qml+1−2
@@ -130,7 +130,7 @@ ScopeView {
130 "VideosGrid": videosGrid,
130 "VideosGrid": videosGrid,
131 }
131 }
132
132
133− ListViewWithPageHeader {
133+ ScopeListView {
134 id: listView
134 id: listView
135 anchors.fill: parent
135 anchors.fill: parent
136 model: categoryListModel
136 model: categoryListModel
@@ -161,7 +161,6 @@ ScopeView {
161 item.clicked.connect(playVideo);
161 item.clicked.connect(playVideo);
162 }
162 }
163 }
163 }
164− asynchronous: true
165 }
164 }
166 }
165 }
167
166
Dash/DashMusic.qml+1−2
@@ -64,7 +64,7 @@ ScopeView {
64 }
64 }
65 }
65 }
66
66
67− ListViewWithPageHeader {
67+ ScopeListView {
68 id: categoryView
68 id: categoryView
69 anchors.fill: parent
69 anchors.fill: parent
70 model: scopeView.categories
70 model: scopeView.categories
@@ -84,7 +84,6 @@ ScopeView {
84 onLoaded: {
84 onLoaded: {
85 item.model = results
85 item.model = results
86 }
86 }
87− asynchronous: true
88 }
87 }
89 }
88 }
90
89
Dash/DashVideos.qml+2−3
@@ -97,11 +97,11 @@ ScopeView {
97 }
97 }
98 }
98 }
99
99
100− ListViewWithPageHeader {
100+ ScopeListView {
101 id: categoryView
101 id: categoryView
102 anchors.fill: parent
102 anchors.fill: parent
103 model: scopeView.categories
103 model: scopeView.categories
104− clipListView: !previewLoader.onScreen
104+ forceNoClip: previewLoader.onScreen
105
105
106 onAtYEndChanged: if (atYEnd) endReached()
106 onAtYEndChanged: if (atYEnd) endReached()
107 onMovingChanged: if (moving && atYEnd) endReached()
107 onMovingChanged: if (moving && atYEnd) endReached()
@@ -119,7 +119,6 @@ ScopeView {
119 onLoaded: {
119 onLoaded: {
120 item.model = results
120 item.model = results
121 }
121 }
122− asynchronous: true
123
122
124 Connections {
123 Connections {
125 target: loader.item
124 target: loader.item
Dash/GenericScopeView.qml+1−1
@@ -43,7 +43,7 @@ ScopeView {
43 }
43 }
44 }
44 }
45
45
46− ListViewWithPageHeader {
46+ ScopeListView {
47 id: categoryView
47 id: categoryView
48 anchors.fill: parent
48 anchors.fill: parent
49 model: scopeView.categories
49 model: scopeView.categories
Dash/Music/AlbumTile.qml+1−1
@@ -45,7 +45,7 @@ AbstractButton {
45
45
46 anchors.fill: icon
46 anchors.fill: icon
47 radius: "medium"
47 radius: "medium"
48− borderSource: ItemStyle.style.borderPressed
48+ borderSource: "radius_pressed.sci"
49 opacity: root.pressed ? 1.0 : 0.0
49 opacity: root.pressed ? 1.0 : 0.0
50 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
50 Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
51 }
51 }
tests/qmltests/plugins/Dee/DeeVariantText.qml → Dash/ScopeListView.qmlrenamed+4−3
@@ -15,8 +15,9 @@
15 */
15 */
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18+import ListViewWithPageHeader 0.1
18
19
19−Item {
20+ListViewWithPageHeader {
20− property variant value
21+ maximumFlickVelocity: height * 10
21− property string text
22+ flickDeceleration: height * 2
22}
23}
Dash/graphics/icon_clear@20.png

Binary file not shown.

Dash/graphics/icon_listview_clear@20.png

Binary file not shown.

Dash/graphics/icon_search_active@20.png

Binary file not shown.

Dash/graphics/icon_search_inactive@20.png

Binary file not shown.

Dash/graphics/phone/home.png

Binary file not shown.

Dash/graphics/phone/music.png

Binary file not shown.

Dash/graphics/phone/screenshots/angrybirds@12.png

Binary file not shown.

Dash/graphics/phone/screenshots/browser@12.png

Binary file not shown.

Dash/graphics/phone/screenshots/camera@12.png

Binary file not shown.

Dash/graphics/phone/screenshots/facebook@12.png

Binary file not shown.

Dash/graphics/phone/screenshots/gallery@12.png

Binary file not shown.

Dash/graphics/phone/screenshots/map@12.png

Binary file not shown.

Dash/graphics/phone/screenshots/music@12.png

Binary file not shown.

Dash/graphics/phone/screenshots/phone@12.png

Binary file not shown.

Dash/graphics/phone/screenshots/settings@12.png

Binary file not shown.

Dash/graphics/phone/screenshots/twitter@12.png

Binary file not shown.

Dash/graphics/phone/videos.png

Binary file not shown.

Dash/graphics/play_button@18.png

Binary file not shown.

Dash/graphics/play_button_active@18.png

Binary file not shown.

Dash/graphics/play_button_active_big@20.png

Binary file not shown.

Dash/graphics/play_button_big@20.png

Binary file not shown.

Dash/graphics/tablet/apps.png

Binary file not shown.

Dash/graphics/tablet/home.png

Binary file not shown.

Dash/graphics/tablet/icon_close_preview@20.png

Binary file not shown.

Dash/graphics/tablet/music.png

Binary file not shown.

Dash/graphics/tablet/people.png

Binary file not shown.

Dash/graphics/tablet/videos.png

Binary file not shown.

Greeter/Greeter.qml+28−2
@@ -16,14 +16,23 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
19import LightDM 0.1 as LightDM
20import LightDM 0.1 as LightDM
20import "../Components"
21import "../Components"
22+import "../Components/Math.js" as MathLocal
21
23
22Showable {
24Showable {
23 id: greeter
25 id: greeter
24 enabled: shown
26 enabled: shown
25 created: greeterContentLoader.status == Loader.Ready && greeterContentLoader.item.ready
27 created: greeterContentLoader.status == Loader.Ready && greeterContentLoader.item.ready
26
28
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
27 property alias model: greeterContentLoader.model
36 property alias model: greeterContentLoader.model
28 property bool locked: shown && multiUser && !greeterContentLoader.promptless
37 property bool locked: shown && multiUser && !greeterContentLoader.promptless
29
38
@@ -39,7 +48,7 @@ Showable {
39 signal unlocked(int uid)
48 signal unlocked(int uid)
40
49
41 onRightTeaserPressedChanged: {
50 onRightTeaserPressedChanged: {
42− if (rightTeaserPressed) {
51+ if (rightTeaserPressed && !locked) {
43 teasingTimer.start();
52 teasingTimer.start();
44 }
53 }
45 }
54 }
@@ -72,7 +81,7 @@ Showable {
72 states: [
81 states: [
73 State {
82 State {
74 name: "teasing"
83 name: "teasing"
75− when: greeter.rightTeaserPressed || teasingTimer.running
84+ when: teasingTimer.running
76 PropertyChanges {
85 PropertyChanges {
77 target: greeter
86 target: greeter
78 x: -units.gu(2)
87 x: -units.gu(2)
@@ -91,4 +100,21 @@ Showable {
91 }
100 }
92 }
101 }
93 ]
102 ]
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+ }
94}
120}
Greeter/GreeterContent.qml+4−1
@@ -80,7 +80,9 @@ MouseArea {
80 source: greeter.narrowMode ? "" : "LoginList.qml"
80 source: greeter.narrowMode ? "" : "LoginList.qml"
81
81
82 onLoaded: {
82 onLoaded: {
83− item.currentIndex = greeterContentLoader.currentIndex
83+ item.currentIndex = greeterContentLoader.currentIndex;
84+ selected(item.currentIndex);
85+ item.resetAuthentication();
84 }
86 }
85
87
86 Binding {
88 Binding {
@@ -122,6 +124,7 @@ MouseArea {
122
124
123 function updateUsername(uid) {
125 function updateUsername(uid) {
124 greeterContentLoader.infographicModel.username = greeterContentLoader.model.data(uid, LightDM.UserRoles.NameRole)
126 greeterContentLoader.infographicModel.username = greeterContentLoader.model.data(uid, LightDM.UserRoles.NameRole)
127+ greeterContentLoader.infographicModel.readyForDataChangeSlot();
125 }
128 }
126
129
127 anchors {
130 anchors {
Greeter/Lockscreen.qml+7−1
@@ -41,7 +41,14 @@ Showable {
41 signal cancel()
41 signal cancel()
42 signal emergencyCall()
42 signal emergencyCall()
43
43
44+ onRequiredChanged: {
45+ if (required && pinPadLoader.item) {
46+ pinPadLoader.item.clear(false);
47+ }
48+ }
49+
44 function reset() {
50 function reset() {
51+ // This causes the loader below to destry and recreate the source
45 pinPadLoader.resetting = true;
52 pinPadLoader.resetting = true;
46 pinPadLoader.resetting = false;
53 pinPadLoader.resetting = false;
47 }
54 }
@@ -140,7 +147,6 @@ Showable {
140 }
147 }
141 if (LightDM.Greeter.authenticated) {
148 if (LightDM.Greeter.authenticated) {
142 root.unlocked();
149 root.unlocked();
143− pinPadLoader.item.clear(false);
144 } else {
150 } else {
145 pinPadLoader.item.clear(true);
151 pinPadLoader.item.clear(true);
146 }
152 }
Greeter/LoginList.qml−8
@@ -66,14 +66,6 @@ Item {
66
66
67 readonly property bool movingInternally: moveTimer.running || userList.moving
67 readonly property bool movingInternally: moveTimer.running || userList.moving
68
68
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−
77 onCurrentIndexChanged: {
69 onCurrentIndexChanged: {
78 if (LightDM.Greeter.authenticationUser != userList.model.data(currentIndex, LightDM.UserRoles.NameRole)) {
70 if (LightDM.Greeter.authenticationUser != userList.model.data(currentIndex, LightDM.UserRoles.NameRole)) {
79 root.resetAuthentication();
71 root.resetAuthentication();
Greeter/graphics/dot_empty.png

Binary file not shown.

Greeter/graphics/dot_filled.png

Binary file not shown.

Greeter/graphics/dot_pointer.png

Binary file not shown.

Greeter/graphics/infographic_circle.png

Binary file not shown.

Hud/SearchBar.qml−7
@@ -55,13 +55,6 @@ Item {
55 }
55 }
56 }
56 }
57
57
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−
65 Item {
58 Item {
66 id: primary
59 id: primary
67 height: searchBar.height
60 height: searchBar.height
Hud/ToolBarIcon.qml+1−3
@@ -17,9 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19
19
20−Button {
20+AbstractButton {
21− ItemStyle.class: "transparent-button"
22−
23 property alias source: image.source
21 property alias source: image.source
24
22
25 height: units.gu(4)
23 height: units.gu(4)
Hud/graphics/hud_bg@20.png

Binary file not shown.

Hud/graphics/hud_handlearrow@20.png

Binary file not shown.

Hud/graphics/hud_handlebar@20.png

Binary file not shown.

Hud/graphics/icon_clear@20.png

Binary file not shown.

Hud/graphics/icon_search@20.png

Binary file not shown.

LGPL_EXCEPTION.txtnew file+22
@@ -0,0 +1,22 @@
1+Digia Qt LGPL Exception version 1.1
2+
3+As an additional permission to the GNU Lesser General Public License version
4+2.1, the object code form of a "work that uses the Library" may incorporate
5+material from a header file that is part of the Library. You may distribute
6+such object code under terms of your choice, provided that:
7+ (i) the header files of the Library have not been modified; and
8+ (ii) the incorporated material is limited to numerical parameters, data
9+ structure layouts, accessors, macros, inline functions and
10+ templates; and
11+ (iii) you comply with the terms of Section 6 of the GNU Lesser General
12+ Public License version 2.1.
13+
14+Moreover, you may apply this exception to a modified version of the Library,
15+provided that such modification does not involve copying material from the
16+Library into the modified Library's header files unless such material is
17+limited to (i) numerical parameters; (ii) data structure layouts;
18+(iii) accessors; and (iv) small macros, templates and inline functions of
19+five lines or less in length.
20+
21+Furthermore, you are not required to apply this additional permission to a
22+modified version of the Library.
Launcher/Launcher.qml+9−17
@@ -25,7 +25,6 @@ Item {
25
25
26 property bool available: true // can be used to disable all interactions
26 property bool available: true // can be used to disable all interactions
27
27
28− property bool teasing: false
29 property int panelWidth: units.gu(8.5)
28 property int panelWidth: units.gu(8.5)
30 property int dragAreaWidth: units.gu(1)
29 property int dragAreaWidth: units.gu(1)
31 property real progress: dragArea.dragging && dragArea.touchX > panel.width ? dragArea.touchX : 0
30 property real progress: dragArea.dragging && dragArea.touchX > panel.width ? dragArea.touchX : 0
@@ -50,7 +49,7 @@ Item {
50 }
49 }
51
50
52 function hide() {
51 function hide() {
53− state = ""
52+ switchToNextState("")
54 }
53 }
55
54
56 function switchToNextState(state) {
55 function switchToNextState(state) {
@@ -58,8 +57,8 @@ Item {
58 animateTimer.start();
57 animateTimer.start();
59 }
58 }
60
59
61− onTeasingChanged: {
60+ function tease() {
62− if (teasing) {
61+ if (available) {
63 teaseTimer.start();
62 teaseTimer.start();
64 }
63 }
65 }
64 }
@@ -181,18 +180,11 @@ Item {
181 }
180 }
182 }
181 }
183
182
184− DirectionalDragArea {
183+ EdgeDragArea {
185 id: dragArea
184 id: dragArea
186
185
187 direction: Direction.Rightwards
186 direction: Direction.Rightwards
188
187
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−
196 enabled: root.available && root.state !== "visible"
188 enabled: root.available && root.state !== "visible"
197 width: root.dragAreaWidth
189 width: root.dragAreaWidth
198 height: root.height
190 height: root.height
@@ -215,11 +207,11 @@ Item {
215
207
216 onDraggingChanged: {
208 onDraggingChanged: {
217 if (!dragging) {
209 if (!dragging) {
218− if (distance > root.width / 2) {
210+ if (distance > panel.width / 2) {
219− root.dash()
220− root.switchToNextState("")
221− } else if (distance > panel.width/2) {
222 root.switchToNextState("visible")
211 root.switchToNextState("visible")
212+ if (distance > panel.width * 2) {
213+ root.dash()
214+ }
223 } else {
215 } else {
224 root.switchToNextState("")
216 root.switchToNextState("")
225 }
217 }
@@ -244,7 +236,7 @@ Item {
244 },
236 },
245 State {
237 State {
246 name: "teasing"
238 name: "teasing"
247− when: root.teasing || teaseTimer.running
239+ when: teaseTimer.running
248 PropertyChanges {
240 PropertyChanges {
249 target: panel
241 target: panel
250 x: -root.panelWidth + units.gu(2)
242 x: -root.panelWidth + units.gu(2)
Launcher/LauncherDelegate.qml+202−39
@@ -25,6 +25,8 @@ Item {
25 property real angle: 0
25 property real angle: 0
26 property bool highlighted: false
26 property bool highlighted: false
27 property real offset: 0
27 property real offset: 0
28+ property alias brightness: transformEffect.brightness
29+ property real itemOpacity: 1
28
30
29 property real maxAngle: 0
31 property real maxAngle: 0
30 property bool inverted: false
32 property bool inverted: false
@@ -32,74 +34,237 @@ Item {
32 readonly property int effectiveHeight: Math.cos(angle * Math.PI / 180) * height
34 readonly property int effectiveHeight: Math.cos(angle * Math.PI / 180) * height
33 readonly property real foldedHeight: Math.cos(maxAngle * Math.PI / 180) * height
35 readonly property real foldedHeight: Math.cos(maxAngle * Math.PI / 180) * height
34
36
35− property int itemsBeforeThis: 0
36− property int itemsAfterThis: 0
37−
38 property bool dragging:false
37 property bool dragging:false
39
38
40 signal clicked()
39 signal clicked()
41 signal longtap()
40 signal longtap()
42 signal released()
41 signal released()
43
42
44− UbuntuShape {
43+ Item {
45 id: iconItem
44 id: iconItem
46− color: Qt.rgba(0, 0, 1, 0.5)
47 width: parent.width
45 width: parent.width
48 height: parent.height
46 height: parent.height
49 anchors.centerIn: parent
47 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− }
63
48
64− MouseArea {
49+ UbuntuShape {
65− id: mouseArea
50+ id: iconShape
66 anchors.fill: parent
51 anchors.fill: parent
67− onClicked: root.clicked()
52+ anchors.margins: units.gu(0.5)
68− onCanceled: root.released()
53+ radius: "medium"
69− preventStealing: false
70
54
71− onPressAndHold: {
55+ image: Image {
72− root.state = "moving"
56+ id: iconImage
57+ sourceSize.width: iconShape.width
58+ sourceSize.height: iconShape.height
59+ source: "../graphics/applicationIcons/" + root.iconName + ".png"
73 }
60 }
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+ }
74− onReleased: {
73+ onReleased: {
75− root.state = "docked"
74+ root.state = "docked"
75+ }
76 }
76 }
77 }
77 }
78−
79 BorderImage {
78 BorderImage {
80 id: overlayHighlight
79 id: overlayHighlight
81 anchors.centerIn: iconItem
80 anchors.centerIn: iconItem
82 rotation: inverted ? 180 : 0
81 rotation: inverted ? 180 : 0
83− source: root.highlighted || mouseArea.pressed ? "graphics/selected.sci" : "graphics/non-selected.sci"
82+ source: isSelected ? "graphics/selected.sci" : "graphics/non-selected.sci"
84− width: iconItem.width + units.gu(1.5)
83+ width: root.width + units.gu(0.5)
85 height: width
84 height: width
85+ property bool isSelected: root.highlighted || mouseArea.pressed
86+ onIsSelectedChanged: shaderEffectSource.scheduleUpdate();
86 }
87 }
87 }
88 }
88
89
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+
89 states: [
171 states: [
90 State {
172 State {
91 name: "docked"
173 name: "docked"
92 PropertyChanges {
174 PropertyChanges {
93 target: root
175 target: root
94− offset: if (launcherFlickable.contentY > itemsBeforeThis * (foldedHeight + launcherColumn.spacing*2)) {
176+
95− return launcherFlickable.contentY - (index * (foldedHeight + launcherColumn.spacing*2));
177+ // This is the offset that keeps the items inside the panel
96− } else if (y + height - launcherFlickable.contentY > launcherFlickable.height - (itemsAfterThis*(foldedHeight - launcherColumn.spacing))) {
178+ offset: {
97− return launcherFlickable.height - (y+height) + launcherFlickable.contentY - (itemsAfterThis*(foldedHeight - launcherColumn.spacing));
179+ // First/last items are special
98− } else {
180+ if (index == 0 || index == priv.listView.count-1) {
99− return 0;
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
100 }
207 }
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+ }
102
210
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+ }
103 }
268 }
104 },
269 },
105
270
@@ -121,7 +286,5 @@ Item {
121 drag.target: root
286 drag.target: root
122 }
287 }
123 }
288 }
124−
125 ]
289 ]
126−
127}
290}
Launcher/LauncherPanel.qml+106−52
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Unity 0.1
19import Unity 0.1
20+import "../Components/ListItems"
20
21
21Item {
22Item {
22 id: root
23 id: root
@@ -26,7 +27,7 @@ Item {
26 property var model
27 property var model
27 property bool inverted: true
28 property bool inverted: true
28 property bool dragging: false
29 property bool dragging: false
29− property bool moving: launcherFlickable.moving
30+ property bool moving: launcherListView.moving || launcherListView.flicking
30 property int dragPosition: 0
31 property int dragPosition: 0
31 property int highlightIndex: -1
32 property int highlightIndex: -1
32
33
@@ -34,23 +35,23 @@ Item {
34 signal dashItemSelected(int index)
35 signal dashItemSelected(int index)
35
36
36 onDragPositionChanged: {
37 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
38
39
39− var hiddenContentHeight = launcherFlickable.contentHeight - launcherFlickable.height
40+ var hiddenContentHeight = launcherListView.contentHeight - launcherListView.height
40 // Shortening scrollable height because the first/last item needs to be fully expanded before reaching the top/bottom
41 // 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
42 // As we shortened the scrollableHeight, lets move everything down by the itemSize
43 // 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
44 var newContentY = shortenedEffectiveDragPosition * hiddenContentHeight / scrollableHeight
45 var newContentY = shortenedEffectiveDragPosition * hiddenContentHeight / scrollableHeight
45
46
46 // limit top/bottom to prevent overshooting
47 // 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));
48
49
49 // Now calculate the current index:
50 // Now calculate the current index:
50 // > the current mouse position + the hidden/scolled content on top is the mouse position in the averall view
51 // > the current mouse position + the hidden/scolled content on top is the mouse position in the averall view
51 // > adjust that removing all the margins
52 // > adjust that removing all the margins
52 // > divide by itemSize to get index
53 // > 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)
54 }
55 }
55
56
56 BorderImage {
57 BorderImage {
@@ -61,58 +62,111 @@ Item {
61
62
62 Column {
63 Column {
63 id: mainColumn
64 id: mainColumn
65+ anchors {
64− anchors.fill: parent
66+ fill: parent
65− anchors.margins: units.gu(1)
67+ topMargin: units.gu(0.5)
68+ bottomMargin: units.gu(1)
69+ leftMargin: units.gu(0.5)
70+ rightMargin: units.gu(0.5)
71+ }
66− spacing: units.gu(1)
72+ spacing: units.gu(0.5)
67
73
68− LauncherDelegate {
74+ MouseArea {
69 id: dashItem
75 id: dashItem
70− objectName: "dashItem"
76+ width: parent.width
71− width: launcherFlickable.itemSize
77+ height: units.gu(6.5)
72− height: launcherFlickable.itemSize
73− anchors.horizontalCenter: parent.horizontalCenter
74− iconName: "dash"
75 onClicked: root.dashItemSelected(0)
78 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+ }
76 }
87 }
77− Flickable {
88+ ThinDivider {
78− id: launcherFlickable
89+ anchors {
90+ left: parent.left
91+ right: parent.right
92+ margins: -mainColumn.anchors.leftMargin
93+ }
94+ rotation: root.rotation
95+ }
96+
97+ Item {
79 anchors.left: parent.left
98 anchors.left: parent.left
80 anchors.right: parent.right
99 anchors.right: parent.right
81− height: parent.height - dashItem.height - parent.spacing
100+ height: parent.height - dashItem.height - parent.spacing*2
82− contentHeight: launcherColumn.height
101+ ListView {
83−
102+ id: launcherListView
84− property int itemSize: width
103+ anchors.fill: parent
85−
104+ anchors.topMargin: -itemSize
86− Column {
105+ anchors.bottomMargin: -itemSize
87− id: launcherColumn
106+ topMargin: itemSize
88− width: parent.width
107+ bottomMargin: itemSize
89− spacing: units.gu(1)
108+ height: parent.height - dashItem.height - parent.spacing*2
90− anchors.horizontalCenter: parent.horizontalCenter
109+ model: root.model
91−
110+ cacheBuffer: itemSize * 3
92− Repeater {
111+ snapMode: ListView.SnapToItem
93− id: iconRepeater
112+ highlightRangeMode: ListView.ApplyRange
94− model: root.model
113+ preferredHighlightBegin: (height - itemSize) / 2
95−
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+
96− LauncherDelegate {
129+ delegate: LauncherDelegate {
97− id: launcherDelegate
130+ id: launcherDelegate
98− objectName: "launcherDelegate" + index
131+ objectName: "launcherDelegate" + index
99− width: launcherFlickable.itemSize
132+ width: launcherListView.itemSize
100− height: launcherFlickable.itemSize
133+ height: launcherListView.itemSize
101− iconName: model.icon
134+ iconName: model.icon
102− inverted: root.inverted
135+ inverted: root.inverted
103− highlighted: root.dragging && index === root.highlightIndex
136+ highlighted: root.dragging && index === root.highlightIndex
104− z: -Math.abs(offset)
137+ z: -Math.abs(offset)
105− state: "docked"
138+ state: "docked"
106−
107− maxAngle: 60
139+ maxAngle: 60
108−
140+
109− itemsBeforeThis: index
110− itemsAfterThis: iconRepeater.count - (index+1)
111−
112− onClicked: {
141+ onClicked: {
113− root.applicationSelected(launcherModel.get(index).desktopFile);
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
114− }
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
115 }
166 }
167+ height: launcherListView.itemSize
168+ enabled: launcherListView.contentHeight - launcherListView.height - launcherListView.contentY > -launcherListView.bottomMargin
169+ onClicked: launcherListView.flick(0, -units.gu(40))
116 }
170 }
117 }
171 }
118 }
172 }
Launcher/graphics/highlight@18.png

Binary file not shown.

Launcher/graphics/home@18.pngnew file

Binary file not shown.

Launcher/graphics/non-selected@18.png

Binary file not shown.

Launcher/graphics/selected@18.png

Binary file not shown.

Launcher/graphics/triangle@18.png

Binary file not shown.

Notifications/Notification.qml+109−12
@@ -30,10 +30,25 @@ UbuntuShape {
30 property var type
30 property var type
31 property var notification
31 property var notification
32
32
33+ objectName: "background"
33− implicitHeight: childrenRect.height
34+ implicitHeight: contentColumn.height + contentColumn.spacing * 2
34 color: Qt.rgba(0, 0, 0, 0.85)
35 color: Qt.rgba(0, 0, 0, 0.85)
35 opacity: 0
36 opacity: 0
36
37
38+ clip: true
39+
40+ Behavior on implicitHeight {
41+ id: heightBehavior
42+
43+ enabled: false
44+ UbuntuNumberAnimation {
45+ duration: UbuntuAnimation.SnapDuration
46+ }
47+ }
48+
49+ // delay enabling height behavior until the add transition is complete
50+ onOpacityChanged: if (opacity == 1) heightBehavior.enabled = true
51+
37 MouseArea {
52 MouseArea {
38 id: interactiveArea
53 id: interactiveArea
39
54
@@ -52,7 +67,7 @@ UbuntuShape {
52 top: parent.top
67 top: parent.top
53 margins: spacing
68 margins: spacing
54 }
69 }
55− height: childrenRect.height + spacing
70+
56 spacing: units.gu(1)
71 spacing: units.gu(1)
57
72
58 Row {
73 Row {
@@ -125,30 +140,112 @@ UbuntuShape {
125 }
140 }
126 }
141 }
127
142
128− Row {
143+ Item {
129 id: buttonRow
144 id: buttonRow
130
145
131 objectName: "buttonRow"
146 objectName: "buttonRow"
132− spacing: contentColumn.spacing
147+ anchors {
133− layoutDirection: Qt.RightToLeft
148+ left: parent.left
149+ right: parent.right
150+ }
134 visible: notification.type == Notification.SnapDecision
151 visible: notification.type == Notification.SnapDecision
152+ height: units.gu(4)
153+
154+ property real buttonWidth: (width - contentColumn.spacing) / 2
155+ property bool expanded
156+
157+ Button {
158+ id: leftButton
159+
160+ objectName: "button1"
161+ width: parent.expanded ? parent.width : parent.buttonWidth
162+ anchors {
163+ top: parent.top
164+ bottom: parent.bottom
165+ }
166+ text: notification.type == Notification.SnapDecision && actionRepeater.count >= 2 ? actionRepeater.itemAt(1).actionLabel : ""
167+ color: "#cdcdcb"
168+ onClicked: {
169+ if (actionRepeater.count > 2) {
170+ buttonRow.expanded = !buttonRow.expanded
171+ } else {
172+ notification.notification.invokeAction(actionRepeater.itemAt(1).actionId)
173+ }
174+ }
175+
176+ Behavior on width {
177+ UbuntuNumberAnimation {
178+ duration: UbuntuAnimation.SnapDuration
179+ }
180+ }
181+ }
182+
183+ Button {
184+ id: rightButton
185+
186+ objectName: "button0"
187+ anchors {
188+ left: leftButton.right
189+ leftMargin: contentColumn.spacing
190+ right: parent.right
191+ }
192+ text: notification.type == Notification.SnapDecision && actionRepeater.count >= 1 ? actionRepeater.itemAt(0).actionLabel : ""
193+ anchors {
194+ top: parent.top
195+ bottom: parent.bottom
196+ }
197+ color: "#d85317"
198+ visible: width > 0
199+ onClicked: notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
200+ }
201+ }
202+
203+ Column {
204+ objectName: "buttonColumn"
205+ spacing: contentColumn.spacing
135 anchors {
206 anchors {
136 left: parent.left
207 left: parent.left
137 right: parent.right
208 right: parent.right
138 }
209 }
139
210
211+ // calculate initial position before Column takes over
212+ y: buttonRow.y + buttonRow.height + contentColumn.spacing
213+
214+ visible: notification.type == Notification.SnapDecision
215+ height: buttonRow.expanded ? implicitHeight : 0
216+
140 Repeater {
217 Repeater {
141 id: actionRepeater
218 id: actionRepeater
219+
142 model: notification.actions
220 model: notification.actions
221+ delegate: Loader {
222+ id: loader
143
223
144− Button {
145− objectName: "button" + index
146− color: Positioner.isFirstItem ? "#d85317" : "#cdcdcb"
147− width: (buttonRow.width - buttonRow.spacing) / 2
148− height: units.gu(4)
149− text: label
150 property string actionId: id
224 property string actionId: id
225+ property string actionLabel: label
226+
227+ anchors {
228+ left: parent.left
229+ right: parent.right
230+ }
231+
232+ Component {
233+ id: actionButton
234+
235+ Button {
236+ objectName: "button" + index
237+ anchors {
238+ left: parent.left
239+ right: parent.right
240+ }
241+
242+ text: loader.actionLabel
243+ height: units.gu(4)
244+ color: "#cdcdcb"
151− onClicked: notification.notification.invokeAction(id)
245+ onClicked: notification.notification.invokeAction(loader.actionId)
246+ }
247+ }
248+ sourceComponent: (index == 0 || index == 1) ? undefined : actionButton
152 }
249 }
153 }
250 }
154 }
251 }
Notifications/Notifications.qml+10−13
@@ -17,7 +17,6 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import "../Components"
19import "../Components"
20−import "timings.js" as Timings
21
20
22ListView {
21ListView {
23 id: notificationList
22 id: notificationList
@@ -40,40 +39,38 @@ ListView {
40 actions: model.actions
39 actions: model.actions
41 notificationId: model.id
40 notificationId: model.id
42 notification: notificationList.model.getRaw(notificationId)
41 notification: notificationList.model.getRaw(notificationId)
42+
43+ // make sure there's no opacity-difference between the several
44+ // elements in a notification
45+ layer.enabled: add.running || remove.running || populate.running
43 }
46 }
44
47
45 populate: Transition {
48 populate: Transition {
46− NumberAnimation {
49+ UbuntuNumberAnimation {
47 property: "opacity"
50 property: "opacity"
48 to: 1
51 to: 1
49− duration: Timings.snapBeat
52+ duration: UbuntuAnimation.SnapDuration
50− easing.type: Timings.easing
51 }
53 }
52 }
54 }
53
55
54 add: Transition {
56 add: Transition {
55− NumberAnimation {
57+ UbuntuNumberAnimation {
56 property: "opacity"
58 property: "opacity"
57 to: 1
59 to: 1
58− duration: Timings.snapBeat
60+ duration: UbuntuAnimation.SnapDuration
59− easing.type: Timings.easing
60 }
61 }
61 }
62 }
62
63
63 remove: Transition {
64 remove: Transition {
64− NumberAnimation {
65+ UbuntuNumberAnimation {
65 property: "opacity"
66 property: "opacity"
66 to: 0
67 to: 0
67− duration: Timings.fastBeat
68− easing.type: Timings.easing
69 }
68 }
70 }
69 }
71
70
72 displaced: Transition {
71 displaced: Transition {
73− NumberAnimation {
72+ UbuntuNumberAnimation {
74 properties: "x,y"
73 properties: "x,y"
75− duration: Timings.fastBeat
76− easing.type: Timings.easing
77 }
74 }
78 }
75 }
79}
76}
Panel/Indicators.qml+111−27
@@ -16,32 +16,49 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
19import Ubuntu.ChewieUI 0.1 as ChewieUI
20import Ubuntu.ChewieUI 0.1 as ChewieUI
20
21
21import "../Components"
22import "../Components"
23+import "../Components/ListItems"
22import "../Components/Math.js" as MathLocal
24import "../Components/Math.js" as MathLocal
23
25
24Showable {
26Showable {
25 id: indicators
27 id: indicators
26
28
27− property int progress: panelHeight
29+ property int referenceOpenedHeight: units.gu(71)
28− property int openedHeight: units.gu(71)
30+ property real openedHeight: pinnedMode ? referenceOpenedHeight - panelHeight
31+ : referenceOpenedHeight
29 property int panelHeight: units.gu(3)
32 property int panelHeight: units.gu(3)
30 property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
33 property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
31
34
32 property int hintValue
35 property int hintValue
33− readonly property int lockThreshold: shell.height/2
36+ readonly property int lockThreshold: referenceOpenedHeight / 2
34− property bool fullyOpened: revealer ? progress == revealer.openedValue : false
37+ property bool fullyOpened: height == openedHeight
35− property bool partiallyOpened: revealer ? progress > revealer.closedValue && progress < revealer.openedValue : false
38+ property bool partiallyOpened: height > panelHeight && !fullyOpened
39+
40+ // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
41+ // use its own values. Need to ask design about this.
42+ showAnimation: StandardAnimation {
43+ property: "height"
44+ duration: 350
45+ to: openedHeight
46+ easing.type: Easing.OutCubic
47+ }
36
48
37− property Revealer revealer: null
49+ hideAnimation: StandardAnimation {
50+ property: "height"
51+ duration: 350
52+ to: panelHeight
53+ easing.type: Easing.OutCubic
54+ }
38
55
39− height: menuContent.height + handle.height + menuContent.y
56+ height: panelHeight
40
57
41− onProgressChanged: {
58+ onHeightChanged: {
42− // need to use handle.get_height(). As the handle height depends on progress changes (but this is called first!)
59+ // need to use handle.get_height(). As the handle height depends on indicators.height changes (but this is called first!)
43− var contentProgress = progress - handle.get_height()
60+ var contentProgress = indicators.height - handle.get_height()
44− if (!showAnimation.running && !hideAnimation.running && !revealer.hintingAnimation.running) {
61+ if (!showAnimation.running && !hideAnimation.running) {
45 if (contentProgress <= hintValue && indicators.state == "reveal") {
62 if (contentProgress <= hintValue && indicators.state == "reveal") {
46 indicators.state = "hint"
63 indicators.state = "hint"
47 menuContent.hideAll()
64 menuContent.hideAll()
@@ -66,12 +83,6 @@ Showable {
66 }
83 }
67 }
84 }
68
85
69− function handlePress() {
70− menuContent.hideAll()
71− menuContent.activateContent()
72− indicators.state = "hint"
73− }
74−
75 function openOverview() {
86 function openOverview() {
76 indicatorRow.currentItem = null
87 indicatorRow.currentItem = null
77 menuContent.showOverview()
88 menuContent.showOverview()
@@ -91,7 +102,9 @@ Showable {
91 If bar is dragged down a distance greater than or equal to lockThreshold, this is 1.
102 If bar is dragged down a distance greater than or equal to lockThreshold, this is 1.
92 Otherwise it contains the bar's location as a fraction of the distance between hintValue (is 0) and lockThreshold (is 1).
103 Otherwise it contains the bar's location as a fraction of the distance between hintValue (is 0) and lockThreshold (is 1).
93 */
104 */
105+ var verticalProgress =
94− var verticalProgress = MathLocal.clamp((indicators.progress - handle.height - hintValue) / (lockThreshold - hintValue), 0, 1)
106+ MathLocal.clamp((indicators.height - handle.height - hintValue) /
107+ (lockThreshold - hintValue), 0, 1)
95
108
96 /*
109 /*
97 Percentage of an indicator icon's width the user's press can stray horizontally from the
110 Percentage of an indicator icon's width the user's press can stray horizontally from the
@@ -139,6 +152,17 @@ Showable {
139 }
152 }
140 }
153 }
141
154
155+ VerticalThinDivider {
156+ anchors {
157+ top: indicators.top
158+ topMargin: panelHeight
159+ bottom: handle.bottom
160+ right: indicators.left
161+ }
162+ width: units.dp(2)
163+ source: "graphics/VerticalDivider.png"
164+ }
165+
142 MenuContent {
166 MenuContent {
143 id: menuContent
167 id: menuContent
144 objectName: "menuContent"
168 objectName: "menuContent"
@@ -147,8 +171,8 @@ Showable {
147 left: parent.left
171 left: parent.left
148 right: parent.right
172 right: parent.right
149 top: indicatorRow.bottom
173 top: indicatorRow.bottom
174+ bottom: parent.bottom
150 }
175 }
151− height: progress - y
152 indicatorsModel: indicatorsModel
176 indicatorsModel: indicatorsModel
153 animate: false
177 animate: false
154 clip: indicators.partiallyOpened
178 clip: indicators.partiallyOpened
@@ -187,7 +211,7 @@ Showable {
187 clip: height < handleImage.height
211 clip: height < handleImage.height
188
212
189 function get_height() {
213 function get_height() {
190− return Math.max(Math.min(handleImage.height, progress - handleImage.height), 0)
214+ return Math.max(Math.min(handleImage.height, indicators.height - handleImage.height), 0)
191 }
215 }
192
216
193 BorderImage {
217 BorderImage {
@@ -205,6 +229,29 @@ Showable {
205 }
229 }
206 }
230 }
207
231
232+ PanelSeparatorLine {
233+ id: indicatorsSeparatorLine
234+ visible: true
235+ anchors {
236+ top: handle.bottom
237+ left: indicators.left
238+ right: indicators.right
239+ }
240+ }
241+
242+ BorderImage {
243+ id: dropShadow
244+ anchors {
245+ top: indicators.top
246+ bottom: indicatorsSeparatorLine.bottom
247+ left: indicators.left
248+ right: indicators.right
249+ margins: -units.gu(1)
250+ }
251+ visible: indicators.height > panelHeight
252+ source: "graphics/rectangular_dropshadow.sci"
253+ }
254+
208 PanelBackground {
255 PanelBackground {
209 anchors.fill: indicatorRow
256 anchors.fill: indicatorRow
210 }
257 }
@@ -249,7 +296,7 @@ Showable {
249 openOverview()
296 openOverview()
250 }
297 }
251 else {
298 else {
252− indicators.calculateCurrentItem(revealer.lateralPosition, false)
299+ indicators.calculateCurrentItem(dragHandle.touchX, false)
253 menuContent.showMenu()
300 menuContent.showMenu()
254 }
301 }
255 indicators.state = "commit"
302 indicators.state = "commit"
@@ -258,10 +305,10 @@ Showable {
258 }
305 }
259
306
260 Connections {
307 Connections {
261− target: revealer
308+ target: dragHandle
262− onLateralPositionChanged: {
309+ onTouchXChanged: {
263− var buffer = revealer.dragging ? true : false
310+ var buffer = dragHandle.dragging ? true : false
264− indicators.calculateCurrentItem(revealer.lateralPosition, buffer)
311+ indicators.calculateCurrentItem(dragHandle.touchX, buffer)
265 }
312 }
266 }
313 }
267
314
@@ -277,6 +324,43 @@ Showable {
277 state = last_state;
324 state = last_state;
278 }
325 }
279
326
327+ property var dragHandle: showDragHandle.dragging ? showDragHandle : hideDragHandle
328+ DragHandle {
329+ id: showDragHandle
330+ anchors.bottom: parent.bottom
331+ // go beyond parent so that it stays reachable, at the top of the screen.
332+ anchors.bottomMargin: pinnedMode ? 0 : -panelHeight
333+ anchors.left: parent.left
334+ anchors.right: parent.right
335+ height: panelHeight
336+ direction: Direction.Downwards
337+ enabled: !indicators.shown
338+ hintDisplacement: pinnedMode ? indicators.hintValue : 0
339+ autoCompleteDragThreshold: maxTotalDragDistance / 2
340+ stretch: true
341+ maxTotalDragDistance: openedHeight - handle.height
342+ distanceThreshold: pinnedMode ? 0 : units.gu(3)
343+
344+ onStatusChanged: {
345+ if (status === DirectionalDragArea.Recognized) {
346+ menuContent.hideAll()
347+ menuContent.activateContent()
348+ }
349+ }
350+ }
351+ DragHandle {
352+ id: hideDragHandle
353+ anchors.fill: handle
354+ height: panelHeight
355+ direction: Direction.Upwards
356+ enabled: indicators.shown
357+ hintDisplacement: units.gu(2)
358+ autoCompleteDragThreshold: maxTotalDragDistance / 6
359+ stretch: true
360+ maxTotalDragDistance: referenceOpenedHeight - 2*panelHeight
361+ distanceThreshold: 0
362+ }
363+
280 property list<State> offScreenModeStates: [
364 property list<State> offScreenModeStates: [
281 State {
365 State {
282 name: "initial"
366 name: "initial"
@@ -289,7 +373,7 @@ Showable {
289 name: "reveal"
373 name: "reveal"
290 extend: "hint"
374 extend: "hint"
291 PropertyChanges { target: menuContent; animate: true }
375 PropertyChanges { target: menuContent; animate: true }
292− StateChangeScript { script: calculateCurrentItem(revealer.lateralPosition, false); }
376+ StateChangeScript { script: calculateCurrentItem(dragHandle.touchX, false); }
293 },
377 },
294 State {
378 State {
295 name: "locked"
379 name: "locked"
@@ -311,7 +395,7 @@ Showable {
311 State {
395 State {
312 name: "reveal"
396 name: "reveal"
313 PropertyChanges { target: menuContent; animate: true }
397 PropertyChanges { target: menuContent; animate: true }
314− StateChangeScript { script: calculateCurrentItem(revealer.lateralPosition, false); }
398+ StateChangeScript { script: calculateCurrentItem(dragHandle.touchX, false); }
315 },
399 },
316 State {
400 State {
317 name: "locked"
401 name: "locked"
Panel/MenuContent.qml+1−1
@@ -98,7 +98,7 @@ Rectangle {
98 visible: content.__shown
98 visible: content.__shown
99 onVisibleChanged: {
99 onVisibleChanged: {
100 // Reset the indicator states
100 // Reset the indicator states
101− if (!visible && item) {
101+ if (!visible && item && item["reset"]) {
102 item.reset()
102 item.reset()
103 }
103 }
104 }
104 }
Panel/Panel.qml+3−74
@@ -17,7 +17,6 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import "../Components"
19import "../Components"
20−import "../Components/ListItems"
21
20
22Item {
21Item {
23 id: root
22 id: root
@@ -75,29 +74,6 @@ Item {
75 }
74 }
76 }
75 }
77
76
78− BorderImage {
79− id: dropShadow
80− anchors {
81− top: indicatorsMenu.top
82− bottom: indicatorsSeparatorLine.bottom
83− left: indicatorsMenu.left
84− right: indicatorsMenu.right
85− margins: -units.gu(1)
86− }
87− visible: indicatorsMenu.progress != indicatorRevealer.closedValue
88− source: "graphics/rectangular_dropshadow.sci"
89− }
90−
91− VerticalThinDivider {
92− anchors {
93− top: leftSeparatorLine.top
94− bottom: indicatorsSeparatorLine.top
95− right: indicatorsMenu.left
96− }
97− width: units.dp(2)
98− source: "graphics/VerticalDivider.png"
99− }
100−
101 Indicators {
77 Indicators {
102 id: indicatorsMenu
78 id: indicatorsMenu
103
79
@@ -105,58 +81,13 @@ Item {
105 y: 0
81 y: 0
106 width: root.indicatorsMenuWidth
82 width: root.indicatorsMenuWidth
107 shown: false
83 shown: false
108− revealer: indicatorRevealer
84+ hintValue: __panelMinusSeparatorLineHeight * 3
109− hintValue: indicatorRevealer.hintDisplacement
110 panelHeight: __panelMinusSeparatorLineHeight
85 panelHeight: __panelMinusSeparatorLineHeight
111− showAnimation: StandardAnimation { property: "progress"; duration: 350; to: indicatorRevealer.openedValue; easing.type: Easing.OutCubic }
112− hideAnimation: StandardAnimation { property: "progress"; duration: 350; to: indicatorRevealer.closedValue; easing.type: Easing.OutCubic }
113− openedHeight: parent.height
86+ referenceOpenedHeight: parent.height
114
87
115 pinnedMode: !fullscreenMode
88 pinnedMode: !fullscreenMode
116
89
117− property real unitProgress: (indicatorRevealer.closedValue - progress) / (indicatorRevealer.closedValue - indicatorRevealer.openedValue)
90+ property real unitProgress: (height - panelHeight) / (openedHeight - panelHeight)
118− }
119−
120− PanelSeparatorLine {
121− id: indicatorsSeparatorLine
122− anchors {
123− top: indicatorsMenu.bottom
124− left: indicatorsMenu.left
125− right: parent.right
126− }
127− }
128−
129− Revealer {
130− id: indicatorRevealer
131− objectName: "indicatorRevealer"
132−
133− width: root.indicatorsMenuWidth
134− anchors {
135− top: parent.top
136− bottom: parent.bottom
137− right: parent.right
138− }
139− target: indicatorsMenu
140− handleSize: __panelMinusSeparatorLineHeight
141− closedValue: __panelMinusSeparatorLineHeight
142− dragVelocityThreshold: units.dp(1)
143− boundProperty: "progress"
144− hintDisplacement: __panelMinusSeparatorLineHeight * 3
145− openOnPress: !fullscreenMode
146− orientation: Qt.Vertical
147−
148− onOpenClicked: {
149− indicatorsMenu.openOverview();
150− indicatorsMenu.show();
151− }
152− onCloseClicked: indicatorsMenu.hide();
153−
154− onOpenPressed: indicatorsMenu.handlePress()
155−
156− function dragToValue(dragPosition) {
157− var offset = target.shown ? 0 : -hintDisplacement + handleSize;
158− return dragPosition + offset;
159− }
160 }
91 }
161
92
162 SearchIndicator {
93 SearchIndicator {
@@ -192,13 +123,11 @@ Item {
192 name: "in" //fully opaque and visible at top edge of screen
123 name: "in" //fully opaque and visible at top edge of screen
193 when: !fullscreenMode
124 when: !fullscreenMode
194 PropertyChanges { target: panelBackground; y: 0 }
125 PropertyChanges { target: panelBackground; y: 0 }
195− PropertyChanges { target: indicatorRevealer; openedValue: indicatorsMenu.openedHeight - panelHeight }
196 },
126 },
197 State {
127 State {
198 name: "out" //pushed off screen
128 name: "out" //pushed off screen
199 when: fullscreenMode
129 when: fullscreenMode
200 PropertyChanges { target: panelBackground; y: -panelHeight }
130 PropertyChanges { target: panelBackground; y: -panelHeight }
201− PropertyChanges { target: indicatorRevealer; openedValue: indicatorsMenu.openedHeight }
202 }
131 }
203 ]
132 ]
204}
133}
Panel/graphics/Battery@18.png

Binary file not shown.

Panel/graphics/Bluetooth@18.png

Binary file not shown.

Panel/graphics/Clock@18.png

Binary file not shown.

Panel/graphics/Location@18.png

Binary file not shown.

Panel/graphics/Messages@18.png

Binary file not shown.

Panel/graphics/Network@18.png

Binary file not shown.

Panel/graphics/Sound@18.png

Binary file not shown.

Panel/graphics/Sync@18.png

Binary file not shown.

Panel/graphics/System@18.png

Binary file not shown.

Panel/graphics/Time@18.png

Binary file not shown.

Panel/graphics/VerticalDivider@18.png

Binary file not shown.

Panel/graphics/rectangular_dropshadow@30.png

Binary file not shown.

Panel/graphics/search@12.png

Binary file not shown.

Shell.qml+46−41
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Application 0.1
18import Ubuntu.Application 0.1
19import Ubuntu.Components 0.1
19import Ubuntu.Components 0.1
20+import Ubuntu.Gestures 0.1
20import LightDM 0.1 as LightDM
21import LightDM 0.1 as LightDM
21import "Dash"
22import "Dash"
22import "Greeter"
23import "Greeter"
@@ -167,7 +168,14 @@ FocusScope {
167
168
168 contentScale: 1.0 - 0.2 * disappearingAnimationProgress
169 contentScale: 1.0 - 0.2 * disappearingAnimationProgress
169 opacity: 1.0 - disappearingAnimationProgress
170 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+
171 // FIXME: only necessary because stagesRevealer.animatedProgress and
179 // FIXME: only necessary because stagesRevealer.animatedProgress and
172 // greeterRevealer.animatedProgress are not animated
180 // greeterRevealer.animatedProgress are not animated
173 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
181 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
@@ -176,25 +184,29 @@ FocusScope {
176
184
177
185
178 Item {
186 Item {
187+ id: stagesOuterContainer
179
188
180 width: parent.width
189 width: parent.width
181 height: parent.height
190 height: parent.height
182 x: launcher.progress
191 x: launcher.progress
183 Behavior on x {SmoothedAnimation{velocity: 600}}
192 Behavior on x {SmoothedAnimation{velocity: 600}}
184
193
194+ property real showProgress:
195+ MathLocal.clamp(1 - (x + stages.x) / shell.width, 0, 1)
185
196
186 Showable {
197 Showable {
187 id: stages
198 id: stages
188
199
200+ x: width
201+
189− property bool fullyShown: shown && stages[stagesRevealer.boundProperty] == stagesRevealer.openedValue
202+ property bool fullyShown: shown && x == 0 && parent.x == 0
190− && parent.x == 0
191− property bool fullyHidden: !shown && stages[stagesRevealer.boundProperty] == stagesRevealer.closedValue
203+ property bool fullyHidden: !shown && x == width
192 available: !greeter.shown
204 available: !greeter.shown
193 hides: [launcher, panel.indicators]
205 hides: [launcher, panel.indicators]
194 shown: false
206 shown: false
195 opacity: 1.0
207 opacity: 1.0
196− showAnimation: StandardAnimation { property: "x"; duration: 350; to: stagesRevealer.openedValue; easing.type: Easing.OutCubic }
208+ showAnimation: StandardAnimation { property: "x"; duration: 350; to: 0; easing.type: Easing.OutCubic }
197− hideAnimation: StandardAnimation { property: "x"; duration: 350; to: stagesRevealer.closedValue; easing.type: Easing.OutCubic }
209+ hideAnimation: StandardAnimation { property: "x"; duration: 350; to: width; easing.type: Easing.OutCubic }
198
210
199 width: parent.width
211 width: parent.width
200 height: parent.height
212 height: parent.height
@@ -325,24 +337,19 @@ FocusScope {
325 height: sideStage.height
337 height: sideStage.height
326 orientation: Qt.Horizontal
338 orientation: Qt.Horizontal
327 }
339 }
328− }
329− }
330
340
341+ DragHandle {
342+ id: stagesRevealer
343+
344+ anchors.top: parent.top
345+ anchors.bottom: parent.bottom
346+ anchors.right: parent.left
331
347
332− Revealer {
348+ width: shell.edgeSize
333− id: stagesRevealer
349+ direction: Direction.Leftwards
334−
335− property real animatedProgress: MathLocal.clamp((-dragPosition - launcher.progress) / closedValue, 0, 1)
336− enabled: mainStage.applications.count > 0 || sideStage.applications.count > 0
350+ enabled: mainStage.applications.count > 0 || sideStage.applications.count > 0
337− direction: Qt.RightToLeft
351+ }
338− openedValue: 0
352+ }
339− hintDisplacement: units.gu(3)
340− handleSize: shell.edgeSize
341− closedValue: width
342− target: stages
343− width: stages.width
344− height: stages.height
345− orientation: Qt.Horizontal
346 }
353 }
347
354
348 Lockscreen {
355 Lockscreen {
@@ -379,7 +386,7 @@ FocusScope {
379 } else {
386 } else {
380 lockscreen.alphaNumeric = true
387 lockscreen.alphaNumeric = true
381 }
388 }
382− lockscreen.placeholderText = i18n.tr("Please enter %1:").arg(text);
389+ lockscreen.placeholderText = i18n.tr("Please enter %1").arg(text);
383 lockscreen.show();
390 lockscreen.show();
384 }
391 }
385 }
392 }
@@ -391,12 +398,13 @@ FocusScope {
391 available: true
398 available: true
392 hides: [launcher, panel.indicators, hud]
399 hides: [launcher, panel.indicators, hud]
393 shown: true
400 shown: true
394− showAnimation: StandardAnimation { property: "x"; to: greeterRevealer.openedValue }
401+
395− hideAnimation: StandardAnimation { property: "x"; to: greeterRevealer.closedValue }
396 y: panel.panelHeight
402 y: panel.panelHeight
397 width: parent.width
403 width: parent.width
398 height: parent.height - panel.panelHeight
404 height: parent.height - panel.panelHeight
399
405
406+ dragHandleWidth: shell.edgeSize
407+
400 property var previousMainApp: null
408 property var previousMainApp: null
401 property var previousSideApp: null
409 property var previousSideApp: null
402
410
@@ -431,6 +439,12 @@ FocusScope {
431 var bgPath = greeter.model.data(uid, LightDM.UserRoles.BackgroundPathRole)
439 var bgPath = greeter.model.data(uid, LightDM.UserRoles.BackgroundPathRole)
432 shell.background = bgPath ? bgPath : default_background
440 shell.background = bgPath ? bgPath : default_background
433 }
441 }
442+
443+ onLeftTeaserPressedChanged: {
444+ if (leftTeaserPressed) {
445+ launcher.tease();
446+ }
447+ }
434 }
448 }
435
449
436 InputFilterArea {
450 InputFilterArea {
@@ -438,19 +452,6 @@ FocusScope {
438 blockInput: greeter.shown || lockscreen.shown
452 blockInput: greeter.shown || lockscreen.shown
439 }
453 }
440
454
441− Revealer {
442− id: greeterRevealer
443−
444− property real animatedProgress: MathLocal.clamp(-dragPosition / closedValue, 0, 1)
445− target: greeter
446− width: greeter.width
447− height: greeter.height
448− handleSize: shell.edgeSize
449− orientation: Qt.Horizontal
450− visible: greeter.shown
451− enabled: !greeter.locked
452− }
453−
454 Item {
455 Item {
455 id: overlay
456 id: overlay
456
457
@@ -515,6 +516,8 @@ FocusScope {
515 theHud: hud
516 theHud: hud
516 anchors.fill: parent
517 anchors.fill: parent
517 enabled: !panel.indicators.shown
518 enabled: !panel.indicators.shown
519+ applicationIsOnForeground: applicationManager.mainStageFocusedApplication
520+ || applicationManager.sideStageFocusedApplication
518 }
521 }
519
522
520 InputFilterArea {
523 InputFilterArea {
@@ -535,7 +538,6 @@ FocusScope {
535 width: parent.width
538 width: parent.width
536 dragAreaWidth: shell.edgeSize
539 dragAreaWidth: shell.edgeSize
537 available: !greeter.locked
540 available: !greeter.locked
538− teasing: available && greeter.leftTeaserPressed
539 onDashItemSelected: {
541 onDashItemSelected: {
540 greeter.hide()
542 greeter.hide()
541 // Animate if moving between application and dash
543 // Animate if moving between application and dash
@@ -547,8 +549,11 @@ FocusScope {
547 stages.hide();
549 stages.hide();
548 }
550 }
549 onDash: {
551 onDash: {
552+ if (stages.shown) {
550− dash.setCurrentScope("applications.scope", true, false)
553+ dash.setCurrentScope("applications.scope", true, false)
551− stages.hide();
554+ stages.hide();
555+ launcher.hide();
556+ }
552 }
557 }
553 onLauncherApplicationSelected:{
558 onLauncherApplicationSelected:{
554 greeter.hide()
559 greeter.hide()
build+18−8
@@ -1,10 +1,9 @@
1#!/bin/sh
1#!/bin/sh
2
2
3−PACKAGE=unity8
4−UNITY_BUILD_DIR=$PWD/../unity_build/build
5SETUP=false
3SETUP=false
6CLEAN=false
4CLEAN=false
7NUM_JOBS=$(( `grep -c ^processor /proc/cpuinfo` + 1 ))
5NUM_JOBS=$(( `grep -c ^processor /proc/cpuinfo` + 1 ))
6+CODE_DIR=$( dirname `readlink -f $0` )
8
7
9usage() {
8usage() {
10 echo "usage: build [OPTIONS] [BUILD_TYPE]\n" >&2
9 echo "usage: build [OPTIONS] [BUILD_TYPE]\n" >&2
@@ -37,13 +36,26 @@ BUILD_TYPE="debug"
37[ $# -eq 1 ] && BUILD_TYPE="$1"
36[ $# -eq 1 ] && BUILD_TYPE="$1"
38
37
39install_dependencies() {
38install_dependencies() {
40− . /etc/lsb-release
41 [ -f /etc/apt/sources.list.d/phablet-team-desktop-deps-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:phablet-team/desktop-deps || exit 1
39 [ -f /etc/apt/sources.list.d/phablet-team-desktop-deps-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:phablet-team/desktop-deps || exit 1
42 [ -f /etc/apt/sources.list.d/canonical-qt5-edgers-qt5-proper-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:canonical-qt5-edgers/qt5-proper || exit 2;
40 [ -f /etc/apt/sources.list.d/canonical-qt5-edgers-qt5-proper-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:canonical-qt5-edgers/qt5-proper || exit 2;
43 [ -f /etc/apt/sources.list.d/ubuntu-sdk-team-ppa-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:ubuntu-sdk-team/ppa || exit 3
41 [ -f /etc/apt/sources.list.d/ubuntu-sdk-team-ppa-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:ubuntu-sdk-team/ppa || exit 3
44 sudo apt-get update || exit 4
42 sudo apt-get update || exit 4
45 echo "Installing Unity 8 dependencies.."
43 echo "Installing Unity 8 dependencies.."
46− sudo apt-get install qtdeclarative5-ubuntu-ui-toolkit-plugin qtdeclarative5-dee-plugin indicators-client indicators-client-plugin-* qtbase5-dev qtbase5-private-dev qtdeclarative5-dev qtdeclarative5-dev-tools qtdeclarative5-test-plugin libdee-qt5-dev libpulse-dev qtdeclarative5-xmllistmodel-plugin unity-lens-mock demo-assets ubuntu-mobile-icons || exit 5
44+ sudo apt-get install devscripts \
45+ equivs \
46+ qtdeclarative5-ubuntu-ui-toolkit-plugin \
47+ qtdeclarative5-dee-plugin \
48+ indicators-client \
49+ indicators-client-plugin-* \
50+ ubuntu-mobile-icons \
51+ unity-notifications-impl-1 \
52+ unity-scope-home \
53+ unity-lens-applications \
54+ || exit 5
55+}
56+
57+mk_build_deps() {
58+ [ ! -f unity8-build-deps*deb -o $CODE_DIR/debian/control -nt unity8-build-deps*deb ] && mk-build-deps --install --root-cmd sudo $CODE_DIR/debian/control
47}
59}
48
60
49if [ -f "/usr/bin/ninja" ] ; then
61if [ -f "/usr/bin/ninja" ] ; then
@@ -56,13 +68,11 @@ fi
56
68
57if $SETUP; then
69if $SETUP; then
58 install_dependencies
70 install_dependencies
59− ./build_unity --setup || exit 1$?
60− ./build_unity || exit 1$?
61else
71else
62 if $CLEAN; then rm -rf builddir; fi
72 if $CLEAN; then rm -rf builddir; fi
63 mkdir -p builddir
73 mkdir -p builddir
64 cd builddir
74 cd builddir
75+ mk_build_deps
65− PKG_CONFIG_PATH=$UNITY_BUILD_DIR/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .. ${GENERATOR} || exit 6
76+ cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE $CODE_DIR ${GENERATOR} || exit 6
66 ${BUILD_COMMAND} || exit 7
77 ${BUILD_COMMAND} || exit 7
67fi
78fi
68−
build_unitydeleted−158
@@ -1,158 +0,0 @@
1−#!/bin/bash
2−
3−TARGET_DIR=$PWD/../unity_build
4−BUILD_DIR=$TARGET_DIR/build
5−SETUP=false
6−UPDATE=false
7−CLEAN=false
8−NUM_JOBS=$(( `grep -c ^processor /proc/cpuinfo` + 1 ))
9−
10−# verified working revisions
11−LIBUNITY_REV=228
12−UNITY_REV=3343
13−HUD_REV=252
14−
15−usage() {
16− echo "usage: build_unity [OPTIONS]\n"
17− echo "Script to build Unity on Ubuntu 12.10.\n"
18− echo "OPTIONS:"
19− echo " -s, --setup Setup the build environment and branch Unity"
20− echo " -u, --update Update Unity's source code"
21− echo " -c, --clean Clean build trees before building"
22− exit 1
23−}
24−
25−set -- `getopt -n$0 -u -a --longoptions="setup,update,clean,help" "such" "$@"`
26−
27−# FIXME: giving incorrect arguments does not call usage and exit
28−while [ $# -gt 0 ]
29−do
30− case "$1" in
31− -s|--setup) SETUP=true;;
32− -u|--update) UPDATE=true;;
33− -c|--clean) CLEAN=true;;
34− -h|--help) usage;;
35− --) shift;break;;
36− esac
37− shift
38−done
39−
40−install_utils() {
41− echo "Installing build utilities.."
42− sudo apt-get install devscripts equivs || exit 4
43−}
44−
45−mk_build_deps() {
46− echo "Installing build dependencies.."
47− cd $TARGET_DIR
48− sudo mk-build-deps -B -i $TARGET_DIR/libunity/debian/control || exit 5
49− sudo mk-build-deps -B -i $TARGET_DIR/unity/debian/control || exit 6
50− sudo mk-build-deps -B -i $TARGET_DIR/hud/debian/control || exit 7
51−}
52−
53−branch_libunity() {
54− echo "Branching libunity.."
55− bzr branch lp:libunity $TARGET_DIR/libunity || exit 8
56−}
57−
58−branch_unity() {
59− echo "Branching Unity.."
60− bzr branch lp:unity $TARGET_DIR/unity || exit 9
61−}
62−
63−branch_hud() {
64− echo "Branching hud.."
65− bzr branch lp:hud $TARGET_DIR/hud || exit 10
66−}
67−
68−update_unity() {
69− echo "Updating Unity.."
70− bzr pull -d $TARGET_DIR/unity || exit 11
71−}
72−
73−update_libunity() {
74− echo "Updating libunity.."
75− bzr pull -d $TARGET_DIR/libunity || exit 12
76−}
77−
78−update_hud() {
79− echo "Updating hud"
80− bzr pull -d $TARGET_DIR/hud || exit 13
81−}
82−
83−compile_libunity() {
84− echo "Configuring libunity.."
85−
86− if $CLEAN; then bzr clean-tree -d $TARGET_DIR/libunity --quiet --unknown --ignored --force; fi
87−
88− cd $TARGET_DIR/libunity
89− bzr revert --quiet -r $LIBUNITY_REV || exit 14
90−
91− mkdir $TARGET_DIR/libunity/build
92− cd $TARGET_DIR/libunity/build
93−
94− ../autogen.sh --prefix $BUILD_DIR --disable-debug --with-pygi-overrides-dir=$BUILD_DIR/gi-overrides || exit 15
95−
96− echo "Building libunity and installing in " $BUILD_DIR
97− make -j$NUM_JOBS install || exit 16
98−
99−}
100−
101−compile_unity_core() {
102− echo "Configuring Unity.."
103−
104− if $CLEAN; then bzr clean-tree -d $TARGET_DIR/unity --quiet --unknown --ignored --force; fi
105−
106− cd $TARGET_DIR/unity
107− bzr revert --quiet -r $UNITY_REV || exit 17
108−
109− mkdir $TARGET_DIR/unity/build
110− cd $TARGET_DIR/unity/build
111−
112− PKG_CONFIG_PATH=$BUILD_DIR/lib/pkgconfig:$PKG_CONFIG_PATH cmake $TARGET_DIR/unity -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$BUILD_DIR -DCOMPIZ_PLUGIN_INSTALL_TYPE=local -DGSETTINGS_LOCALINSTALL=ON || exit 18
113−
114− echo "Building UnityCore and installing in " $BUILD_DIR
115− cd UnityCore
116− make -j$NUM_JOBS install || exit 19
117−
118−}
119−
120−compile_hud() {
121− echo "Configuring hud.."
122−
123− if $CLEAN; then bzr clean-tree -d $TARGET_DIR/hud --quiet --unknown --ignored --force; fi
124−
125− cd $TARGET_DIR/hud
126− bzr revert -r $HUD_REV || exit 20
127−
128− mkdir $TARGET_DIR/hud/build
129− cd $TARGET_DIR/hud/build
130−
131− cmake $TARGET_DIR/hud/ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$BUILD_DIR -DCMAKE_INSTALL_LIBDIR=lib -DLOCAL_INSTALL=ON -DENABLE_TESTS=OFF || exit 21
132−
133− echo "Building hud and installing in " $BUILD_DIR
134− make install || exit 22
135−
136−}
137−
138−if $SETUP; then
139− echo "Setting up environment for building Unity.."
140− install_utils
141− mkdir -p $TARGET_DIR
142− branch_libunity
143− branch_unity
144− branch_hud
145− mk_build_deps
146−elif $UPDATE; then
147− update_libunity
148− update_unity
149− update_hud
150− mk_build_deps
151−else
152− if $CLEAN; then rm -Rf $BUILD_DIR; fi
153− mkdir -p $BUILD_DIR
154− compile_libunity
155− compile_unity_core
156− compile_hud
157−fi
158−
debian/changelog+122
@@ -1,3 +1,125 @@
1+unity8 (7.81.3+13.10.20130704ubuntu.unity.next-0ubuntu1) saucy; urgency=low
2+
3+ [ Didier Roche ]
4+ * Clean packaging for entering saucy and following daily release guidelines
5+ * Automatic snapshot from revision 49 (bootstrap)
6+
7+ [ Michał Sawicz ]
8+ * Fix unity8.pot file.
9+ * Support the simplified theming from ubuntu-ui-toolkit.
10+ * Use AbstractButtons instead of Button { color: "transparent" } that
11+ doesn't work.
12+
13+ [ Albert Astals ]
14+ * ListViewWithPageHeader implementation in C++. (LP: #1171918)
15+ * LVWPH: Do not crash on showHeader if we don't have a header .
16+ * Fix bug when setting the same model twice to a QLimitProxyModelQML.
17+ * Add some const & Saves us some microseconds in copying stuff.
18+
19+ [ Daniel d'Andrada ]
20+ * Make Greeter and Stage use the new DragHandle component. So they no
21+ longer use Revealers. Now a directional drag gesture is required to
22+ start the animation that brings back a "minimized" application when
23+ the dash is on foreground. Besides that, now they have the following
24+ feature:  - Action only completes succesfully if you drag through at
25+ least half the    screen width or if your swipe is fast enough. The
26+ shorter the swipe, the faster it has to be for the action to auto-
27+ complete.
28+ * DirectionalDragArea: add touchSceneX, touchSceneY, and sceneDistance
29+ properties.
30+ * DirectionalDragArea: emit draggingChanged() on direct recognition
31+ draggingChanged() should be emited when status change from
32+ WaitingForTouch directly to Recognized.
33+ * update CODING instructions for building & running.
34+ * DragHandle: add stretch and hintDisplacement properties.
35+ * DragHandle: fix hinting Revision 64 had a bad interaction with
36+ revision 66 (that added line was lost in the merge/rebase process).
37+ tst_DragHandle::hintingAnimation() points out the problem (fails on
38+ line 388).
39+ * Make Panel use DragHandles instead of a Revealer - A directional
40+ drag gesture is needed reveal the panel when fullscreen. - better
41+ logic for deciding when to auto-complete the show/hide animation -
42+ hinting animation to close the panel - Tapping on menu bar no longer
43+ opens nearest indicator menu - No closing with handle click.
44+
45+ [ mhall119 ]
46+ * Fix build script error from extra blank line. (LP: #1196322)
47+
48+ [ Nick Dedekind ]
49+ * Changed shellImportPath to return a list of paths. Added
50+ prependImportPaths and changed appendImportPaths to check for
51+ duplicates.
52+
53+ [ Mirco Müller ]
54+ * Added support and tests for expanding snap-decisions with more than
55+ 2 actions passed in.
56+
57+ [ Michael Zanetti ]
58+ * As requested by design, decreasing wobblyness in the
59+ WrongPasswordAnimation.
60+ * improve the bzr commit hook - don't run qmltests in here, it takes
61+ too long - don't abort commit on failed tests, its too annoying -
62+ instead, print a fat warning and backup the commit message to be
63+ reused after uncommitting and fixing the tests.
64+ * edge hinting tweaks - change edge hinting behavior to only happen on
65+ onPressed and immediately snap back - fix edge hinting to not happen
66+ if the Greeter is locked .
67+
68+ [ Michael Terry ]
69+ * Fix "Tap to Unlock" text not appearing when in tablet greeter mode
70+ with only one user.
71+ * Use libusermetrics to provide infographic data.
72+ * Delete builddir/ when running "debuild clean".
73+
74+ [ Pawel Stolowski ]
75+ * Bindings for preview and activation requests.
76+
77+ [ Kevin Gunn ]
78+ * update CODING instructions for building & running.
79+
80+ [ Ubuntu daily release ]
81+ * Automatic snapshot from revision 78 (ubuntu-unity/next)
82+
83+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 04 Jul 2013 12:44:19 +0000
84+
85+unity8 (7.81.3) UNRELEASED; urgency=low
86+
87+ * Choose more appropriate values for edge-drag gestures (LP: #1194150)
88+
89+ -- Daniel d'Andrada <daniel.dandrada@canonical.com> Fri, 28 Jun 2013 16:28:24 -0300
90+
91+unity8 (7.81.2) saucy; urgency=low
92+
93+ * Translation updates.
94+
95+ [ Michał Sawicz ]
96+ * Fix icons in ApplicationsFilterGrid.qml.
97+ * Support flipped image in run_on_device.
98+
99+ [ Michael Zanetti ]
100+ * Don't clear lockscreen when it's fading out.
101+ * Reworked Launcher folding.
102+ * Tweak Launcher revealing.
103+
104+ [ Michal Hruby ]
105+ * Add content_type property to category models.
106+
107+ -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 26 Jun 2013 18:10:39 +0200
108+
109+unity8 (7.81.1) saucy; urgency=low
110+
111+ * Translation updates.
112+
113+ [ Michał Sawicz ]
114+ * Don't limit installed apps.
115+ * Pre-optimize PNGs to speed-up builds.
116+ * Clean up build scripts.
117+
118+ [ Daniel d'Andrada ]
119+ * Use DirectionalDragArea in BottomBar.
120+
121+ -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 21 Jun 2013 17:37:02 +0200
122+
1unity8 (7.81.0) saucy; urgency=low
123unity8 (7.81.0) saucy; urgency=low
2
124
3 * Translation updates.
125 * Translation updates.
debian/control+48−48
@@ -1,99 +1,99 @@
1Source: unity8
1Source: unity8
2Section: x11
2Section: x11
3−Priority: extra
3+Priority: optional
4Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
4Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
5Build-Depends: cmake,
5Build-Depends: cmake,
6 debhelper (>= 9),
6 debhelper (>= 9),
7− libc6-dev,
7+ libjson-perl,
8 libdee-qt5-dev (>= 3.0),
8 libdee-qt5-dev (>= 3.0),
9 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
9 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
10 libgl1-mesa-dri,
10 libgl1-mesa-dri,
11 libgles2-mesa-dev[armhf],
11 libgles2-mesa-dev[armhf],
12 libhud-client2-dev,
12 libhud-client2-dev,
13 libpulse-dev,
13 libpulse-dev,
14+ libqt5v8-5-private-dev,
14 libunity-core-6.0-dev (<< 7.80),
15 libunity-core-6.0-dev (<< 7.80),
16+ libunity-dev (>= 7.0.3),
17+ libusermetricsoutput1-dev,
15 libxcb1-dev,
18 libxcb1-dev,
16 pkg-config,
19 pkg-config,
17 python3,
20 python3,
21+ python (>= 2.7),
22+ python-setuptools,
18 qt5-default,
23 qt5-default,
19 qtbase5-dev,
24 qtbase5-dev,
20 qtbase5-private-dev,
25 qtbase5-private-dev,
21 qtdeclarative5-dev,
26 qtdeclarative5-dev,
22 qtdeclarative5-dev-tools,
27 qtdeclarative5-dev-tools,
28+ qtdeclarative5-private-dev,
23 qtdeclarative5-qtquick2-plugin,
29 qtdeclarative5-qtquick2-plugin,
24 qtdeclarative5-test-plugin,
30 qtdeclarative5-test-plugin,
25 qtdeclarative5-ubuntu-ui-toolkit-plugin,
31 qtdeclarative5-ubuntu-ui-toolkit-plugin,
26 qtdeclarative5-xmllistmodel-plugin,
32 qtdeclarative5-xmllistmodel-plugin,
27 ttf-ubuntu-font-family,
33 ttf-ubuntu-font-family,
34+ libunity-scopes-json-def-phone,
28−Standards-Version: 3.9.3
35+Standards-Version: 3.9.4
29Homepage: http://launchpad.net/unity
36Homepage: http://launchpad.net/unity
30# If you aren't a member of ~unity-team but need to upload
37# If you aren't a member of ~unity-team but need to upload
31# packaging changes, just go ahead. ~unity-team will notice
38# packaging changes, just go ahead. ~unity-team will notice
32# and sync up the code again.
39# and sync up the code again.
33−Vcs-Bzr: https://code.launchpad.net/~unity-team/unity/phablet
40+Vcs-Bzr: https://code.launchpad.net/unity8
34−Vcs-Browser: https://bazaar.launchpad.net/~unity-team/unity/phablet/files
41+Vcs-Browser: https://bazaar.launchpad.net/~unity-team/unity8/trunk
35
42
36Package: unity8
43Package: unity8
37−Replaces: qml-phone-shell (<< 7.80~)
38−Breaks: qml-phone-shell (<< 7.80~)
39−Architecture: amd64 armhf i386
44+Architecture: any
45+Depends: ${misc:Depends},
46+ ${shlibs:Depends},
47+ unity8-private (= ${binary:Version}),
40−Depends: indicators-client (>= 0.6.1),
48+ indicators-client (>= 0.6.1),
41 qtdeclarative5-dee-plugin,
49 qtdeclarative5-dee-plugin,
42 qtdeclarative5-ubuntu-ui-toolkit-plugin,
50 qtdeclarative5-ubuntu-ui-toolkit-plugin,
43 qtdeclarative5-unity-notifications-plugin | unity-notifications-impl,
51 qtdeclarative5-unity-notifications-plugin | unity-notifications-impl,
44 unity-notifications-impl-1,
52 unity-notifications-impl-1,
45 qtdeclarative5-xmllistmodel-plugin,
53 qtdeclarative5-xmllistmodel-plugin,
46− qtubuntu,
54+ unity8-fake-env | qtubuntu-shell,
47− ${misc:Depends},
55+Recommends: ${unity-default-masterscopes},
48− ${shlibs:Depends},
49−Recommends: indicators-client-plugin-datetime (>= 0.6.1),
56+ indicators-client-plugin-datetime (>= 0.6.1),
50 indicators-client-plugin-messaging (>= 0.6.1),
57 indicators-client-plugin-messaging (>= 0.6.1),
51 indicators-client-plugin-network (>= 0.6.1),
58 indicators-client-plugin-network (>= 0.6.1),
52 indicators-client-plugin-power (>= 0.6.1),
59 indicators-client-plugin-power (>= 0.6.1),
53 indicators-client-plugin-sound (>= 0.6.1),
60 indicators-client-plugin-sound (>= 0.6.1),
54− unity-scope-home,
55− unity-lens-applications,
56−Description: Ubuntu QML shell
61+Description: Unity 8 shell
57− The Ubuntu QML shell is the primary user interface for Ubuntu devices.
62+ The Unity 8 shell is the primary user interface for Ubuntu devices.
58
63
59−Package: qml-phone-shell
64+Package: unity8-private
60−Depends: unity8, ${misc:Depends}
61−Architecture: all
65+Architecture: any
62−Description: transitional dummy package
66+Multi-Arch: same
63− This is a transitional dummy package. It can safely be removed.
67+Pre-Depends: ${misc:Pre-Depends}
68+Depends: ${misc:Depends},
69+ ${shlibs:Depends},
70+Description: Unity 8 private libs
71+ The Unity 8 shell is the primary user interface for Ubuntu devices.
72+ .
73+ This package contains the private libraries for QML and other components
74+ only used by the shell.
64
75
65Package: unity8-fake-env
76Package: unity8-fake-env
66−Replaces: qml-phone-shell-fake-env (<< 7.80~)
67−Breaks: qml-phone-shell-fake-env (<< 7.80~)
68−Architecture: amd64 armhf i386
77+Architecture: any
78+Multi-Arch: same
79+Pre-Depends: ${misc:Pre-Depends}
69−Depends: ${misc:Depends}, ${shlibs:Depends}
80+Depends: ${misc:Depends},
81+ ${shlibs:Depends},
82+Provides: qtubuntu-shell,
70−Description: Fake environment for running Ubuntu QML shell
83+Description: Fake environment for running Unity 8 shell
71− Provides fake implementations of some QML modules used by Ubuntu QML shell
84+ Provides fake implementations of some QML modules used by Unity 8 shell
72 (e.g Ubuntu.Application) so that you can run it in a sandboxed environment.
85 (e.g Ubuntu.Application) so that you can run it in a sandboxed environment.
73
86
74−Package: qml-phone-shell-fake-env
75−Depends: unity8-fake-env, ${misc:Depends}
76−Architecture: all
77−Description: transitional dummy package
78− This is a transitional dummy package. It can safely be removed.
79−
80Package: unity8-autopilot
87Package: unity8-autopilot
81−Replaces: qml-phone-shell-autopilot (<< 7.80~)
82−Breaks: qml-phone-shell-autopilot (<< 7.80~)
83Architecture: all
88Architecture: all
89+Depends: ${misc:Depends},
90+ ${shlibs:Depends},
91+ ${python:Depends},
84−Depends: libautopilot-qt,
92+ libautopilot-qt,
85 libqt5test5,
93 libqt5test5,
86 libqt5widgets5,
94 libqt5widgets5,
87 python-evdev,
95 python-evdev,
88− unity8 (= ${source:Version}),
96+ unity8 (>= ${source:Version}),
89− unity8-fake-env (= ${source:Version}),
97+ unity8-fake-env (>= ${source:Version}),
90− ${misc:Depends},
91− ${shlibs:Depends},
92−Description: Test package for the shell
98+Description: Test package for Unity 8 shell
93 Autopilot tests for the unity8 package
99 Autopilot tests for the unity8 package
94−
95−Package: qml-phone-shell-autopilot
96−Depends: unity8-autopilot, ${misc:Depends}
97−Architecture: all
98−Description: transitional dummy package
99− This is a transitional dummy package. It can safely be removed.
debian/copyright+13−3
@@ -1,7 +1,9 @@
1Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
1Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2+Upstream-Name: unity8
3+Source: http://launchpad.net/unity
2
4
3Files: *
5Files: *
4−Copyright: 2013 Canonical Ltd.
6+Copyright: 2011-2013 Canonical Ltd.
5License: GPL-3
7License: GPL-3
6
8
7License: GPL-3
9License: GPL-3
@@ -20,9 +22,17 @@ License: GPL-3
20 On Debian systems, the full text of the GNU General Public License
22 On Debian systems, the full text of the GNU General Public License
21 version 3 can be found in the file /usr/share/common-licenses/GPL-3.
23 version 3 can be found in the file /usr/share/common-licenses/GPL-3.
22
24
25+Files: tests/mocks/LightDM/UsersModel.h tests/mocks/LightDM/Greeter.h
26+Copyright: 2013 Canonical Ltd.
27+ 2010-2011 David Edmundson
28+ 2010-2011 Robert Ancell
29+License: GPL-3
30+
31+Files: plugins/Utils/qvariantlistmodel.*
23−Files: tests/unittests/plugins/Utils/modeltest.*
32+ tests/unittests/plugins/Utils/modeltest.*
33+ tests/plugins/Utils/modeltest.*
24Copyright: 2013 Digia Plc and/or its subsidiary(-ies).
34Copyright: 2013 Digia Plc and/or its subsidiary(-ies).
25−License:
35+License: LGPL-2.1 with Digia Qt LGPL Exception 1.1 or GPL-3
26 Commercial License Usage
36 Commercial License Usage
27 Licensees holding valid commercial Qt licenses may use this file in
37 Licensees holding valid commercial Qt licenses may use this file in
28 accordance with the commercial license agreement provided with the
38 accordance with the commercial license agreement provided with the
debian/rules+23−2
@@ -4,12 +4,33 @@
4# Uncomment this to turn on verbose mode.
4# Uncomment this to turn on verbose mode.
5#export DH_VERBOSE=1
5#export DH_VERBOSE=1
6export DPKG_GENSYMBOLS_CHECK_LEVEL=4
6export DPKG_GENSYMBOLS_CHECK_LEVEL=4
7+export NO_PNG_PKG_MANGLE=1
8+
9+SCOPES_RECOMMENDS := $(shell perl debian/scopes-recommends-generator /usr/share/unity/client-scopes.json)
7
10
8%:
11%:
9− dh $@ --parallel
12+ dh $@ --parallel --fail-missing --with python2
13+
14+override_dh_auto_clean:
15+ dh_auto_clean
16+ rm -rf builddir
10
17
11override_dh_install:
18override_dh_install:
19+ # install autopilot tests
20+ cd tests/autopilot; \
21+ set -ex; for python in $(shell pyversions -r); do \
22+ $$python setup.py install --root=$(CURDIR)/debian/tmp --install-layout=deb; \
23+ done; \
24+ cd $(CURDIR)
12− dh_install --fail-missing
25+ dh_install -X'*.pyc' --fail-missing
13
26
27+# use private lib directories
28+override_dh_makeshlibs:
29+ dh_makeshlibs -Nunity8-private -Nunity8-fake-env
30+
31+# libMockLightDM-qml.so links against liblightdm-qt5-2.so which doesn't exist
14override_dh_shlibdeps:
32override_dh_shlibdeps:
15 dh_shlibdeps -XlibMockLightDM-qml.so
33 dh_shlibdeps -XlibMockLightDM-qml.so
34+
35+override_dh_gencontrol:
36+ dh_gencontrol -- -Vunity-default-masterscopes="$(SCOPES_RECOMMENDS)"
debian/scopes-recommends-generatornew file+27
@@ -0,0 +1,27 @@
1+#!/usr/bin/perl -w
2+
3+use strict;
4+binmode STDOUT, ":utf8";
5+use utf8;
6+
7+use JSON;
8+
9+my $json;
10+{
11+ local $/; #Enable 'slurp' mode
12+ open my $fh, "<", $ARGV[0];
13+ $json = <$fh>;
14+ close $fh;
15+}
16+# get it to a scalar
17+my $j = "[" . $json . "]";
18+
19+my $decoded_json = decode_json( $j );
20+
21+my $recommends_list = "";
22+for my $record ( @$decoded_json ) {
23+ foreach my $key ( keys(%$record) ) {
24+ $recommends_list = $recommends_list . $key . ", ";
25+ }
26+}
27+print $recommends_list;
debian/unity8-autopilot.install+1−1
@@ -1 +1 @@
1−tests/autopilot/unity8/* usr/lib/python2.7/dist-packages/unity8/
1+usr/lib/python*/*/unity*
debian/unity8-fake-env.install+1−1
@@ -1 +1 @@
1−/usr/share/unity8/plugins/mocks/*
1+usr/lib/*/unity8/qml/mocks
debian/unity8-private.installnew file+6
@@ -0,0 +1,6 @@
1+usr/lib/*/unity8/qml/HudClient
2+usr/lib/*/unity8/qml/LightDM
3+usr/lib/*/unity8/qml/ListViewWithPageHeader
4+usr/lib/*/unity8/qml/Ubuntu
5+usr/lib/*/unity8/qml/Unity
6+usr/lib/*/unity8/qml/Utils
debian/unity8.install+15−20
@@ -1,20 +1,15 @@
1−/usr/bin/unity8
1+usr/bin/unity8
2−/usr/share/applications/unity8.desktop
2+usr/share/applications/unity8.desktop
3−/usr/share/locale/*
3+usr/share/locale
4−/usr/share/unity8/Applications/*
4+usr/share/unity8/Applications
5−/usr/share/unity8/Bottombar/*
5+usr/share/unity8/Bottombar
6−/usr/share/unity8/Components/*
6+usr/share/unity8/Components
7−/usr/share/unity8/Dash/*
7+usr/share/unity8/Dash
8−/usr/share/unity8/Greeter/*
8+usr/share/unity8/Greeter
9−/usr/share/unity8/Hud/*
9+usr/share/unity8/Hud
10−/usr/share/unity8/Launcher/*
10+usr/share/unity8/Launcher
11−/usr/share/unity8/Notifications/*
11+usr/share/unity8/Notifications
12−/usr/share/unity8/Panel/*
12+usr/share/unity8/Panel
13−/usr/share/unity8/Shell.qml
13+usr/share/unity8/Shell.qml
14−/usr/share/unity8/SideStage/*
14+usr/share/unity8/SideStage
15−/usr/share/unity8/graphics/*
15+usr/share/unity8/graphics
16−/usr/share/unity8/plugins/HudClient/*
17−/usr/share/unity8/plugins/LightDM/*
18−/usr/share/unity8/plugins/Ubuntu/*
19−/usr/share/unity8/plugins/Unity/*
20−/usr/share/unity8/plugins/Utils/*
graphics/12_10_background_wide@12.png

Binary file not shown.

graphics/applicationIcons/angrybirds@18.png

Binary file not shown.

graphics/applicationIcons/camera@18.png

Binary file not shown.

graphics/applicationIcons/dash@18.png

Binary file not shown.

graphics/applicationIcons/evernote@18.png

Binary file not shown.

graphics/applicationIcons/gallery@18.png

Binary file not shown.

graphics/applicationIcons/map@18.png

Binary file not shown.

graphics/applicationIcons/music@18.png

Binary file not shown.

graphics/applicationIcons/phone-app@18.png

Binary file not shown.

graphics/applicationIcons/pinterest@18.png

Binary file not shown.

graphics/applicationIcons/ski_safari@18.png

Binary file not shown.

graphics/applicationIcons/skype@18.png

Binary file not shown.

graphics/applicationIcons/twitter@18.png

Binary file not shown.

graphics/applicationIcons/youtube@18.png

Binary file not shown.

graphics/avatars/amanda@12.png

Binary file not shown.

graphics/avatars/anna_olsson@12.png

Binary file not shown.

graphics/avatars/funky@12.png

Binary file not shown.

graphics/clock@18.png

Binary file not shown.

main.cpp+26−7
@@ -31,13 +31,33 @@
31#include "MouseTouchAdaptor.h"
31#include "MouseTouchAdaptor.h"
32
32
33namespace {
33namespace {
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+ engine->addImportPath(path);
44+ }
45+ }
46+}
47+
34/* When you append and import path to the list of import paths it will be the *last*
48/* When you append and import path to the list of import paths it will be the *last*
35 place where Qt will search for QML modules.
49 place where Qt will search for QML modules.
36 The usual QQmlEngine::addImportPath() actually prepends the given path.*/
50 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)
38{
52{
39 QStringList importPathList = engine->importPathList();
53 QStringList importPathList = engine->importPathList();
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()) {
40− importPathList.append(path);
58+ importPathList.append(path);
59+ }
60+ }
41 engine->setImportPathList(importPathList);
61 engine->setImportPathList(importPathList);
42}
62}
43
63
@@ -59,7 +79,7 @@ int main(int argc, char** argv)
59 setenv("QML_FORCE_THREADED_RENDERER", "1", 1);
79 setenv("QML_FORCE_THREADED_RENDERER", "1", 1);
60 setenv("QML_FIXED_ANIMATION_STEP", "1", 1);
80 setenv("QML_FIXED_ANIMATION_STEP", "1", 1);
61
81
62− QGuiApplication::setApplicationName("Qml Phone Shell");
82+ QGuiApplication::setApplicationName("Unity 8");
63 QGuiApplication application(argc, argv);
83 QGuiApplication application(argc, argv);
64
84
65 resolveIconTheme();
85 resolveIconTheme();
@@ -88,7 +108,7 @@ int main(int argc, char** argv)
88 QQuickView* view = new QQuickView();
108 QQuickView* view = new QQuickView();
89 view->setResizeMode(QQuickView::SizeRootObjectToView);
109 view->setResizeMode(QQuickView::SizeRootObjectToView);
90 view->setTitle("Qml Phone Shell");
110 view->setTitle("Qml Phone Shell");
91− view->engine()->setBaseUrl(QUrl::fromLocalFile(shellAppDirectory()));
111+ view->engine()->setBaseUrl(QUrl::fromLocalFile(::shellAppDirectory()));
92 if (args.contains(QLatin1String("-frameless"))) {
112 if (args.contains(QLatin1String("-frameless"))) {
93 view->setFlags(Qt::FramelessWindowHint);
113 view->setFlags(Qt::FramelessWindowHint);
94 }
114 }
@@ -114,9 +134,8 @@ int main(int argc, char** argv)
114 QObject::connect(view->engine(), SIGNAL(quit()), qApp, SLOT(quit()));
134 QObject::connect(view->engine(), SIGNAL(quit()), qApp, SLOT(quit()));
115
135
116 QUrl source("Shell.qml");
136 QUrl source("Shell.qml");
117− view->engine()->addImportPath(shellAppDirectory());
137+ prependImportPaths(view->engine(), ::overrideImportPaths());
118− view->engine()->addImportPath(shellImportPath());
138+ appendImportPaths(view->engine(), ::fallbackImportPaths());
119− appendImportPath(view->engine(), fakePluginsImportPath());
120 view->setSource(source);
139 view->setSource(source);
121 view->setColor("transparent");
140 view->setColor("transparent");
122
141
paths.h.in+16−8
@@ -17,6 +17,9 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
18 */
19
19
20+#ifndef PATHS_H
21+#define PATHS_H
22+
20// Qt
23// Qt
21#include <QtCore/QCoreApplication>
24#include <QtCore/QCoreApplication>
22#include <QtCore/QDir>
25#include <QtCore/QDir>
@@ -43,22 +46,27 @@ inline QString shellAppDirectory() {
43 }
46 }
44}
47}
45
48
46−inline QString shellImportPath() {
49+inline QStringList overrideImportPaths() {
50+ QStringList paths;
47− if (isRunningInstalled()) {
51+ if (!isRunningInstalled()) {
48− return QString("@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/plugins");
49− } else {
50− return QString("@CMAKE_BINARY_DIR@/plugins/");
52+ paths << QString("@CMAKE_BINARY_DIR@/plugins");
51 }
53 }
54+ return paths;
52}
55}
53
56
54−inline QString fakePluginsImportPath() {
57+inline QStringList fallbackImportPaths() {
58+ QStringList paths;
55 if (isRunningInstalled()) {
59 if (isRunningInstalled()) {
56− return QString("@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/plugins/mocks");
60+ paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_PRIVATE_LIBDIR@/qml");
61+ paths << QString("@CMAKE_INSTALL_PREFIX@/@SHELL_PRIVATE_LIBDIR@/qml/mocks");
57 } else {
62 } else {
58− return QString("@CMAKE_BINARY_DIR@/tests/mocks");
63+ paths << QString("@CMAKE_BINARY_DIR@/tests/mocks");
59 }
64 }
65+ return paths;
60}
66}
61
67
62inline QString sourceDirectory() {
68inline QString sourceDirectory() {
63 return QString("@CMAKE_SOURCE_DIR@/");
69 return QString("@CMAKE_SOURCE_DIR@/");
64}
70}
71+
72+#endif
plugins/CMakeLists.txt+1
@@ -3,3 +3,4 @@ add_subdirectory(Utils)
3add_subdirectory(Unity)
3add_subdirectory(Unity)
4add_subdirectory(HudClient)
4add_subdirectory(HudClient)
5add_subdirectory(LightDM)
5add_subdirectory(LightDM)
6+add_subdirectory(ListViewWithPageHeader)
plugins/HudClient/CMakeLists.txt+2−2
@@ -41,9 +41,9 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
41 )
41 )
42
42
43install(TARGETS HudClientQml
43install(TARGETS HudClientQml
44− DESTINATION ${SHELL_APP_DIR}/plugins/HudClient
44+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/HudClient
45 )
45 )
46
46
47install(FILES qmldir
47install(FILES qmldir
48− DESTINATION ${SHELL_APP_DIR}/plugins/HudClient
48+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/HudClient
49 )
49 )
plugins/LightDM/CMakeLists.txt+6−3
@@ -1,6 +1,7 @@
1# Dependencies
1# Dependencies
2+include(FindPkgConfig)
3+pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2# TODO: Once we split out a separate greeter process, uncomment these lines
4# TODO: Once we split out a separate greeter process, uncomment these lines
3−#include(FindPkgConfig)
4#pkg_check_modules(LIBLIGHTDM REQUIRED liblightdm-qt5-2)
5#pkg_check_modules(LIBLIGHTDM REQUIRED liblightdm-qt5-2)
5
6
6include_directories(
7include_directories(
@@ -8,6 +9,7 @@ include_directories(
8 ${CMAKE_CURRENT_BINARY_DIR}
9 ${CMAKE_CURRENT_BINARY_DIR}
9 ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM
10 ${CMAKE_SOURCE_DIR}/tests/mocks/LightDM
10 #${LIBLIGHTDM_INCLUDE_DIRS}
11 #${LIBLIGHTDM_INCLUDE_DIRS}
12+ ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
11)
13)
12
14
13set(QMLPLUGIN_SRC
15set(QMLPLUGIN_SRC
@@ -25,6 +27,7 @@ target_link_libraries(LightDM-qml
25 MockLightDM-demo
27 MockLightDM-demo
26# TODO: Once we split out a separate greeter process, uncomment these lines
28# TODO: Once we split out a separate greeter process, uncomment these lines
27# ${LIBLIGHTDM_LDFLAGS}
29# ${LIBLIGHTDM_LDFLAGS}
30+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
28 )
31 )
29
32
30qt5_use_modules(LightDM-qml Gui Qml)
33qt5_use_modules(LightDM-qml Gui Qml)
@@ -35,9 +38,9 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
35 )
38 )
36
39
37install(TARGETS LightDM-qml
40install(TARGETS LightDM-qml
38− DESTINATION ${SHELL_APP_DIR}/plugins/LightDM
41+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/LightDM
39 )
42 )
40
43
41install(FILES qmldir
44install(FILES qmldir
42− DESTINATION ${SHELL_APP_DIR}/plugins/LightDM
45+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/LightDM
43 )
46 )
plugins/LightDM/Greeter.cpp+6−6
@@ -102,21 +102,21 @@ bool Greeter::startSessionSync(const QString &session)
102 return d->m_greeter->startSessionSync(session);
102 return d->m_greeter->startSessionSync(session);
103}
103}
104
104
105−void Greeter::showPromptFilter(QString text, QLightDM::Greeter::PromptType type)
105+void Greeter::showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type)
106{
106{
107 Q_D(Greeter);
107 Q_D(Greeter);
108 d->wasPrompted = true;
108 d->wasPrompted = true;
109
109
110 // Strip prompt of any colons at the end
110 // Strip prompt of any colons at the end
111− text = text.trimmed();
111+ QString trimmedText = text.trimmed();
112− if (text.endsWith(":") || text.endsWith(":")) {
112+ if (trimmedText.endsWith(":") || trimmedText.endsWith(":")) {
113− text.chop(1);
113+ trimmedText.chop(1);
114 }
114 }
115
115
116− Q_EMIT showPrompt(text, type == QLightDM::Greeter::PromptTypeSecret);
116+ Q_EMIT showPrompt(trimmedText, type == QLightDM::Greeter::PromptTypeSecret);
117}
117}
118
118
119−void Greeter::showMessageFilter(QString text, QLightDM::Greeter::MessageType type)
119+void Greeter::showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type)
120{
120{
121 Q_EMIT showMessage(text, type == QLightDM::Greeter::MessageTypeError);
121 Q_EMIT showMessage(text, type == QLightDM::Greeter::MessageTypeError);
122}
122}
plugins/LightDM/Greeter.h+4−4
@@ -51,8 +51,8 @@ public Q_SLOTS:
51 bool startSessionSync(const QString &session=QString());
51 bool startSessionSync(const QString &session=QString());
52
52
53Q_SIGNALS:
53Q_SIGNALS:
54− void showMessage(QString text, bool isError);
54+ void showMessage(const QString &text, bool isError);
55− void showPrompt(QString text, bool isSecret);
55+ void showPrompt(const QString &text, bool isSecret);
56 void authenticationComplete();
56 void authenticationComplete();
57 void promptlessChanged();
57 void promptlessChanged();
58
58
@@ -62,8 +62,8 @@ private:
62 Q_DECLARE_PRIVATE(Greeter)
62 Q_DECLARE_PRIVATE(Greeter)
63
63
64private Q_SLOTS:
64private Q_SLOTS:
65− void showMessageFilter(QString text, QLightDM::Greeter::MessageType type);
65+ void showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type);
66− void showPromptFilter(QString text, QLightDM::Greeter::PromptType type);
66+ void showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type);
67 void authenticationCompleteFilter();
67 void authenticationCompleteFilter();
68};
68};
69
69
plugins/LightDM/plugin.cpp+5−4
@@ -20,8 +20,9 @@
20#include "plugin.h"
20#include "plugin.h"
21#include "Greeter.h"
21#include "Greeter.h"
22#include "UsersModel.h"
22#include "UsersModel.h"
23+#include <libusermetricsoutput/ColorTheme.h>
24+#include <libusermetricsoutput/UserMetrics.h>
23#include <QLightDM/UsersModel>
25#include <QLightDM/UsersModel>
24−#include "InfographicModel.h"
25
26
26#include <QtCore/QAbstractItemModel>
27#include <QtCore/QAbstractItemModel>
27#include <QtQml>
28#include <QtQml>
@@ -44,17 +45,17 @@ static QObject *infographic_provider(QQmlEngine *engine, QJSEngine *scriptEngine
44{
45{
45 Q_UNUSED(engine)
46 Q_UNUSED(engine)
46 Q_UNUSED(scriptEngine)
47 Q_UNUSED(scriptEngine)
47− return InfographicModel::getInstance();
48+ return UserMetricsOutput::UserMetrics::getInstance();
48}
49}
49
50
50void LightDMPlugin::registerTypes(const char *uri)
51void LightDMPlugin::registerTypes(const char *uri)
51{
52{
52 qmlRegisterType<QAbstractItemModel>();
53 qmlRegisterType<QAbstractItemModel>();
53− qmlRegisterType<InfographicColorTheme>();
54+ qmlRegisterType<UserMetricsOutput::ColorTheme>();
54
55
55 Q_ASSERT(uri == QLatin1String("LightDM"));
56 Q_ASSERT(uri == QLatin1String("LightDM"));
56 qmlRegisterSingletonType<Greeter>(uri, 0, 1, "Greeter", greeter_provider);
57 qmlRegisterSingletonType<Greeter>(uri, 0, 1, "Greeter", greeter_provider);
57 qmlRegisterSingletonType<UsersModel>(uri, 0, 1, "Users", users_provider);
58 qmlRegisterSingletonType<UsersModel>(uri, 0, 1, "Users", users_provider);
58 qmlRegisterUncreatableType<QLightDM::UsersModel>(uri, 0, 1, "UserRoles", "Type is not instantiable");
59 qmlRegisterUncreatableType<QLightDM::UsersModel>(uri, 0, 1, "UserRoles", "Type is not instantiable");
59− qmlRegisterSingletonType<InfographicModel>(uri, 0, 1, "Infographic", infographic_provider);
60+ qmlRegisterSingletonType<UserMetricsOutput::UserMetrics>(uri, 0, 1, "Infographic", infographic_provider);
60}
61}
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_PRIVATE_LIBDIR}/qml/ListViewWithPageHeader
40+ )
41+
42+install(FILES qmldir
43+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/ListViewWithPageHeader
44+ )
plugins/ListViewWithPageHeader/listviewwithpageheader.cppnew file+1062
@@ -0,0 +1,1062 @@
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+ if (!m_headerItem)
346+ return;
347+
348+ auto to = qMax(-minYExtent(), contentY() - m_headerItem->height() + m_headerItemShownHeight);
349+ if (to != contentY()) {
350+ m_headerShowAnimation->setTo(to);
351+ m_headerShowAnimation->start();
352+ }
353+}
354+
355+qreal ListViewWithPageHeader::minYExtent() const
356+{
357+// qDebug() << "ListViewWithPageHeader::minYExtent" << m_minYExtent;
358+ return m_minYExtent;
359+}
360+
361+void ListViewWithPageHeader::componentComplete()
362+{
363+ if (m_delegateModel)
364+ m_delegateModel->componentComplete();
365+
366+ QQuickFlickable::componentComplete();
367+
368+ polish();
369+}
370+
371+void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
372+{
373+ QQuickFlickable::viewportMoved(orient);
374+// qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY();
375+ qreal diff = m_previousContentY - contentY();
376+ if (m_headerItem) {
377+ auto oldHeaderItemShownHeight = m_headerItemShownHeight;
378+ if (contentY() < -m_minYExtent) {
379+ // Stick the header item to the top when dragging down
380+ m_headerItem->setY(contentY());
381+ m_headerItem->setHeight(m_headerItem->implicitHeight() + (-m_minYExtent - contentY()));
382+ } else {
383+ m_headerItem->setHeight(m_headerItem->implicitHeight());
384+ // We are going down (but it's not because of the rebound at the end)
385+ // (but the header was not shown by it's own position)
386+ // or the header is partially shown
387+ const bool scrolledUp = m_previousContentY > contentY();
388+ const bool notRebounding = contentY() + height() < contentHeight();
389+ const bool notShownByItsOwn = contentY() + diff > m_headerItem->y() + m_headerItem->height();
390+
391+ if (!scrolledUp && contentY() == -m_minYExtent) {
392+ m_headerItemShownHeight = 0;
393+ m_headerItem->setY(contentY());
394+ } else if ((scrolledUp && notRebounding && notShownByItsOwn) || (m_headerItemShownHeight > 0)) {
395+ m_headerItemShownHeight += diff;
396+ if (contentY() == -m_minYExtent) {
397+ m_headerItemShownHeight = 0;
398+ } else {
399+ m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, m_headerItem->height());
400+ }
401+ if (m_headerItemShownHeight > 0) {
402+ m_headerItem->setY(contentY() - m_headerItem->height() + m_headerItemShownHeight);
403+ } else {
404+ m_headerItem->setY(-m_minYExtent);
405+ }
406+ }
407+ }
408+ // We will be changing the clip item, need to accomadate for it
409+ // otherwise we move the firstItem down/up twice (unless the
410+ // show header animation is running, where we want to keep the viewport stable)
411+ if (!m_headerShowAnimation->isRunning()) {
412+ diff += oldHeaderItemShownHeight - m_headerItemShownHeight;
413+ } else {
414+ diff = -diff;
415+ }
416+ }
417+ if (!m_visibleItems.isEmpty()) {
418+ updateClipItem();
419+ ListItem *firstItem = m_visibleItems.first();
420+ firstItem->setY(firstItem->y() + diff);
421+ if (m_headerShowAnimation->isRunning()) {
422+ adjustMinYExtent();
423+ }
424+ }
425+
426+ m_previousContentY = contentY();
427+ layout();
428+ polish();
429+}
430+
431+void ListViewWithPageHeader::createDelegateModel()
432+{
433+ m_delegateModel = new QQuickVisualDataModel(qmlContext(this), this);
434+ connect(m_delegateModel, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(itemCreated(int,QQuickItem*)));
435+ if (isComponentComplete())
436+ m_delegateModel->componentComplete();
437+ updateWatchedRoles();
438+}
439+
440+void ListViewWithPageHeader::refill()
441+{
442+ if (m_inLayout) {
443+ return;
444+ }
445+ if (!isComponentComplete()) {
446+ return;
447+ }
448+
449+ const qreal buffer = height() * bufferRatio;
450+ const qreal from = contentY();
451+ const qreal to = from + height();
452+ const qreal bufferFrom = from - buffer;
453+ const qreal bufferTo = to + buffer;
454+
455+ bool added = addVisibleItems(from, to, false);
456+ bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
457+ added |= addVisibleItems(bufferFrom, bufferTo, true);
458+
459+ if (added || removed) {
460+ m_contentHeightDirty = true;
461+ }
462+}
463+
464+bool ListViewWithPageHeader::addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous)
465+{
466+ if (!delegate())
467+ return false;
468+
469+ if (m_delegateModel->count() == 0)
470+ return false;
471+
472+ ListItem *item;
473+// qDebug() << "ListViewWithPageHeader::addVisibleItems" << fillFrom << fillTo << asynchronous;
474+
475+ int modelIndex = 0;
476+ qreal pos = 0;
477+ if (!m_visibleItems.isEmpty()) {
478+ modelIndex = m_firstVisibleIndex + m_visibleItems.count();
479+ item = m_visibleItems.last();
480+ pos = item->y() + item->height() + m_clipItem->y();
481+ }
482+ bool changed = false;
483+// qDebug() << (modelIndex < m_delegateModel->count()) << pos << fillTo;
484+ while (modelIndex < m_delegateModel->count() && pos <= fillTo) {
485+// qDebug() << "refill: append item" << modelIndex << "pos" << pos << "asynchronous" << asynchronous;
486+ if (!(item = createItem(modelIndex, asynchronous)))
487+ break;
488+ pos += item->height();
489+ ++modelIndex;
490+ changed = true;
491+ }
492+
493+ modelIndex = 0;
494+ pos = 0;
495+ if (!m_visibleItems.isEmpty()) {
496+ modelIndex = m_firstVisibleIndex - 1;
497+ item = m_visibleItems.first();
498+ pos = item->y() + m_clipItem->y();
499+ }
500+ while (modelIndex >= 0 && pos > fillFrom) {
501+// qDebug() << "refill: prepend item" << modelIndex << "pos" << pos << "fillFrom" << fillFrom << "asynchronous" << asynchronous;
502+ if (!(item = createItem(modelIndex, asynchronous)))
503+ break;
504+ pos -= item->height();
505+ --modelIndex;
506+ changed = true;
507+ }
508+
509+ return changed;
510+}
511+
512+void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
513+{
514+ QQuickItem *item = listItem->m_item;
515+ QQuickVisualModel::ReleaseFlags flags = m_delegateModel->release(item);
516+ if (flags & QQuickVisualModel::Destroyed) {
517+ item->setParentItem(nullptr);
518+ }
519+ delete listItem->m_sectionItem;
520+ delete listItem;
521+}
522+
523+void ListViewWithPageHeader::releaseItem(ListItem *listItem)
524+{
525+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(listItem->m_item);
526+ itemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
527+ m_itemsToRelease << listItem;
528+}
529+
530+void ListViewWithPageHeader::updateWatchedRoles()
531+{
532+ if (m_delegateModel) {
533+ QList<QByteArray> roles;
534+ if (!m_sectionProperty.isEmpty())
535+ roles << m_sectionProperty.toUtf8();
536+ m_delegateModel->setWatchedRoles(roles);
537+ }
538+}
539+
540+QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyInserted)
541+{
542+ if (!m_sectionDelegate)
543+ return nullptr;
544+
545+ const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
546+ if (modelIndex > 0) {
547+ const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
548+ if (section == prevSection)
549+ return nullptr;
550+ }
551+ if (modelIndex + 1 < model()->rowCount() && !alreadyInserted) {
552+ // Already inserted items can't steal next section header
553+ const QString nextSection = m_delegateModel->stringValue(modelIndex + 1, m_sectionProperty);
554+ if (section == nextSection) {
555+ // Steal the section header
556+ ListItem *nextItem = itemAtIndex(modelIndex); // Not +1 since not yet inserted into m_visibleItems
557+ if (nextItem) {
558+ QQuickItem *sectionItem = nextItem->m_sectionItem;
559+ nextItem->m_sectionItem = nullptr;
560+ return sectionItem;
561+ }
562+ }
563+ }
564+
565+ return getSectionItem(section);
566+}
567+
568+QQuickItem *ListViewWithPageHeader::getSectionItem(const QString &sectionText)
569+{
570+ QQuickItem *sectionItem = nullptr;
571+
572+ QQmlContext *creationContext = m_sectionDelegate->creationContext();
573+ QQmlContext *context = new QQmlContext(creationContext ? creationContext : qmlContext(this));
574+ context->setContextProperty(QLatin1String("section"), sectionText);
575+ QObject *nobj = m_sectionDelegate->beginCreate(context);
576+ if (nobj) {
577+ QQml_setParent_noEvent(context, nobj);
578+ sectionItem = qobject_cast<QQuickItem *>(nobj);
579+ if (!sectionItem) {
580+ delete nobj;
581+ } else {
582+ sectionItem->setZ(2);
583+ QQml_setParent_noEvent(sectionItem, m_clipItem);
584+ sectionItem->setParentItem(m_clipItem);
585+ }
586+ } else {
587+ delete context;
588+ }
589+ m_sectionDelegate->completeCreate();
590+
591+ // TODO attach to sectionItem so we can accomodate to it changing its height
592+
593+ return sectionItem;
594+}
595+
596+bool ListViewWithPageHeader::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
597+{
598+// qDebug() << "ListViewWithPageHeader::removeNonVisibleItems" << bufferFrom << bufferTo;
599+ // Do not remove items if we are overshooting up or down, since we'll come back
600+ // to the "stable" position and delete/create items without any reason
601+ if (contentY() < -m_minYExtent) {
602+ return false;
603+ } else if (contentY() + height() > contentHeight()) {
604+ return false;
605+ }
606+ bool changed = false;
607+
608+ bool foundVisible = false;
609+ int i = 0;
610+ int removedItems = 0;
611+ const auto oldFirstVisibleIndex = m_firstVisibleIndex;
612+ while (i < m_visibleItems.count()) {
613+ ListItem *item = m_visibleItems[i];
614+ const qreal pos = item->y() + m_clipItem->y();
615+// qDebug() << i << pos << (pos + item->height()) << bufferFrom << bufferTo;
616+ if (pos + item->height() < bufferFrom || pos > bufferTo) {
617+// qDebug() << "Releasing" << i << (pos + item->height() < bufferFrom) << pos + item->height() << bufferFrom << (pos > bufferTo) << pos << bufferTo;
618+ releaseItem(item);
619+ m_visibleItems.removeAt(i);
620+ changed = true;
621+ ++removedItems;
622+ } else {
623+ if (!foundVisible) {
624+ foundVisible = true;
625+ const int itemIndex = m_firstVisibleIndex + removedItems + i;
626+ m_firstVisibleIndex = itemIndex;
627+ }
628+ ++i;
629+ }
630+ }
631+ if (m_firstVisibleIndex != oldFirstVisibleIndex) {
632+ adjustMinYExtent();
633+ }
634+
635+ return changed;
636+}
637+
638+ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIndex, bool asynchronous)
639+{
640+// qDebug() << "CREATE ITEM" << modelIndex;
641+ if (asynchronous && m_asyncRequestedIndex != -1)
642+ return nullptr;
643+
644+ m_asyncRequestedIndex = -1;
645+ QQuickItem *item = m_delegateModel->item(modelIndex, asynchronous);
646+ if (!item) {
647+ m_asyncRequestedIndex = modelIndex;
648+ return 0;
649+ } else {
650+// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
651+ ListItem *listItem = new ListItem;
652+ listItem->m_item = item;
653+ listItem->m_sectionItem = getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/);
654+ QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
655+ ListItem *prevItem = itemAtIndex(modelIndex - 1);
656+ bool lostItem = false; // Is an item that we requested async but because of model changes
657+ // it is no longer attached to any of the existing items (has no prev nor next item)
658+ // nor is the first item
659+ if (prevItem) {
660+ listItem->setY(prevItem->y() + prevItem->height());
661+ } else {
662+ ListItem *currItem = itemAtIndex(modelIndex);
663+ if (currItem) {
664+ // There's something already in m_visibleItems at out index, meaning this is an insert, so attach to its top
665+ listItem->setY(currItem->y() - listItem->height());
666+ } else {
667+ ListItem *nextItem = itemAtIndex(modelIndex + 1);
668+ if (nextItem) {
669+ listItem->setY(nextItem->y() - listItem->height());
670+ } else if (modelIndex == 0 && m_headerItem) {
671+ listItem->setY(m_headerItem->height());
672+ } else if (!m_visibleItems.isEmpty()) {
673+ lostItem = true;
674+ }
675+ }
676+ }
677+ if (lostItem) {
678+ releaseItem(listItem);
679+ listItem = nullptr;
680+ } else {
681+ listItem->setCulled(listItem->y() + listItem->height() + m_clipItem->y() < contentY() || listItem->y() + m_clipItem->y() >= contentY() + height());
682+ if (m_visibleItems.isEmpty()) {
683+ m_visibleItems << listItem;
684+ } else {
685+ m_visibleItems.insert(modelIndex - m_firstVisibleIndex, listItem);
686+ }
687+ if (m_firstVisibleIndex < 0 || modelIndex < m_firstVisibleIndex) {
688+ m_firstVisibleIndex = modelIndex;
689+ polish();
690+ }
691+ adjustMinYExtent();
692+ m_contentHeightDirty = true;
693+ }
694+ return listItem;
695+ }
696+}
697+
698+void ListViewWithPageHeader::itemCreated(int modelIndex, QQuickItem *item)
699+{
700+// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
701+
702+ item->setParentItem(m_clipItem);
703+ QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
704+ context->setContextProperty(QLatin1String("ListViewWithPageHeader"), this);
705+ context->setContextProperty(QLatin1String("heightToClip"), QVariant::fromValue<int>(0));
706+ if (modelIndex == m_asyncRequestedIndex) {
707+ createItem(modelIndex, false);
708+ refill();
709+ }
710+}
711+
712+void ListViewWithPageHeader::updateClipItem()
713+{
714+ m_clipItem->setHeight(height() - m_headerItemShownHeight);
715+ m_clipItem->setY(contentY() + m_headerItemShownHeight);
716+ m_clipItem->setClip(!m_forceNoClip && m_headerItemShownHeight > 0);
717+}
718+
719+void ListViewWithPageHeader::onContentHeightChanged()
720+{
721+ updateClipItem();
722+}
723+
724+void ListViewWithPageHeader::onContentWidthChanged()
725+{
726+ m_clipItem->setWidth(contentItem()->width());
727+}
728+
729+void ListViewWithPageHeader::onHeightChanged()
730+{
731+ polish();
732+}
733+
734+void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bool /*reset*/)
735+{
736+ // TODO Do something with reset
737+// qDebug() << "ListViewWithPageHeader::onModelUpdated" << changeSet << reset;
738+ const auto oldFirstVisibleIndex = m_firstVisibleIndex;
739+
740+ Q_FOREACH(const QQuickChangeSet::Remove &remove, changeSet.removes()) {
741+// qDebug() << "ListViewWithPageHeader::onModelUpdated Remove" << remove.index << remove.count;
742+ if (remove.index + remove.count > m_firstVisibleIndex && remove.index < m_firstVisibleIndex + m_visibleItems.count()) {
743+ const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
744+ // If all the items we are removing are either not created or culled
745+ // we have to grow down to avoid viewport changing
746+ bool growDown = true;
747+ for (int i = 0; growDown && i < remove.count; ++i) {
748+ const int modelIndex = remove.index + i;
749+ ListItem *item = itemAtIndex(modelIndex);
750+ if (item && !item->culled()) {
751+ growDown = false;
752+ }
753+ }
754+ for (int i = remove.count - 1; i >= 0; --i) {
755+ const int visibleIndex = remove.index + i - m_firstVisibleIndex;
756+ if (visibleIndex >= 0 && visibleIndex < m_visibleItems.count()) {
757+ ListItem *item = m_visibleItems[visibleIndex];
758+ // Pass the section item down if needed
759+ if (item->m_sectionItem && visibleIndex + 1 < m_visibleItems.count()) {
760+ ListItem *nextItem = m_visibleItems[visibleIndex + 1];
761+ if (!nextItem->m_sectionItem) {
762+ nextItem->m_sectionItem = item->m_sectionItem;
763+ item->m_sectionItem = nullptr;
764+ }
765+ }
766+ releaseItem(item);
767+ m_visibleItems.removeAt(visibleIndex);
768+ }
769+ }
770+ if (growDown) {
771+ adjustMinYExtent();
772+ } else if (remove.index <= m_firstVisibleIndex && !m_visibleItems.isEmpty()) {
773+ // We removed the first item that is the one that positions the rest
774+ // position the new first item correctly
775+ m_visibleItems.first()->setY(oldFirstValidIndexPos);
776+ }
777+ } else if (remove.index + remove.count <= m_firstVisibleIndex) {
778+ m_firstVisibleIndex -= remove.count;
779+ }
780+ for (int i = remove.count - 1; i >= 0; --i) {
781+ const int modelIndex = remove.index + i;
782+ if (modelIndex == m_asyncRequestedIndex) {
783+ m_asyncRequestedIndex = -1;
784+ } else if (modelIndex < m_asyncRequestedIndex) {
785+ m_asyncRequestedIndex--;
786+ }
787+ }
788+ }
789+
790+ Q_FOREACH(const QQuickChangeSet::Insert &insert, changeSet.inserts()) {
791+// qDebug() << "ListViewWithPageHeader::onModelUpdated Insert" << insert.index << insert.count;
792+ const bool insertingInValidIndexes = insert.index > m_firstVisibleIndex && insert.index < m_firstVisibleIndex + m_visibleItems.count();
793+ const bool firstItemWithViewOnTop = insert.index == 0 && m_firstVisibleIndex == 0 && m_visibleItems.first()->y() + m_clipItem->y() > contentY();
794+ if (insertingInValidIndexes || firstItemWithViewOnTop)
795+ {
796+ // If the items we are adding won't be really visible
797+ // we grow up instead of down to not change the viewport
798+ bool growUp = false;
799+ if (!firstItemWithViewOnTop) {
800+ for (int i = 0; i < m_visibleItems.count(); ++i) {
801+ if (!m_visibleItems[i]->culled()) {
802+ if (insert.index <= m_firstVisibleIndex + i) {
803+ growUp = true;
804+ }
805+ break;
806+ }
807+ }
808+ }
809+
810+ const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
811+ for (int i = insert.count - 1; i >= 0; --i) {
812+ const int modelIndex = insert.index + i;
813+ ListItem *item = createItem(modelIndex, false);
814+ if (growUp) {
815+ ListItem *firstItem = m_visibleItems.first();
816+ firstItem->setY(firstItem->y() - item->height());
817+ adjustMinYExtent();
818+ }
819+ // Adding an item may break a "same section" chain, so check
820+ // if we need adding a new section item
821+ if (m_sectionDelegate) {
822+ ListItem *nextItem = itemAtIndex(modelIndex + 1);
823+ if (nextItem && !nextItem->m_sectionItem) {
824+ nextItem->m_sectionItem = getSectionItem(modelIndex + 1, true /* alredy inserted into m_visibleItems*/);
825+ if (growUp && nextItem->m_sectionItem) {
826+ ListItem *firstItem = m_visibleItems.first();
827+ firstItem->setY(firstItem->y() - nextItem->m_sectionItem->height());
828+ adjustMinYExtent();
829+ }
830+ }
831+ }
832+ }
833+ if (firstItemWithViewOnTop) {
834+ ListItem *firstItem = m_visibleItems.first();
835+ firstItem->setY(oldFirstValidIndexPos);
836+ }
837+ } else if (insert.index <= m_firstVisibleIndex) {
838+ m_firstVisibleIndex += insert.count;
839+ }
840+
841+ for (int i = insert.count - 1; i >= 0; --i) {
842+ const int modelIndex = insert.index + i;
843+ if (modelIndex <= m_asyncRequestedIndex) {
844+ m_asyncRequestedIndex++;
845+ }
846+ }
847+ }
848+
849+ if (m_firstVisibleIndex != oldFirstVisibleIndex) {
850+ adjustMinYExtent();
851+ }
852+
853+ layout();
854+ polish();
855+ m_contentHeightDirty = true;
856+}
857+
858+void ListViewWithPageHeader::onShowHeaderAnimationFinished()
859+{
860+ m_contentHeightDirty = true;
861+ polish();
862+}
863+
864+void ListViewWithPageHeader::itemGeometryChanged(QQuickItem * /*item*/, const QRectF &newGeometry, const QRectF &oldGeometry)
865+{
866+ const qreal heightDiff = newGeometry.height() - oldGeometry.height();
867+ if (heightDiff != 0) {
868+ if (oldGeometry.y() + oldGeometry.height() + m_clipItem->y() < contentY() && !m_visibleItems.isEmpty()) {
869+ ListItem *firstItem = m_visibleItems.first();
870+ firstItem->setY(firstItem->y() - heightDiff);
871+ adjustMinYExtent();
872+ layout();
873+ }
874+ refill();
875+ adjustMinYExtent();
876+ polish();
877+ m_contentHeightDirty = true;
878+ }
879+}
880+
881+void ListViewWithPageHeader::headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY)
882+{
883+ const qreal heightDiff = newHeaderHeight - oldHeaderHeight;
884+ if (m_headerItemShownHeight > 0) {
885+ // If the header is shown because of the clip
886+ // Change its size
887+ m_headerItemShownHeight += heightDiff;
888+ m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, newHeaderHeight);
889+ updateClipItem();
890+ adjustMinYExtent();
891+ } else {
892+ if (oldHeaderY + oldHeaderHeight > contentY()) {
893+ // If the header is shown because its position
894+ // Change its size
895+ ListItem *firstItem = m_visibleItems.first();
896+ firstItem->setY(firstItem->y() + heightDiff);
897+ layout();
898+ } else {
899+ // If the header is not on screen, just change the start of the list
900+ // so the viewport is not changed
901+ adjustMinYExtent();
902+ }
903+ }
904+}
905+
906+
907+void ListViewWithPageHeader::adjustMinYExtent()
908+{
909+ if (m_visibleItems.isEmpty()) {
910+ m_minYExtent = 0;
911+ } else {
912+ qreal nonCreatedHeight = 0;
913+ if (m_firstVisibleIndex != 0) {
914+ // Calculate the average height of items to estimate the position of the list start
915+ const int visibleItems = m_visibleItems.count();
916+ qreal visibleItemsHeight = 0;
917+ Q_FOREACH(ListItem *item, m_visibleItems) {
918+ visibleItemsHeight += item->height();
919+ }
920+ nonCreatedHeight = m_firstVisibleIndex * visibleItemsHeight / visibleItems;
921+// qDebug() << m_firstVisibleIndex << visibleItemsHeight << visibleItems << nonCreatedHeight;
922+ }
923+ m_minYExtent = nonCreatedHeight - m_visibleItems.first()->y() - m_clipItem->y() + (m_headerItem ? m_headerItem->implicitHeight() : 0);
924+ }
925+}
926+
927+ListViewWithPageHeader::ListItem *ListViewWithPageHeader::itemAtIndex(int modelIndex) const
928+{
929+ const int visibleIndexedModelIndex = modelIndex - m_firstVisibleIndex;
930+ if (visibleIndexedModelIndex >= 0 && visibleIndexedModelIndex < m_visibleItems.count())
931+ return m_visibleItems[visibleIndexedModelIndex];
932+
933+ return nullptr;
934+}
935+
936+void ListViewWithPageHeader::layout()
937+{
938+ if (m_inLayout)
939+ return;
940+
941+ m_inLayout = true;
942+ if (!m_visibleItems.isEmpty()) {
943+ const qreal visibleFrom = contentY() - m_clipItem->y() + m_headerItemShownHeight;
944+ const qreal visibleTo = contentY() + height() - m_clipItem->y();
945+
946+ qreal pos = m_visibleItems.first()->y();
947+
948+// qDebug() << "ListViewWithPageHeader::layout Updating positions and heights. contentY" << contentY() << "minYExtent" << minYExtent();
949+ int firstReallyVisibleItem = -1;
950+ int modelIndex = m_firstVisibleIndex;
951+ Q_FOREACH(ListItem *item, m_visibleItems) {
952+ const bool cull = pos + item->height() < visibleFrom || pos >= visibleTo;
953+ item->setCulled(cull);
954+ item->setY(pos);
955+ if (!cull && firstReallyVisibleItem == -1) {
956+ firstReallyVisibleItem = modelIndex;
957+ if (m_topSectionItem) {
958+ // Update the top sticky section header
959+ const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
960+ QQmlContext *context = QQmlEngine::contextForObject(m_topSectionItem)->parentContext();
961+ context->setContextProperty(QLatin1String("section"), section);
962+
963+ // Positing the top section sticky item is a two step process
964+ // First we set it either we cull it (because it doesn't need to be sticked to the top)
965+ // or stick it to the top
966+ // Then after the loop we'll make sure that if there's another section just below it
967+ // pushed the sticky section up to make it disappear
968+ const qreal topSectionStickPos = m_headerItemShownHeight + contentY() - m_clipItem->y();
969+ if (topSectionStickPos <= pos) {
970+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
971+ if (item->m_sectionItem) {
972+ // This seems it should happen since why would we cull the top section
973+ // if the first visible item has no section header? This only happens briefly
974+ // when increasing the height of a list that is at the bottom, the m_topSectionItem
975+ // gets shown shortly in the next polish call
976+ QQuickItemPrivate::get(item->m_sectionItem)->setCulled(false);
977+ }
978+ } else {
979+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(false);
980+ m_topSectionItem->setY(topSectionStickPos);
981+ if (item->m_sectionItem) {
982+ QQuickItemPrivate::get(item->m_sectionItem)->setCulled(true);
983+ }
984+ }
985+ }
986+ }
987+ QQmlContext *context = QQmlEngine::contextForObject(item->m_item)->parentContext();
988+ const qreal clipFrom = visibleFrom + (!item->m_sectionItem && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
989+ if (!cull && pos < clipFrom) {
990+ context->setContextProperty(QLatin1String("heightToClip"), clipFrom - pos);
991+ } else {
992+ context->setContextProperty(QLatin1String("heightToClip"), QVariant::fromValue<int>(0));
993+ }
994+// qDebug() << "ListViewWithPageHeader::layout" << item->m_item;
995+ pos += item->height();
996+ ++modelIndex;
997+ }
998+
999+ // Second step of section sticky item positioning
1000+ // Look at the next section header, check if it's pushing up the sticky one
1001+ if (m_topSectionItem) {
1002+ if (firstReallyVisibleItem >= 0) {
1003+ for (int i = firstReallyVisibleItem - m_firstVisibleIndex + 1; i < m_visibleItems.count(); ++i) {
1004+ ListItem *item = m_visibleItems[i];
1005+ if (item->m_sectionItem) {
1006+ if (m_topSectionItem->y() + m_topSectionItem->height() > item->y()) {
1007+ m_topSectionItem->setY(item->y() - m_topSectionItem->height());
1008+ }
1009+ break;
1010+ }
1011+ }
1012+ }
1013+ }
1014+ }
1015+ m_inLayout = false;
1016+}
1017+
1018+void ListViewWithPageHeader::updatePolish()
1019+{
1020+ Q_FOREACH(ListItem *item, m_itemsToRelease)
1021+ reallyReleaseItem(item);
1022+ m_itemsToRelease.clear();
1023+
1024+ if (!model())
1025+ return;
1026+
1027+ layout();
1028+
1029+ refill();
1030+
1031+ if (m_contentHeightDirty) {
1032+ qreal contentHeight;
1033+ if (m_visibleItems.isEmpty()) {
1034+ contentHeight = m_headerItem ? m_headerItem->height() : 0;
1035+ } else {
1036+ const int modelCount = model()->rowCount();
1037+ const int visibleItems = m_visibleItems.count();
1038+ const int lastValidIndex = m_firstVisibleIndex + visibleItems - 1;
1039+ qreal nonCreatedHeight = 0;
1040+ if (lastValidIndex != modelCount - 1) {
1041+ const int visibleItems = m_visibleItems.count();
1042+ qreal visibleItemsHeight = 0;
1043+ Q_FOREACH(ListItem *item, m_visibleItems) {
1044+ visibleItemsHeight += item->height();
1045+ }
1046+ const int unknownSizes = modelCount - (m_firstVisibleIndex + visibleItems);
1047+ nonCreatedHeight = unknownSizes * visibleItemsHeight / visibleItems;
1048+ }
1049+ ListItem *item = m_visibleItems.last();
1050+ contentHeight = nonCreatedHeight + item->y() + item->height() + m_clipItem->y();
1051+ if (m_firstVisibleIndex != 0) {
1052+ // Make sure that if we are shrinking we tell the view we still fit
1053+ m_minYExtent = qMax(m_minYExtent, -(contentHeight - height()));
1054+ }
1055+ }
1056+
1057+ m_contentHeightDirty = false;
1058+ setContentHeight(contentHeight);
1059+ }
1060+}
1061+
1062+#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 @@
21#include "AxisVelocityCalculator.h"
21#include "AxisVelocityCalculator.h"
22#include <QtCore/QElapsedTimer>
22#include <QtCore/QElapsedTimer>
23
23
24−class RealTimeSource : public AxisVelocityCalculator::TimeSource {
24+class RealTimeSource : public UbuntuGestures::TimeSource {
25public:
25public:
26− RealTimeSource() {
26+ RealTimeSource()
27+ : UbuntuGestures::TimeSource() {
27 m_timer.start();
28 m_timer.start();
28 }
29 }
29 virtual qint64 msecsSinceReference() {
30 virtual qint64 msecsSinceReference() {
@@ -33,23 +34,17 @@ private:
33 QElapsedTimer m_timer;
34 QElapsedTimer m_timer;
34};
35};
35
36
36−
37AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
37AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
38− : AxisVelocityCalculator(new RealTimeSource, parent)
39−{
40−}
41−
42−AxisVelocityCalculator::AxisVelocityCalculator(TimeSource *timeSource, QObject *parent)
43 : QObject(parent)
38 : QObject(parent)
44− , m_timeSource(timeSource)
39+ , m_timeSource(new RealTimeSource)
45 , m_trackedPosition(0.0)
40 , m_trackedPosition(0.0)
46{
41{
42+ m_timeSource->setParent(this);
47 reset();
43 reset();
48}
44}
49
45
50AxisVelocityCalculator::~AxisVelocityCalculator()
46AxisVelocityCalculator::~AxisVelocityCalculator()
51{
47{
52− delete m_timeSource;
53}
48}
54
49
55qreal AxisVelocityCalculator::trackedPosition() const
50qreal AxisVelocityCalculator::trackedPosition() const
@@ -59,13 +54,17 @@ qreal AxisVelocityCalculator::trackedPosition() const
59
54
60void AxisVelocityCalculator::setTrackedPosition(qreal newPosition)
55void AxisVelocityCalculator::setTrackedPosition(qreal newPosition)
61{
56{
57+ processMovement(newPosition - m_trackedPosition);
58+
62− if (newPosition == m_trackedPosition) {
59+ if (newPosition != m_trackedPosition) {
63− return;
60+ m_trackedPosition = newPosition;
61+ Q_EMIT trackedPositionChanged(newPosition);
64 }
62 }
63+}
65
64
65+void AxisVelocityCalculator::updateIdleTime()
66+{
66− processMovement(newPosition - m_trackedPosition);
67+ processMovement(0);
67− m_trackedPosition = newPosition;
68− Q_EMIT trackedPositionChanged(newPosition);
69}
68}
70
69
71void AxisVelocityCalculator::processMovement(qreal movement)
70void AxisVelocityCalculator::processMovement(qreal movement)
@@ -83,11 +82,12 @@ void AxisVelocityCalculator::processMovement(qreal movement)
83 m_samplesWrite = (m_samplesWrite + 1) % MAX_SAMPLES;
82 m_samplesWrite = (m_samplesWrite + 1) % MAX_SAMPLES;
84}
83}
85
84
86−qreal AxisVelocityCalculator::calculate() const
85+qreal AxisVelocityCalculator::calculate()
87{
86{
88 if (numSamples() < MIN_SAMPLES_NEEDED) {
87 if (numSamples() < MIN_SAMPLES_NEEDED) {
89 return 0.0;
88 return 0.0;
90 }
89 }
90+ updateIdleTime(); // consider the time elapsed since the last update and now
91
91
92 int lastIndex;
92 int lastIndex;
93 if (m_samplesWrite == 0) {
93 if (m_samplesWrite == 0) {
@@ -141,3 +141,18 @@ int AxisVelocityCalculator::numSamples() const
141 }
141 }
142 }
142 }
143}
143}
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 @@
25#include <stdint.h>
25#include <stdint.h>
26#include <QtCore/QObject>
26#include <QtCore/QObject>
27
27
28+namespace UbuntuGestures {
29+/*
30+ Interface for a time source.
31+ */
32+class UBUNTUGESTURES_EXPORT TimeSource : public QObject {
33+ Q_OBJECT
34+public:
35+ virtual ~TimeSource() {}
36+ /* Returns the current time in milliseconds since some reference time in the past. */
37+ virtual qint64 msecsSinceReference() = 0;
38+};
39+}
40+
28/*
41/*
29 Estimates the current velocity of a finger based on recent movement along an axis
42 Estimates the current velocity of a finger based on recent movement along an axis
30
43
@@ -59,27 +72,11 @@ class UBUNTUGESTURES_EXPORT AxisVelocityCalculator : public QObject
59 NOTIFY trackedPositionChanged)
72 NOTIFY trackedPositionChanged)
60public:
73public:
61
74
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−
72 /*
75 /*
73 Regular constructor
76 Regular constructor
74 */
77 */
75 AxisVelocityCalculator(QObject *parent = 0);
78 AxisVelocityCalculator(QObject *parent = 0);
76
79
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−
83 virtual ~AxisVelocityCalculator();
80 virtual ~AxisVelocityCalculator();
84
81
85 qreal trackedPosition() const;
82 qreal trackedPosition() const;
@@ -88,7 +85,7 @@ public:
88 /*
85 /*
89 Calculates the finger velocity, in axis units/millisecond
86 Calculates the finger velocity, in axis units/millisecond
90 */
87 */
91− Q_INVOKABLE qreal calculate() const;
88+ Q_INVOKABLE qreal calculate();
92
89
93 /*
90 /*
94 Removes all stored movements from previous calls to setTrackedPosition()
91 Removes all stored movements from previous calls to setTrackedPosition()
@@ -97,6 +94,11 @@ public:
97
94
98 int numSamples() const;
95 int numSamples() const;
99
96
97+ /*
98+ Replaces the TimeSource with the given one. Useful for testing purposes.
99+ */
100+ void setTimeSource(UbuntuGestures::TimeSource *timeSource);
101+
100 /*
102 /*
101 The minimum amount of samples needed for a velocity calculation.
103 The minimum amount of samples needed for a velocity calculation.
102 */
104 */
@@ -105,18 +107,27 @@ public:
105 /*
107 /*
106 Maximum number of movement samples stored
108 Maximum number of movement samples stored
107 */
109 */
108− static const int MAX_SAMPLES = 10;
110+ static const int MAX_SAMPLES = 50;
109
111
110 /*
112 /*
111 Age of the oldest sample considered in the velocity calculations, in
113 Age of the oldest sample considered in the velocity calculations, in
112 milliseconds, compared to the most recent one.
114 milliseconds, compared to the most recent one.
113 */
115 */
114− static const int AGE_OLDEST_SAMPLE = 200;
116+ static const int AGE_OLDEST_SAMPLE = 100;
115
117
116Q_SIGNALS:
118Q_SIGNALS:
117 void trackedPositionChanged(qreal value);
119 void trackedPositionChanged(qreal value);
118
120
119private:
121private:
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+
120 /*
131 /*
121 How much the finger has moved since processMovement() was last called.
132 How much the finger has moved since processMovement() was last called.
122 */
133 */
@@ -134,7 +145,7 @@ private:
134 int m_samplesRead; /* index of the oldest sample available. -1 if buffer is empty */
145 int m_samplesRead; /* index of the oldest sample available. -1 if buffer is empty */
135 int m_samplesWrite; /* index where the next sample will be written */
146 int m_samplesWrite; /* index where the next sample will be written */
136
147
137− TimeSource *m_timeSource;
148+ UbuntuGestures::TimeSource *m_timeSource;
138
149
139 qreal m_trackedPosition;
150 qreal m_trackedPosition;
140};
151};
plugins/Ubuntu/Gestures/CMakeLists.txt+2−2
@@ -27,9 +27,9 @@ add_custom_target(UbuntuGestureQmlDirFile ALL
27)
27)
28
28
29install(TARGETS UbuntuGestureQml
29install(TARGETS UbuntuGestureQml
30− DESTINATION ${SHELL_APP_DIR}/plugins/Ubuntu/Gestures
30+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Ubuntu/Gestures
31 )
31 )
32
32
33install(FILES qmldir
33install(FILES qmldir
34− DESTINATION ${SHELL_APP_DIR}/plugins/Ubuntu/Gestures
34+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Ubuntu/Gestures
35 )
35 )
plugins/Ubuntu/Gestures/Direction.cpp+5
@@ -25,3 +25,8 @@ bool Direction::isVertical(Direction::Type type)
25{
25{
26 return type == Direction::Upwards || type == Direction::Downwards;
26 return type == Direction::Upwards || type == Direction::Downwards;
27}
27}
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:
38
38
39 Q_INVOKABLE static bool isHorizontal(Direction::Type type);
39 Q_INVOKABLE static bool isHorizontal(Direction::Type type);
40 Q_INVOKABLE static bool isVertical(Direction::Type type);
40 Q_INVOKABLE static bool isVertical(Direction::Type type);
41+ Q_INVOKABLE static bool isPositive(Direction::Type type);
41};
42};
42
43
43#endif // DIRECTION_H
44#endif // DIRECTION_H
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+61−10
@@ -141,12 +141,9 @@ void DirectionalDragArea::setRecognitionTimer(UbuntuGestures::AbstractTimer *tim
141 }
141 }
142}
142}
143
143
144−void DirectionalDragArea::setAxisVelocityCalculator(AxisVelocityCalculator *newVelCalc)
144+void DirectionalDragArea::setTimeSource(UbuntuGestures::TimeSource *timeSource)
145{
145{
146− if (m_velocityCalculator->parent() == this)
146+ m_velocityCalculator->setTimeSource(timeSource);
147− delete m_velocityCalculator;
148−
149− m_velocityCalculator = newVelCalc;
150}
147}
151
148
152qreal DirectionalDragArea::distance() const
149qreal DirectionalDragArea::distance() const
@@ -158,6 +155,15 @@ qreal DirectionalDragArea::distance() const
158 }
155 }
159}
156}
160
157
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+
161qreal DirectionalDragArea::touchX() const
167qreal DirectionalDragArea::touchX() const
162{
168{
163 return m_previousPos.x();
169 return m_previousPos.x();
@@ -168,6 +174,16 @@ qreal DirectionalDragArea::touchY() const
168 return m_previousPos.y();
174 return m_previousPos.y();
169}
175}
170
176
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+
171void DirectionalDragArea::touchEvent(QTouchEvent *event)
187void DirectionalDragArea::touchEvent(QTouchEvent *event)
172{
188{
173 if (!isEnabled() || !isVisible()) {
189 if (!isEnabled() || !isVisible()) {
@@ -195,15 +211,22 @@ void DirectionalDragArea::touchEvent_absent(QTouchEvent *event)
195{
211{
196 if ((event->touchPointStates() && (Qt::TouchPointPressed || Qt::TouchPointMoved))
212 if ((event->touchPointStates() && (Qt::TouchPointPressed || Qt::TouchPointMoved))
197 && event->touchPoints().count() == 1) {
213 && event->touchPoints().count() == 1) {
214+ const QTouchEvent::TouchPoint &touchPoint = event->touchPoints()[0];
198− m_startPos = event->touchPoints()[0].pos();
215+ m_startPos = touchPoint.pos();
216+ m_startScenePos = touchPoint.scenePos();
199− m_touchId = event->touchPoints()[0].id();
217+ m_touchId = touchPoint.id();
200 m_dampedPos.reset(m_startPos);
218 m_dampedPos.reset(m_startPos);
201 updateVelocityCalculator(m_startPos);
219 updateVelocityCalculator(m_startPos);
202 m_velocityCalculator->reset();
220 m_velocityCalculator->reset();
203 m_numSamplesOnLastSpeedCheck = 0;
221 m_numSamplesOnLastSpeedCheck = 0;
204 m_silenceTime = 0;
222 m_silenceTime = 0;
205 setPreviousPos(m_startPos);
223 setPreviousPos(m_startPos);
224+ setPreviousScenePos(m_startScenePos);
225+
226+ if (m_distanceThreshold > 0)
206− setStatus(Undecided);
227+ setStatus(Undecided);
228+ else
229+ setStatus(Recognized);
207 }
230 }
208}
231}
209
232
@@ -241,6 +264,7 @@ void DirectionalDragArea::touchEvent_undecided(QTouchEvent *event)
241 }
264 }
242
265
243 setPreviousPos(touchPos);
266 setPreviousPos(touchPos);
267+ setPreviousScenePos(touchPoint->scenePos());
244
268
245 if (movedFarEnough(touchPos)) {
269 if (movedFarEnough(touchPos)) {
246 setStatus(Recognized);
270 setStatus(Recognized);
@@ -252,6 +276,7 @@ void DirectionalDragArea::touchEvent_recognized(QTouchEvent *event)
252 const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
276 const QTouchEvent::TouchPoint *touchPoint = fetchTargetTouchPoint(event);
253
277
254 setPreviousPos(touchPoint->pos());
278 setPreviousPos(touchPoint->pos());
279+ setPreviousScenePos(touchPoint->scenePos());
255
280
256 if (touchPoint->state() == Qt::TouchPointReleased) {
281 if (touchPoint->state() == Qt::TouchPointReleased) {
257 setStatus(WaitingForTouch);
282 setStatus(WaitingForTouch);
@@ -366,6 +391,10 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
366 m_recognitionTimer->start();
391 m_recognitionTimer->start();
367 Q_EMIT draggingChanged(true);
392 Q_EMIT draggingChanged(true);
368 break;
393 break;
394+ case Recognized:
395+ if (oldStatus == WaitingForTouch)
396+ Q_EMIT draggingChanged(true);
397+ break;
369 case Rejected:
398 case Rejected:
370 Q_EMIT draggingChanged(false);
399 Q_EMIT draggingChanged(false);
371 break;
400 break;
@@ -375,7 +404,7 @@ void DirectionalDragArea::setStatus(DirectionalDragArea::Status newStatus)
375 }
404 }
376}
405}
377
406
378−void DirectionalDragArea::setPreviousPos(QPointF point)
407+void DirectionalDragArea::setPreviousPos(const QPointF &point)
379{
408{
380 Q_ASSERT(m_status != Rejected);
409 Q_ASSERT(m_status != Rejected);
381
410
@@ -397,7 +426,29 @@ void DirectionalDragArea::setPreviousPos(QPointF point)
397 }
426 }
398}
427}
399
428
429+void DirectionalDragArea::setPreviousScenePos(const 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+
400−void DirectionalDragArea::updateVelocityCalculator(QPointF point)
451+void DirectionalDragArea::updateVelocityCalculator(const QPointF &point)
401{
452{
402 if (Direction::isHorizontal(m_direction)) {
453 if (Direction::isHorizontal(m_direction)) {
403 m_velocityCalculator->setTrackedPosition(point.x());
454 m_velocityCalculator->setTrackedPosition(point.x());
plugins/Ubuntu/Gestures/DirectionalDragArea.h+23−5
@@ -60,10 +60,18 @@ class UBUNTUGESTURES_EXPORT DirectionalDragArea : public QQuickItem {
60 // DirectionalDragArea's direction.
60 // DirectionalDragArea's direction.
61 Q_PROPERTY(qreal distance READ distance NOTIFY distanceChanged)
61 Q_PROPERTY(qreal distance READ distance NOTIFY distanceChanged)
62
62
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+
63− // Position of the touch point performing the drag.
67+ // Position of the touch point performing the drag relative to this item.
64 Q_PROPERTY(qreal touchX READ touchX NOTIFY touchXChanged)
68 Q_PROPERTY(qreal touchX READ touchX NOTIFY touchXChanged)
65 Q_PROPERTY(qreal touchY READ touchY NOTIFY touchYChanged)
69 Q_PROPERTY(qreal touchY READ touchY NOTIFY touchYChanged)
66
70
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+
67 // The current status of the directional drag gesture area.
75 // The current status of the directional drag gesture area.
68 Q_PROPERTY(Status status READ status NOTIFY statusChanged)
76 Q_PROPERTY(Status status READ status NOTIFY statusChanged)
69
77
@@ -146,10 +154,14 @@ public:
146 Status status() const { return m_status; }
154 Status status() const { return m_status; }
147
155
148 qreal distance() const;
156 qreal distance() const;
157+ qreal sceneDistance() const;
149
158
150 qreal touchX() const;
159 qreal touchX() const;
151 qreal touchY() const;
160 qreal touchY() const;
152
161
162+ qreal touchSceneX() const;
163+ qreal touchSceneY() const;
164+
153 bool dragging() const { return (m_status == Undecided) || (m_status == Recognized); }
165 bool dragging() const { return (m_status == Undecided) || (m_status == Recognized); }
154
166
155 qreal maxDeviation() const { return m_dampedPos.maxDelta(); }
167 qreal maxDeviation() const { return m_dampedPos.maxDelta(); }
@@ -172,14 +184,15 @@ public:
172 // Useful for providing a fake timer when testing.
184 // Useful for providing a fake timer when testing.
173 void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
185 void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
174
186
175− // Useful for testing, where a calculator with a fake time source can be supplied
187+ // Useful for testing, where a fake time source can be supplied
176− void setAxisVelocityCalculator(AxisVelocityCalculator *velCalc);
188+ void setTimeSource(UbuntuGestures::TimeSource *timeSource);
177
189
178Q_SIGNALS:
190Q_SIGNALS:
179 void directionChanged(Direction::Type direction);
191 void directionChanged(Direction::Type direction);
180 void statusChanged(Status value);
192 void statusChanged(Status value);
181 void draggingChanged(bool value);
193 void draggingChanged(bool value);
182 void distanceChanged(qreal value);
194 void distanceChanged(qreal value);
195+ void sceneDistanceChanged(qreal value);
183 void maxDeviationChanged(qreal value);
196 void maxDeviationChanged(qreal value);
184 void wideningAngleChanged(qreal value);
197 void wideningAngleChanged(qreal value);
185 void distanceThresholdChanged(qreal value);
198 void distanceThresholdChanged(qreal value);
@@ -187,6 +200,8 @@ Q_SIGNALS:
187 void maxSilenceTimeChanged(int value);
200 void maxSilenceTimeChanged(int value);
188 void touchXChanged(qreal value);
201 void touchXChanged(qreal value);
189 void touchYChanged(qreal value);
202 void touchYChanged(qreal value);
203+ void touchSceneXChanged(qreal value);
204+ void touchSceneYChanged(qreal value);
190
205
191protected:
206protected:
192 virtual void touchEvent(QTouchEvent *event);
207 virtual void touchEvent(QTouchEvent *event);
@@ -204,13 +219,16 @@ private:
204 bool movedFarEnough(const QPointF &point) const;
219 bool movedFarEnough(const QPointF &point) const;
205 const QTouchEvent::TouchPoint *fetchTargetTouchPoint(QTouchEvent *event);
220 const QTouchEvent::TouchPoint *fetchTargetTouchPoint(QTouchEvent *event);
206 void setStatus(Status newStatus);
221 void setStatus(Status newStatus);
207− void setPreviousPos(QPointF point);
222+ void setPreviousPos(const QPointF &point);
223+ void setPreviousScenePos(const QPointF &point);
208− void updateVelocityCalculator(QPointF point);
224+ void updateVelocityCalculator(const QPointF &point);
209
225
210 Status m_status;
226 Status m_status;
211
227
212 QPointF m_startPos;
228 QPointF m_startPos;
229+ QPointF m_startScenePos;
213 QPointF m_previousPos;
230 QPointF m_previousPos;
231+ QPointF m_previousScenePos;
214 int m_touchId;
232 int m_touchId;
215
233
216 // A movement damper is used in some of the gesture recognition calculations
234 // A movement damper is used in some of the gesture recognition calculations
plugins/Unity/CMakeLists.txt+10−2
@@ -30,6 +30,14 @@ set(QMLPLUGIN_SRC
30 ratingsfilter.cpp
30 ratingsfilter.cpp
31 bottombarvisibilitycommunicatorshell.cpp
31 bottombarvisibilitycommunicatorshell.cpp
32 launchermodel.cpp
32 launchermodel.cpp
33+ applicationpreview.cpp
34+ genericpreview.cpp
35+ moviepreview.cpp
36+ musicpreview.cpp
37+ preview.cpp
38+ previewaction.cpp
39+ previewinfohint.cpp
40+ variantutils.cpp
33 )
41 )
34
42
35add_library(Unity-qml MODULE
43add_library(Unity-qml MODULE
@@ -51,9 +59,9 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
51 )
59 )
52
60
53install(TARGETS Unity-qml
61install(TARGETS Unity-qml
54− DESTINATION ${SHELL_APP_DIR}/plugins/Unity
62+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity
55 )
63 )
56
64
57install(FILES qmldir
65install(FILES qmldir
58− DESTINATION ${SHELL_APP_DIR}/plugins/Unity
66+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity
59 )
67 )
plugins/Unity/applicationpreview.cppnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+// local
21+#include "applicationpreview.h"
22+
23+#include <QDebug>
24+
25+ApplicationPreview::ApplicationPreview(QObject *parent):
26+ Preview(parent),
27+ m_unityAppPreview(nullptr)
28+{
29+}
30+
31+QString ApplicationPreview::lastUpdate() const
32+{
33+ if (m_unityAppPreview) {
34+ return QString::fromStdString(m_unityAppPreview->last_update());
35+ } else {
36+ qWarning() << "Preview not set";
37+ }
38+ return QString();
39+}
40+
41+QString ApplicationPreview::copyright() const
42+{
43+ if (m_unityAppPreview) {
44+ return QString::fromStdString(m_unityAppPreview->copyright());
45+ } else {
46+ qWarning() << "Preview not set";
47+ }
48+ return QString();
49+}
50+
51+QString ApplicationPreview::license() const
52+{
53+ if (m_unityAppPreview) {
54+ return QString::fromStdString(m_unityAppPreview->license());
55+ } else {
56+ qWarning() << "Preview not set";
57+ }
58+ return QString();
59+}
60+
61+QString ApplicationPreview::appIcon() const
62+{
63+ if (m_unityAppPreview) {
64+ return QString::fromUtf8(g_icon_to_string(m_unityAppPreview->app_icon()));
65+ } else {
66+ qWarning() << "Preview not set";
67+ }
68+ return QString();
69+}
70+
71+float ApplicationPreview::rating() const
72+{
73+ if (m_unityAppPreview) {
74+ return m_unityAppPreview->rating();
75+ } else {
76+ qWarning() << "Preview not set";
77+ }
78+ return 0.0f;
79+}
80+
81+unsigned int ApplicationPreview::numRatings() const
82+{
83+ if (m_unityAppPreview) {
84+ return m_unityAppPreview->num_ratings();
85+ } else {
86+ qWarning() << "Preview not set";
87+ }
88+ return 0;
89+}
90+
91+void ApplicationPreview::setUnityPreview(unity::dash::Preview::Ptr unityPreview)
92+{
93+ m_unityAppPreview = std::dynamic_pointer_cast<unity::dash::ApplicationPreview>(unityPreview);
94+
95+ Q_EMIT previewChanged();
96+}
plugins/Unity/applicationpreview.hnew file+66
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef APPLICATIONPREVIEW_H
21+#define APPLICATIONPREVIEW_H
22+
23+// local
24+#include "preview.h"
25+
26+// Qt
27+#include <QObject>
28+#include <QMetaType>
29+
30+// libunity-core
31+#include <UnityCore/ApplicationPreview.h>
32+
33+class Q_DECL_EXPORT ApplicationPreview: public Preview
34+{
35+ Q_OBJECT
36+
37+ Q_PROPERTY(QString lastUpdate READ lastUpdate NOTIFY previewChanged)
38+ Q_PROPERTY(QString copyright READ copyright NOTIFY previewChanged)
39+ Q_PROPERTY(QString license READ license NOTIFY previewChanged)
40+ Q_PROPERTY(QString appIcon READ appIcon NOTIFY previewChanged)
41+ Q_PROPERTY(float rating READ rating NOTIFY previewChanged)
42+ Q_PROPERTY(unsigned int numRatings READ numRatings NOTIFY previewChanged)
43+
44+public:
45+ explicit ApplicationPreview(QObject *parent = 0);
46+
47+ QString lastUpdate() const;
48+ QString copyright() const;
49+ QString license() const;
50+ QString appIcon() const;
51+ float rating() const;
52+ unsigned int numRatings() const;
53+
54+Q_SIGNALS:
55+ void previewChanged();
56+
57+protected:
58+ void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
59+
60+private:
61+ unity::dash::ApplicationPreview::Ptr m_unityAppPreview;
62+};
63+
64+Q_DECLARE_METATYPE(ApplicationPreview *)
65+
66+#endif
plugins/Unity/categories.cpp+26−17
@@ -30,6 +30,7 @@ Categories::Categories(QObject* parent)
30 m_roles[Categories::RoleName] = "name";
30 m_roles[Categories::RoleName] = "name";
31 m_roles[Categories::RoleIcon] = "icon";
31 m_roles[Categories::RoleIcon] = "icon";
32 m_roles[Categories::RoleRenderer] = "renderer";
32 m_roles[Categories::RoleRenderer] = "renderer";
33+ m_roles[Categories::RoleContentType] = "content_type";
33 m_roles[Categories::RoleHints] = "hints";
34 m_roles[Categories::RoleHints] = "hints";
34 m_roles[Categories::RoleResults] = "results";
35 m_roles[Categories::RoleResults] = "results";
35 m_roles[Categories::RoleCount] = "count";
36 m_roles[Categories::RoleCount] = "count";
@@ -111,22 +112,30 @@ Categories::data(const QModelIndex& index, int role) const
111 return QVariant();
112 return QVariant();
112 }
113 }
113
114
115+ switch (role) {
114− if (role == RoleId) {
116+ case RoleId:
115− return QVariant::fromValue(index.row());
117+ return QVariant::fromValue(index.row());
116− } else if (role == RoleName) {
118+ case RoleName:
117− return QVariant::fromValue(DeeListModel::data(index, 1)); //DISPLAY_NAME
119+ return QVariant::fromValue(DeeListModel::data(index, 1)); //DISPLAY_NAME
118− } else if (role == RoleIcon) {
120+ case RoleIcon:
119− return QVariant::fromValue(DeeListModel::data(index, 2)); //ICON_HINT
121+ return QVariant::fromValue(DeeListModel::data(index, 2)); //ICON_HINT
120− } else if (role == RoleRenderer) {
122+ case RoleRenderer:
121− return QVariant::fromValue(DeeListModel::data(index, 3)); //RENDERER_NAME
123+ return QVariant::fromValue(DeeListModel::data(index, 3)); //RENDERER_NAME
124+ case RoleContentType:
125+ {
126+ auto hints = QVariant::fromValue(DeeListModel::data(index, 4)).toHash();
127+ return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
128+ }
122− } else if (role == RoleHints) {
129+ case RoleHints:
123− return QVariant::fromValue(DeeListModel::data(index, 4)); //HINTS
130+ return QVariant::fromValue(DeeListModel::data(index, 4)); //HINTS
124− } else if (role == RoleResults) {
131+ case RoleResults:
125− return QVariant::fromValue(getFilter(index.row()));
132+ return QVariant::fromValue(getFilter(index.row()));
126− } else if (role == RoleCount) {
133+ case RoleCount:
134+ {
127− CategoryFilter* filter = getFilter(index.row());
135+ CategoryFilter* filter = getFilter(index.row());
128− return QVariant::fromValue(filter->rowCount());
136+ return QVariant::fromValue(filter->rowCount());
129− } else {
137+ }
138+ default:
130− return QVariant();
139+ return QVariant();
131 }
140 }
132}
141}
plugins/Unity/categories.h+1
@@ -46,6 +46,7 @@ public:
46 RoleName,
46 RoleName,
47 RoleIcon,
47 RoleIcon,
48 RoleRenderer,
48 RoleRenderer,
49+ RoleContentType,
49 RoleHints,
50 RoleHints,
50 RoleResults,
51 RoleResults,
51 RoleCount
52 RoleCount
Notifications/timings.js → plugins/Unity/genericpreview.cpprenamed+9−6
@@ -1,6 +1,9 @@
1/*
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
3 *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
4 * This program is free software; you can redistribute it and/or modify
7 * 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
8 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
9 * the Free Software Foundation; version 3.
@@ -14,10 +17,10 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
18 */
16
19
17−var rhythm = 700;
20+// local
18−var fastBeat = 0.5 * rhythm;
21+#include "genericpreview.h"
19−var snapBeat = 0.5 * fastBeat;
20−var slowBeat = rhythm;
21−var sleepyBeat = slowBeat * 2;
22
22
23−var easing = Easing.OutQuint;
23+GenericPreview::GenericPreview(QObject *parent):
24+ Preview(parent)
25+{
26+}
plugins/Unity/genericpreview.hnew file+40
@@ -0,0 +1,40 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef GENERICPREVIEW_H
21+#define GENERICPREVIEW_H
22+
23+// local
24+#include "preview.h"
25+
26+// Qt
27+#include <QObject>
28+#include <QMetaType>
29+
30+class GenericPreview : public Preview
31+{
32+ Q_OBJECT
33+
34+public:
35+ explicit GenericPreview(QObject *parent = 0);
36+};
37+
38+Q_DECLARE_METATYPE(GenericPreview *)
39+
40+#endif
plugins/Unity/moviepreview.cppnew file+67
@@ -0,0 +1,67 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+// local
21+#include "moviepreview.h"
22+
23+// Qt
24+#include <QDebug>
25+
26+MoviePreview::MoviePreview(QObject *parent):
27+ Preview(parent),
28+ m_unityMoviePreview(nullptr)
29+{
30+}
31+
32+QString MoviePreview::year() const
33+{
34+ if (m_unityMoviePreview) {
35+ return QString::fromStdString(m_unityMoviePreview->year());
36+ } else {
37+ qWarning() << "Preview not set";
38+ }
39+ return QString();
40+}
41+
42+float MoviePreview::rating() const
43+{
44+ if (m_unityMoviePreview) {
45+ return m_unityMoviePreview->rating();
46+ } else {
47+ qWarning() << "Preview not set";
48+ }
49+ return 0.0f;
50+}
51+
52+unsigned int MoviePreview::numRatings() const
53+{
54+ if (m_unityMoviePreview) {
55+ return m_unityMoviePreview->num_ratings();
56+ } else {
57+ qWarning() << "Preview not set";
58+ }
59+ return 0;
60+}
61+
62+void MoviePreview::setUnityPreview(unity::dash::Preview::Ptr unityPreview)
63+{
64+ m_unityMoviePreview = std::dynamic_pointer_cast<unity::dash::MoviePreview>(unityPreview);
65+
66+ Q_EMIT previewChanged();
67+}
plugins/Unity/moviepreview.hnew file+60
@@ -0,0 +1,60 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef MOVIEPREVIEW_H
21+#define MOVIEPREVIEW_H
22+
23+// local
24+#include "preview.h"
25+
26+// Qt
27+#include <QObject>
28+#include <QMetaType>
29+
30+// libunity-core
31+#include <UnityCore/MoviePreview.h>
32+
33+class Q_DECL_EXPORT MoviePreview: public Preview
34+{
35+ Q_OBJECT
36+
37+ Q_PROPERTY(QString year READ year NOTIFY previewChanged)
38+ Q_PROPERTY(float rating READ rating NOTIFY previewChanged)
39+ Q_PROPERTY(unsigned int numRatings READ numRatings NOTIFY previewChanged)
40+
41+public:
42+ explicit MoviePreview(QObject *parent = 0);
43+
44+ QString year() const;
45+ float rating() const;
46+ unsigned int numRatings() const;
47+
48+Q_SIGNALS:
49+ void previewChanged();
50+
51+protected:
52+ void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
53+
54+private:
55+ unity::dash::MoviePreview::Ptr m_unityMoviePreview;
56+};
57+
58+Q_DECLARE_METATYPE(MoviePreview *)
59+
60+#endif
plugins/Unity/musicpreview.cppnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#include "musicpreview.h"
21+#include <QDebug>
22+
23+// dee-qt
24+#include "deelistmodel.h"
25+
26+MusicPreview::MusicPreview(QObject *parent):
27+ Preview(parent),
28+ m_unityMusicPreview(nullptr)
29+{
30+ m_tracks = new DeeListModel(this);
31+}
32+
33+void MusicPreview::setUnityPreview(unity::dash::Preview::Ptr unityPreview)
34+{
35+ m_unityMusicPreview = std::dynamic_pointer_cast<unity::dash::MusicPreview>(unityPreview);
36+ m_tracks->setModel(m_unityMusicPreview->GetTracksModel()->model());
37+ m_unityMusicPreview->GetTracksModel()->model.changed.connect(sigc::mem_fun(this, &MusicPreview::onTracksModelChanged));
38+
39+ Q_EMIT previewChanged();
40+ Q_EMIT tracksChanged();
41+}
42+
43+DeeListModel* MusicPreview::tracks() const
44+{
45+ if (m_unityMusicPreview == nullptr) {
46+ qWarning() << "Preview not set";
47+ }
48+ return m_tracks;
49+}
50+
51+void MusicPreview::onTracksModelChanged(unity::glib::Object<DeeModel> /* model */)
52+{
53+ m_tracks->setModel(m_unityMusicPreview->GetTracksModel()->model());
54+}
plugins/Unity/musicpreview.hnew file+62
@@ -0,0 +1,62 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef MUSICPREVIEW_H
21+#define MUSICPREVIEW_H
22+
23+// local
24+#include "preview.h"
25+
26+// Qt
27+#include <QObject>
28+#include <QMetaType>
29+
30+// libunity-core
31+#include <UnityCore/MusicPreview.h>
32+
33+class DeeListModel;
34+
35+class Q_DECL_EXPORT MusicPreview: public Preview
36+{
37+ Q_OBJECT
38+
39+ Q_PROPERTY(DeeListModel* tracks READ tracks NOTIFY tracksChanged)
40+
41+public:
42+ explicit MusicPreview(QObject *parent = 0);
43+
44+ DeeListModel* tracks() const;
45+
46+Q_SIGNALS:
47+ void tracksChanged();
48+
49+protected:
50+ void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
51+
52+private Q_SLOTS:
53+ void onTracksModelChanged(unity::glib::Object<DeeModel> model);
54+
55+private:
56+ unity::dash::MusicPreview::Ptr m_unityMusicPreview;
57+ DeeListModel *m_tracks;
58+};
59+
60+Q_DECLARE_METATYPE(MusicPreview *)
61+
62+#endif
plugins/Unity/plugin.cpp+6
@@ -24,6 +24,9 @@
24#include "plugin.h"
24#include "plugin.h"
25
25
26// local
26// local
27+#include "preview.h"
28+#include "previewaction.h"
29+#include "previewinfohint.h"
27#include "scope.h"
30#include "scope.h"
28#include "scopes.h"
31#include "scopes.h"
29#include "categories.h"
32#include "categories.h"
@@ -40,6 +43,9 @@ static const char* DBUS_SERVICE = "com.canonical.Shell.BottomBarVisibilityCommun
40void UnityPlugin::registerTypes(const char *uri)
43void UnityPlugin::registerTypes(const char *uri)
41{
44{
42 Q_ASSERT(uri == QLatin1String("Unity"));
45 Q_ASSERT(uri == QLatin1String("Unity"));
46+ qmlRegisterUncreatableType<Preview>(uri, 0, 1, "Preview", "Can't create Preview object in QML.");
47+ qmlRegisterUncreatableType<PreviewAction>(uri, 0, 1, "PreviewAction", "Can't create PreviewAction object in QML.");
48+ qmlRegisterUncreatableType<PreviewInfoHint>(uri, 0, 1, "PreviewInfoHint", "Can't create PreviewInfoHint object in QML.");
43 qmlRegisterType<Scope>(uri, 0, 1, "Scope");
49 qmlRegisterType<Scope>(uri, 0, 1, "Scope");
44 qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
50 qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
45 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
51 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
plugins/Unity/preview.cppnew file+173
@@ -0,0 +1,173 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+// local
21+#include "preview.h"
22+#include "previewaction.h"
23+#include "previewinfohint.h"
24+#include "genericpreview.h"
25+#include "applicationpreview.h"
26+#include "moviepreview.h"
27+#include "musicpreview.h"
28+#include "variantutils.h"
29+
30+// Qt
31+#include <QDebug>
32+#include <QtAlgorithms>
33+
34+#include <UnityCore/GenericPreview.h>
35+#include <UnityCore/ApplicationPreview.h>
36+#include <UnityCore/MoviePreview.h>
37+#include <UnityCore/MusicPreview.h>
38+
39+Preview::Preview(QObject *parent):
40+ QObject(parent),
41+ m_unityPreview(nullptr)
42+{
43+}
44+
45+QString Preview::rendererName() const
46+{
47+ if (m_unityPreview) {
48+ return QString::fromStdString(m_unityPreview->renderer_name());
49+ } else {
50+ qWarning() << "Preview not set";
51+ }
52+ return QString();
53+}
54+
55+QString Preview::title() const
56+{
57+ if (m_unityPreview) {
58+ return QString::fromStdString(m_unityPreview->title());
59+ } else {
60+ qWarning() << "Preview not set";
61+ }
62+ return QString();
63+}
64+
65+QString Preview::subtitle () const
66+{
67+ if (m_unityPreview) {
68+ return QString::fromStdString(m_unityPreview->subtitle());
69+ } else {
70+ qWarning() << "Preview not set";
71+ }
72+ return QString();
73+}
74+
75+QString Preview::description() const
76+{
77+ if (m_unityPreview) {
78+ return QString::fromStdString(m_unityPreview->description());
79+ } else {
80+ qWarning() << "Preview not set";
81+ }
82+ return QString();
83+}
84+
85+QVariant Preview::actions()
86+{
87+ return QVariant::fromValue(m_actions);
88+}
89+
90+QVariant Preview::infoHints()
91+{
92+ return QVariant::fromValue(m_infoHints);
93+}
94+
95+QString Preview::image() const
96+{
97+ if (m_unityPreview) {
98+ return QString::fromUtf8(g_icon_to_string(m_unityPreview->image()));
99+ } else {
100+ qWarning() << "Preview not set";
101+ }
102+ return QString::null;
103+}
104+
105+QString Preview::imageSourceUri() const
106+{
107+ if (m_unityPreview) {
108+ return QString::fromStdString(m_unityPreview->image_source_uri());
109+ } else {
110+ qWarning() << "Preview not set";
111+ }
112+ return QString::null;
113+}
114+
115+Preview* Preview::newFromUnityPreview(unity::dash::Preview::Ptr unityPreview)
116+{
117+ Preview* preview = nullptr;
118+
119+ if (dynamic_cast<unity::dash::GenericPreview *>(unityPreview.get()) != nullptr) {
120+ preview = new GenericPreview();
121+ } else if (dynamic_cast<unity::dash::MusicPreview *>(unityPreview.get()) != nullptr) {
122+ preview = new MusicPreview();
123+ } else if (dynamic_cast<unity::dash::MoviePreview *>(unityPreview.get()) != nullptr) {
124+ preview = new MoviePreview();
125+ } else if (dynamic_cast<unity::dash::ApplicationPreview *>(unityPreview.get()) != nullptr) {
126+ preview = new ApplicationPreview();
127+ } else {
128+ qWarning() << "Unknown preview type: " << typeid(*unityPreview).name();
129+ preview = new GenericPreview();
130+ }
131+
132+ preview->setUnityPreviewBase(unityPreview);
133+ preview->setUnityPreview(unityPreview);
134+
135+ return preview;
136+}
137+
138+void Preview::setUnityPreviewBase(unity::dash::Preview::Ptr unityPreview)
139+{
140+ m_unityPreview = unityPreview;
141+
142+ qDeleteAll(m_infoHints);
143+ m_infoHints.clear();
144+ qDeleteAll(m_actions);
145+ m_actions.clear();
146+
147+ for (auto unityInfoHint: m_unityPreview->GetInfoHints()) {
148+ auto hint = new PreviewInfoHint(this);
149+ hint->setUnityInfoHint(unityInfoHint);
150+ m_infoHints.append(hint);
151+ }
152+
153+ for (auto unityAction: m_unityPreview->GetActions()) {
154+ auto action = new PreviewAction(this);
155+ action->setUnityAction(unityAction);
156+ m_actions.append(action);
157+ }
158+}
159+
160+void Preview::setUnityPreview(unity::dash::Preview::Ptr /* unityPreview */)
161+{
162+ // default implementation does nothing
163+}
164+
165+void Preview::execute(const QString& actionId, const QHash<QString, QVariant>& hints)
166+{
167+ if (m_unityPreview) {
168+ auto unityHints = convertToHintsMap(hints);
169+ m_unityPreview->PerformAction(actionId.toStdString(), unityHints);
170+ } else {
171+ qWarning() << "Preview not set";
172+ }
173+}
plugins/Unity/preview.hnew file+80
@@ -0,0 +1,80 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef PREVIEW_H
21+#define PREVIEW_H
22+
23+// Qt
24+#include <QObject>
25+#include <QString>
26+#include <QMetaType>
27+#include <QList>
28+
29+// libunity-core
30+#include <UnityCore/Preview.h>
31+
32+// local
33+#include "previewaction.h"
34+
35+class Q_DECL_EXPORT Preview : public QObject
36+{
37+ Q_OBJECT
38+
39+ Q_PROPERTY(QString rendererName READ rendererName NOTIFY previewChanged)
40+ Q_PROPERTY(QString title READ title NOTIFY previewChanged)
41+ Q_PROPERTY(QString subtitle READ subtitle NOTIFY previewChanged)
42+ Q_PROPERTY(QString description READ description NOTIFY previewChanged)
43+ Q_PROPERTY(QVariant actions READ actions NOTIFY previewChanged)
44+ Q_PROPERTY(QVariant infoHints READ infoHints NOTIFY previewChanged)
45+ Q_PROPERTY(QString image READ image NOTIFY previewChanged)
46+ Q_PROPERTY(QString imageSourceUri READ imageSourceUri NOTIFY previewChanged)
47+
48+public:
49+ explicit Preview(QObject *parent = 0);
50+ static Preview* newFromUnityPreview(unity::dash::Preview::Ptr unityPreview);
51+
52+ QString rendererName() const;
53+ QString title() const;
54+ QString subtitle() const;
55+ QString description() const;
56+ QVariant actions();
57+ QVariant infoHints();
58+ QString image() const;
59+ QString imageSourceUri() const;
60+
61+ Q_INVOKABLE void execute(const QString& actionId, const QHash<QString, QVariant>& hints);
62+
63+Q_SIGNALS:
64+ void previewChanged();
65+
66+protected:
67+ virtual void setUnityPreview(unity::dash::Preview::Ptr unityPreview);
68+
69+ unity::dash::Preview::Ptr m_unityPreview;
70+
71+private:
72+ void setUnityPreviewBase(unity::dash::Preview::Ptr unityPreview);
73+
74+ QList<QObject *> m_actions;
75+ QList<QObject *> m_infoHints;
76+};
77+
78+Q_DECLARE_METATYPE(Preview *)
79+
80+#endif
plugins/Unity/previewaction.cppnew file+75
@@ -0,0 +1,75 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#include "previewaction.h"
21+
22+PreviewAction::PreviewAction(QObject *parent)
23+ : QObject(parent),
24+ m_unityAction(nullptr)
25+{
26+}
27+
28+void PreviewAction::setUnityAction(unity::dash::Preview::ActionPtr unityAction)
29+{
30+ m_unityAction = unityAction;
31+
32+ Q_EMIT previewActionChanged();
33+}
34+
35+QString PreviewAction::id() const
36+{
37+ if (m_unityAction)
38+ return QString::fromStdString(m_unityAction->id);
39+ return QString();
40+}
41+
42+QString PreviewAction::displayName() const
43+{
44+ if (m_unityAction)
45+ return QString::fromStdString(m_unityAction->display_name);
46+ return QString();
47+}
48+
49+QString PreviewAction::iconHint() const
50+{
51+ if (m_unityAction)
52+ return QString::fromStdString(m_unityAction->icon_hint);
53+ return QString();
54+}
55+
56+QString PreviewAction::extraText() const
57+{
58+ if (m_unityAction)
59+ return QString::fromStdString(m_unityAction->extra_text);
60+ return QString();
61+}
62+
63+QString PreviewAction::activationUri() const
64+{
65+ if (m_unityAction)
66+ return QString::fromStdString(m_unityAction->activation_uri);
67+ return QString();
68+}
69+
70+LayoutHint PreviewAction::layoutHint() const
71+{
72+ if (m_unityAction)
73+ return static_cast<LayoutHint>(m_unityAction->layout_hint);
74+ return LayoutHint::None;
75+}
plugins/Unity/previewaction.hnew file+71
@@ -0,0 +1,71 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef PREVIEWACTION_H
21+#define PREVIEWACTION_H
22+
23+// Qt
24+#include <QObject>
25+#include <QList>
26+
27+// libuinity-core
28+#include <UnityCore/Preview.h>
29+
30+enum LayoutHint // keep in sync with unty::dash::LayoutHint
31+{
32+ None,
33+ Left,
34+ Right,
35+ Top,
36+ Bottom
37+};
38+
39+class PreviewAction : public QObject
40+{
41+ Q_OBJECT
42+
43+ Q_PROPERTY(QString id READ id NOTIFY previewActionChanged)
44+ Q_PROPERTY(QString displayName READ displayName NOTIFY previewActionChanged)
45+ Q_PROPERTY(QString iconHint READ iconHint NOTIFY previewActionChanged)
46+ Q_PROPERTY(QString extraText READ extraText NOTIFY previewActionChanged)
47+ Q_PROPERTY(QString activationUri READ activationUri NOTIFY previewActionChanged)
48+ Q_PROPERTY(LayoutHint layoutHint READ layoutHint NOTIFY previewActionChanged)
49+
50+public:
51+ explicit PreviewAction(QObject *parent = 0);
52+ void setUnityAction(unity::dash::Preview::ActionPtr unityAction);
53+
54+ QString id() const;
55+ QString displayName() const;
56+ QString iconHint() const;
57+ QString extraText() const;
58+ QString activationUri() const;
59+ LayoutHint layoutHint() const;
60+
61+Q_SIGNALS:
62+ void previewActionChanged();
63+
64+private:
65+ unity::dash::Preview::ActionPtr m_unityAction;
66+};
67+
68+Q_DECLARE_METATYPE(PreviewAction *)
69+Q_DECLARE_METATYPE(LayoutHint)
70+
71+#endif
plugins/Unity/previewinfohint.cppnew file+67
@@ -0,0 +1,67 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+// local
21+#include "previewinfohint.h"
22+#include "variantutils.h"
23+
24+PreviewInfoHint::PreviewInfoHint(QObject *parent):
25+ QObject(parent),
26+ m_unityInfoHint(nullptr)
27+{
28+}
29+
30+void PreviewInfoHint::setUnityInfoHint(unity::dash::Preview::InfoHintPtr unityInfoHint)
31+{
32+ m_unityInfoHint = unityInfoHint;
33+
34+ Q_EMIT previewInfoHintChanged();
35+}
36+
37+QString PreviewInfoHint::id() const
38+{
39+ if (m_unityInfoHint) {
40+ return QString::fromStdString(m_unityInfoHint->id);
41+ }
42+ return QString();
43+}
44+
45+QString PreviewInfoHint::displayName() const
46+{
47+ if (m_unityInfoHint) {
48+ return QString::fromStdString(m_unityInfoHint->display_name);
49+ }
50+ return QString();
51+}
52+
53+QString PreviewInfoHint::iconHint() const
54+{
55+ if (m_unityInfoHint) {
56+ return QString::fromStdString(m_unityInfoHint->icon_hint);
57+ }
58+ return QString();
59+}
60+
61+QVariant PreviewInfoHint::value() const
62+{
63+ if (m_unityInfoHint) {
64+ return QVariantFromGVariant(m_unityInfoHint->value);
65+ }
66+ return QVariant();
67+}
plugins/Unity/previewinfohint.hnew file+58
@@ -0,0 +1,58 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef PREVIEWINFOHINT_H
21+#define PREVIEWINFOHINT_H
22+
23+// Qt
24+#include <QObject>
25+#include <QString>
26+#include <QVariant>
27+
28+// libunity-core
29+#include <UnityCore/Preview.h>
30+
31+class PreviewInfoHint : public QObject
32+{
33+ Q_OBJECT
34+
35+ Q_PROPERTY(QString id READ id NOTIFY previewInfoHintChanged)
36+ Q_PROPERTY(QString displayName READ displayName NOTIFY previewInfoHintChanged)
37+ Q_PROPERTY(QString iconHint READ iconHint NOTIFY previewInfoHintChanged)
38+ Q_PROPERTY(QVariant value READ value NOTIFY previewInfoHintChanged)
39+
40+public:
41+ explicit PreviewInfoHint(QObject *parent = 0);
42+ void setUnityInfoHint(unity::dash::Preview::InfoHintPtr unityInfoHint);
43+
44+ QString id() const;
45+ QString displayName() const;
46+ QString iconHint() const;
47+ QVariant value() const;
48+
49+Q_SIGNALS:
50+ void previewInfoHintChanged();
51+
52+private:
53+ unity::dash::Preview::InfoHintPtr m_unityInfoHint;
54+};
55+
56+Q_DECLARE_METATYPE(PreviewInfoHint *)
57+
58+#endif
plugins/Unity/scope.cpp+79−11
@@ -19,12 +19,19 @@
19
19
20// Self
20// Self
21#include "scope.h"
21#include "scope.h"
22+
23+// local
22#include "categories.h"
24#include "categories.h"
25+#include "preview.h"
26+#include "variantutils.h"
23
27
24// Qt
28// Qt
25#include <QUrl>
29#include <QUrl>
26#include <QDebug>
30#include <QDebug>
27#include <QtGui/QDesktopServices>
31#include <QtGui/QDesktopServices>
32+#include <QQmlEngine>
33+
34+#include <UnityCore/Variant.h>
28
35
29#include <libintl.h>
36#include <libintl.h>
30
37
@@ -118,21 +125,80 @@ void Scope::setNoResultsHint(const QString& hint) {
118 }
125 }
119}
126}
120
127
128+
129+unity::dash::LocalResult Scope::createLocalResult(const QVariant &uri, const QVariant &icon_hint,
130+ const QVariant &category, const QVariant &result_type,
131+ const QVariant &mimetype, const QVariant &title,
132+ const QVariant &comment, const QVariant &dnd_uri,
133+ const QVariant &metadata)
134+{
135+ unity::dash::LocalResult res;
136+ res.uri = uri.toString().toStdString();
137+ res.icon_hint = icon_hint.toString().toStdString();
138+ res.category_index = category.toUInt();
139+ res.result_type = result_type.toUInt();
140+ res.mimetype = mimetype.toString().toStdString();
141+ res.name = title.toString().toStdString();
142+ res.comment = comment.toString().toStdString();
143+ res.dnd_uri = dnd_uri.toString().toStdString();
144+ res.hints = convertToHintsMap(metadata);
145+
146+ return res;
147+}
148+
149+// FIXME: Change to use row index.
121−void Scope::activate(const QString& /*uri*/)
150+void Scope::activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
151+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
152+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
153+{
154+ auto res = createLocalResult(uri, icon_hint, category, result_type, mimetype, title, comment, dnd_uri, metadata);
155+ m_unityScope->Activate(res);
156+}
157+
158+// FIXME: Change to use row index.
159+void Scope::preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
160+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
161+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
122{
162{
123− // TODO:
163+ auto res = createLocalResult(uri, icon_hint, category, result_type, mimetype, title, comment, dnd_uri, metadata);
124− // we need to create unity::dash::LocalResult (see UnityCore/Result.h) and pass it to Activate;
164+ m_unityScope->Preview(res);
125− // this requires entire row from the model, so we need row index rather than uri.
126− // m_unityScope->Activate(QByteArray::fromPercentEncoding(uri.toUtf8()).constData());
127}
165}
128
166
129−void Scope::onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const&)
167+void Scope::onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const& hints)
130{
168{
169+ // note: we will not get called on SHOW_PREVIEW, instead UnityCore will signal preview_ready.
170+ switch (type)
171+ {
131− if (type == unity::dash::NOT_HANDLED) {
172+ case unity::dash::NOT_HANDLED:
132− fallbackActivate(QString::fromStdString(result.uri));
173+ fallbackActivate(QString::fromStdString(result.uri));
174+ break;
175+ case unity::dash::SHOW_DASH:
176+ Q_EMIT showDash();
177+ break;
178+ case unity::dash::HIDE_DASH:
179+ Q_EMIT hideDash();
180+ break;
181+ case unity::dash::GOTO_DASH_URI:
182+ if (hints.find("goto-uri") != hints.end()) {
183+ Q_EMIT gotoUri(QString::fromStdString(g_variant_get_string(hints.at("goto-uri"), nullptr)));
184+ } else {
185+ qWarning() << "Missing goto-uri hint for GOTO_DASH_URI activation reply";
186+ }
187+ break;
188+ default:
189+ qWarning() << "Unhandled activation response:" << type;
133 }
190 }
134}
191}
135
192
193+void Scope::onPreviewReady(unity::dash::LocalResult const& /* result */, unity::dash::Preview::Ptr const& preview)
194+{
195+ auto prv = Preview::newFromUnityPreview(preview);
196+ // is this the best solution? QML may need to keep more than one preview instance around, so we can't own it.
197+ // passing it by value is not possible.
198+ QQmlEngine::setObjectOwnership(prv, QQmlEngine::JavaScriptOwnership);
199+ Q_EMIT previewReady(prv);
200+}
201+
136void Scope::fallbackActivate(const QString& uri)
202void Scope::fallbackActivate(const QString& uri)
137{
203{
138 /* FIXME: stripping all content before the first column because for some
204 /* FIXME: stripping all content before the first column because for some
@@ -161,10 +227,10 @@ void Scope::fallbackActivate(const QString& uri)
161 return;
227 return;
162 }
228 }
163
229
164− qWarning() << "FIXME: Possibly no handler for scheme: " << url.scheme();
165− qWarning() << "Trying to open" << tweakedUri;
230+ qDebug() << "Trying to open" << uri;
231+
166 /* Try our luck */
232 /* Try our luck */
167− QDesktopServices::openUrl(url);
233+ QDesktopServices::openUrl(uri); //url?
168}
234}
169
235
170void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
236void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
@@ -204,6 +270,8 @@ void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
204 /* FIXME: signal should be forwarded instead of calling the handler directly */
270 /* FIXME: signal should be forwarded instead of calling the handler directly */
205 m_unityScope->activated.connect(sigc::mem_fun(this, &Scope::onActivated));
271 m_unityScope->activated.connect(sigc::mem_fun(this, &Scope::onActivated));
206
272
273+ m_unityScope->preview_ready.connect(sigc::mem_fun(this, &Scope::onPreviewReady));
274+
207 /* Synchronize local states with m_unityScope right now and whenever
275 /* Synchronize local states with m_unityScope right now and whenever
208 m_unityScope becomes connected */
276 m_unityScope becomes connected */
209 /* FIXME: should emit change notification signals for all properties */
277 /* FIXME: should emit change notification signals for all properties */
plugins/Unity/scope.h+20−3
@@ -33,6 +33,7 @@
33#include "deelistmodel.h"
33#include "deelistmodel.h"
34
34
35class Categories;
35class Categories;
36+class Preview;
36
37
37class Scope : public QObject
38class Scope : public QObject
38{
39{
@@ -73,7 +74,12 @@ public:
73 void setSearchQuery(const QString& search_query);
74 void setSearchQuery(const QString& search_query);
74 void setNoResultsHint(const QString& hint);
75 void setNoResultsHint(const QString& hint);
75
76
76− Q_INVOKABLE void activate(const QString& uri);
77+ Q_INVOKABLE void activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
78+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
79+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
80+ Q_INVOKABLE void preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
81+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
82+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
77 void setUnityScope(const unity::dash::Scope::Ptr& scope);
83 void setUnityScope(const unity::dash::Scope::Ptr& scope);
78 unity::dash::Scope::Ptr unityScope() const;
84 unity::dash::Scope::Ptr unityScope() const;
79
85
@@ -94,6 +100,12 @@ Q_SIGNALS:
94 void searchQueryChanged();
100 void searchQueryChanged();
95 void noResultsHintChanged();
101 void noResultsHintChanged();
96
102
103+ // signals triggered by activate(..) or preview(..) requests.
104+ void previewReady(Preview *preview);
105+ void showDash();
106+ void hideDash();
107+ void gotoUri(const QString &uri);
108+
97private Q_SLOTS:
109private Q_SLOTS:
98 void synchronizeStates();
110 void synchronizeStates();
99 void onSearchFinished(const std::string &, unity::glib::HintsMap const &);
111 void onSearchFinished(const std::string &, unity::glib::HintsMap const &);
@@ -105,8 +117,13 @@ private:
105 void onCategoriesSwarmNameChanged(const std::string&);
117 void onCategoriesSwarmNameChanged(const std::string&);
106 void onCategoriesModelChanged(unity::glib::Object<DeeModel>);
118 void onCategoriesModelChanged(unity::glib::Object<DeeModel>);
107 void onCategoriesChanged(const unity::dash::Categories::Ptr&);
119 void onCategoriesChanged(const unity::dash::Categories::Ptr&);
108−
120+ unity::dash::LocalResult createLocalResult(const QVariant &uri, const QVariant &icon_hint,
121+ const QVariant &category, const QVariant &result_type,
122+ const QVariant &mimetype, const QVariant &title,
123+ const QVariant &comment, const QVariant &dnd_uri,
124+ const QVariant &metadata);
109− void onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const&);
125+ void onActivated(unity::dash::LocalResult const& result, unity::dash::ScopeHandledType type, unity::glib::HintsMap const& hints);
126+ void onPreviewReady(unity::dash::LocalResult const& result, unity::dash::Preview::Ptr const& preview);
110 void fallbackActivate(const QString& uri);
127 void fallbackActivate(const QString& uri);
111
128
112 unity::dash::Scope::Ptr m_unityScope;
129 unity::dash::Scope::Ptr m_unityScope;
plugins/Unity/variantutils.cppnew file+158
@@ -0,0 +1,158 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#include "variantutils.h"
21+
22+/* Returns floating ref */
23+GVariant* GVariantFromQVariant(const QVariant &var)
24+{
25+ GVariant *gv = nullptr;
26+
27+ switch (var.type()) {
28+ case QVariant::String:
29+ gv = g_variant_new_string(var.toString().toUtf8());
30+ break;
31+ case QVariant::UInt:
32+ gv = g_variant_new_uint32(var.toUInt());
33+ break;
34+ case QVariant::Int:
35+ gv = g_variant_new_int32(var.toInt());
36+ break;
37+ case QVariant::LongLong:
38+ gv = g_variant_new_int64(var.toLongLong());
39+ break;
40+ case QVariant::ULongLong:
41+ gv = g_variant_new_uint64(var.toULongLong());
42+ break;
43+ case QVariant::Double:
44+ gv = g_variant_new_double(var.toDouble());
45+ break;
46+ case QVariant::Bool:
47+ gv = g_variant_new_boolean(var.toBool());
48+ break;
49+ case QVariant::Hash: {
50+ const auto hash = var.toHash();
51+ GVariant **children = new GVariant*[hash.size()];
52+ int cnt = 0;
53+ QHash<QString, QVariant>::const_iterator it = hash.constBegin();
54+ while (it != hash.constEnd()) {
55+ GVariant *key = g_variant_new_string(it.key().toUtf8());
56+ children[cnt++] = g_variant_new_dict_entry(key, g_variant_new_variant(GVariantFromQVariant(it.value())));
57+ ++it;
58+ }
59+ gv = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, hash.size());
60+ delete [] children;
61+ break;
62+ }
63+ default:
64+ break;
65+ }
66+ return gv;
67+}
68+
69+// implementation of this conversion taken from libdee-qt private utility function.
70+QVariant QVariantFromGVariant(GVariant *value)
71+{
72+ /* We need to special-case a{sv} here as G_VARIANT_CLASS_ARRAY handles simple arrays;
73+ we need to create QVariantHash, not a list */
74+ if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARDICT)) {
75+ const gsize nChildren = g_variant_n_children(value);
76+ QVariantHash hash;
77+ for (gsize i = 0; i < nChildren; ++i)
78+ {
79+ GVariant* dict_entry = g_variant_get_child_value(value, i);
80+
81+ gchar* dict_key;
82+ GVariant *dict_var;
83+ g_variant_get(dict_entry, "{&sv}", &dict_key, &dict_var);
84+ hash.insert(QString::fromUtf8(dict_key), QVariantFromGVariant(dict_var));
85+ g_variant_unref(dict_var);
86+ g_variant_unref(dict_entry);
87+ }
88+ return hash;
89+ }
90+
91+ switch (g_variant_classify(value)) {
92+ case G_VARIANT_CLASS_BOOLEAN:
93+ return QVariant((bool) g_variant_get_boolean(value));
94+ case G_VARIANT_CLASS_BYTE:
95+ return QVariant((uchar) g_variant_get_byte(value));
96+ case G_VARIANT_CLASS_INT16:
97+ return QVariant((qint16) g_variant_get_int16(value));
98+ case G_VARIANT_CLASS_UINT16:
99+ return QVariant((quint16) g_variant_get_uint16(value));
100+ case G_VARIANT_CLASS_INT32:
101+ return QVariant((qint32) g_variant_get_int32(value));
102+ case G_VARIANT_CLASS_UINT32:
103+ return QVariant((quint32) g_variant_get_uint32(value));
104+ case G_VARIANT_CLASS_INT64:
105+ return QVariant((qint64) g_variant_get_int64(value));
106+ case G_VARIANT_CLASS_UINT64:
107+ return QVariant((quint64) g_variant_get_uint64(value));
108+ case G_VARIANT_CLASS_DOUBLE:
109+ return QVariant(g_variant_get_double(value));
110+ case G_VARIANT_CLASS_STRING:
111+ return QVariant(QString::fromUtf8(g_variant_get_string(value, NULL)));
112+ case G_VARIANT_CLASS_ARRAY:
113+ case G_VARIANT_CLASS_TUPLE:
114+ {
115+ const gsize nChildren = g_variant_n_children(value);
116+ QList<QVariant> array;
117+ for (gsize i = 0; i < nChildren; ++i)
118+ {
119+ GVariant* gvariant = g_variant_get_child_value(value, i);
120+ array << QVariantFromGVariant(gvariant);
121+ g_variant_unref(gvariant);
122+ }
123+ return array;
124+ }
125+ default:
126+ /* Fallback on an empty QVariant.
127+ FIXME: Missing conversion of following GVariant types:
128+ - G_VARIANT_CLASS_HANDLE
129+ - G_VARIANT_CLASS_OBJECT_PATH
130+ - G_VARIANT_CLASS_SIGNATURE
131+ - G_VARIANT_CLASS_VARIANT
132+ - G_VARIANT_CLASS_MAYBE
133+ - G_VARIANT_CLASS_DICT_ENTRY
134+ */
135+ return QVariant();
136+ }
137+}
138+
139+unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val)
140+{
141+ unity::glib::HintsMap hintsMap;
142+ QHash<QString, QVariant>::const_iterator it = val.constBegin();
143+ while (it != val.constEnd()) {
144+ hintsMap[it.key().toStdString()] = GVariantFromQVariant(it.value());
145+ ++it;
146+ }
147+ return hintsMap;
148+}
149+
150+unity::glib::HintsMap convertToHintsMap(const QVariant &var)
151+{
152+ if (var.type() == QVariant::Hash) {
153+ unity::glib::HintsMap hintsMap;
154+ const auto hash = var.toHash();
155+ return convertToHintsMap(hash);
156+ }
157+ return unity::glib::HintsMap();
158+}
plugins/Unity/variantutils.hnew file+34
@@ -0,0 +1,34 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef VARIANTUTILS_H
21+#define VARIANTUTILS_H
22+
23+#include <glib.h>
24+#include <QVariant>
25+
26+// libunity-core
27+#include <UnityCore/Variant.h>
28+
29+GVariant* GVariantFromQVariant(const QVariant &value);
30+QVariant QVariantFromGVariant(GVariant *value);
31+unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val);
32+unity::glib::HintsMap convertToHintsMap(const QVariant &var);
33+
34+#endif
plugins/Utils/CMakeLists.txt+2−2
@@ -28,9 +28,9 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
28 )
28 )
29
29
30install(TARGETS Utils-qml
30install(TARGETS Utils-qml
31− DESTINATION ${SHELL_APP_DIR}/plugins/Utils
31+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Utils
32 )
32 )
33
33
34install(FILES qmldir
34install(FILES qmldir
35− DESTINATION ${SHELL_APP_DIR}/plugins/Utils
35+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Utils
36 )
36 )
plugins/Utils/qlimitproxymodelqml.cpp+4−4
@@ -39,11 +39,11 @@ QHash<int, QByteArray> QLimitProxyModelQML::roleNames() const
39void
39void
40QLimitProxyModelQML::setModel(QAbstractItemModel *itemModel)
40QLimitProxyModelQML::setModel(QAbstractItemModel *itemModel)
41{
41{
42− if (sourceModel() != NULL) {
43− sourceModel()->disconnect(this);
44− }
45−
46 if (itemModel != sourceModel()) {
42 if (itemModel != sourceModel()) {
43+ if (sourceModel() != NULL) {
44+ sourceModel()->disconnect(this);
45+ }
46+
47 setSourceModel(itemModel);
47 setSourceModel(itemModel);
48
48
49 if (sourceModel() != NULL) {
49 if (sourceModel() != NULL) {
po/ar.po+40−48
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-14 21:09+0000\n"
11+"PO-Revision-Date: 2013-06-22 16:15+0000\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
13"Language-Team: Arabic <ar@li.org>\n"
13"Language-Team: Arabic <ar@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "متوفرة للتنزيل"
109msgid "Apps"
109msgid "Apps"
110msgstr "تطبيقات"
110msgstr "تطبيقات"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "تطبيقات مألوفة"
114msgstr "تطبيقات مألوفة"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "آخر الصوتيات المشغلة"
118msgstr "آخر الصوتيات المشغلة"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "فيديوهات رائجة على الإنترنت"
122msgstr "فيديوهات رائجة على الإنترنت"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "الرئيسية"
126msgstr "الرئيسية"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "موسيقى"
146msgstr "موسيقى"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr "الشائع على الإنترنت"
150msgstr "الشائع على الإنترنت"
@@ -193,18 +165,18 @@ msgstr "النجوم:"
193msgid "Author:"
165msgid "Author:"
194msgstr "المؤلف:"
166msgstr "المؤلف:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198−msgstr ""
170+msgstr "مكالمة طوارئ"
199
171
200#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
201#, qt-format
173#, qt-format
202msgid "Hello %1"
174msgid "Hello %1"
203−msgstr ""
175+msgstr "مرحبا %1"
204
176
205#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
206msgid "Hello"
178msgid "Hello"
207−msgstr ""
179+msgstr "مرحبًا"
208
180
209#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
210msgid "Confirm"
182msgid "Confirm"
@@ -234,19 +206,39 @@ msgstr "الجهاز"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "نمط الطيران"
207msgstr "نمط الطيران"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "ابحث"
211msgstr "ابحث"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "عذراً، لا يوجد ما يطابق بحثك."
215msgstr "عذراً، لا يوجد ما يطابق بحثك."
244
216
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr "الشاشة الرئيسية"
248−
249−#: Shell.qml:380
217+#: Shell.qml:383
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Tətbiqlər"
110msgstr "Tətbiqlər"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Ev"
126msgstr "Ev"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Musiqi"
146msgstr "Musiqi"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Axtar"
211msgstr "Axtar"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
215msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Əsas Ekran"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-19 15:47+0000\n"
11"PO-Revision-Date: 2013-06-19 15:47+0000\n"
12"Last-Translator: Miroslav E. Hadzhiev (Хаджиев) "
12"Last-Translator: Miroslav E. Hadzhiev (Хаджиев) "
13"<miroslav.hadzhiev@gmail.com>\n"
13"<miroslav.hadzhiev@gmail.com>\n"
@@ -15,8 +15,8 @@ msgstr ""
15"MIME-Version: 1.0\n"
15"MIME-Version: 1.0\n"
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
18+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
19−"X-Generator: Launchpad (build 16673)\n"
19+"X-Generator: Launchpad (build 16681)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -110,27 +110,19 @@ msgstr ""
110msgid "Apps"
110msgid "Apps"
111msgstr "Приложения"
111msgstr "Приложения"
112
112
113−#: Dash/DashHome.qml:43
113+#: Dash/DashHome.qml:40
114msgid "Frequent Apps"
114msgid "Frequent Apps"
115msgstr ""
115msgstr ""
116
116
117−#: Dash/DashHome.qml:46
117+#: Dash/DashHome.qml:43
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
126msgid "Recent Music"
118msgid "Recent Music"
127msgstr ""
119msgstr ""
128
120
129−#: Dash/DashHome.qml:55
121+#: Dash/DashHome.qml:46
130msgid "Videos Popular Online"
122msgid "Videos Popular Online"
131msgstr ""
123msgstr ""
132
124
133−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
125+#: Dash/DashHome.qml:175
134msgid "Home"
126msgid "Home"
135msgstr "Начало"
127msgstr "Начало"
136
128
@@ -154,26 +146,6 @@ msgstr ""
154msgid "Music"
146msgid "Music"
155msgstr "Музика"
147msgstr "Музика"
156
148
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−
177#: Dash/DashVideos.qml:31
149#: Dash/DashVideos.qml:31
178msgid "Popular Online"
150msgid "Popular Online"
179msgstr ""
151msgstr ""
@@ -194,7 +166,7 @@ msgstr ""
194msgid "Author:"
166msgid "Author:"
195msgstr "Автор:"
167msgstr "Автор:"
196
168
197−#: Greeter/Lockscreen.qml:126
169+#: Greeter/Lockscreen.qml:133
198msgid "Emergency call"
170msgid "Emergency call"
199msgstr ""
171msgstr ""
200
172
@@ -235,19 +207,27 @@ msgstr "Устройство"
235msgid "Flight mode"
207msgid "Flight mode"
236msgstr ""
208msgstr ""
237
209
238−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
210+#: Panel/SearchIndicator.qml:26
239msgid "Search"
211msgid "Search"
240msgstr "Търсене"
212msgstr "Търсене"
241
213
242−#: plugins/Unity/lens.cpp:333
214+#: plugins/Unity/scope.cpp:268
243msgid "Sorry, there is nothing that matches your search."
215msgid "Sorry, there is nothing that matches your search."
244msgstr "Съжаляваме, няма нищо, което да отговаря на вашето търсене."
216msgstr "Съжаляваме, няма нищо, което да отговаря на вашето търсене."
245
217
246−#: plugins/Unity/lenses.cpp:39
218+#: Shell.qml:383
247−msgid "Home screen"
248−msgstr "Начален екран"
249−
250−#: Shell.qml:380
251#, qt-format
219#, qt-format
252−msgid "Please enter %1:"
220+msgid "Please enter %1"
253msgstr ""
221msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Catalan <ca@li.org>\n"
13"Language-Team: Catalan <ca@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Disponibles per baixar"
109msgid "Apps"
109msgid "Apps"
110msgstr "Aplicacions"
110msgstr "Aplicacions"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Aplicacions freqüents"
114msgstr "Aplicacions freqüents"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Música recent"
118msgstr "Música recent"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Vídeos populars en línia"
122msgstr "Vídeos populars en línia"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Inici"
126msgstr "Inici"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Música"
146msgstr "Música"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,27 @@ msgstr "Dispositiu"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Mode d'avió"
207msgstr "Mode d'avió"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Cerca"
211msgstr "Cerca"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "No hi ha res que coincideixi amb la cerca"
215msgstr "No hi ha res que coincideixi amb la cerca"
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Pantalla d'inici"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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+42−50
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-15 20:04+0000\n"
11+"PO-Revision-Date: 2013-06-29 12:53+0000\n"
12−"Last-Translator: Eduard Gotwig <eduardgotwig@gmail.com>\n"
12+"Last-Translator: Phillip Sz <Unknown>\n"
13"Language-Team: German <de@li.org>\n"
13"Language-Team: German <de@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16692)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Zum Herunterladen verfügbar"
109msgid "Apps"
109msgid "Apps"
110msgstr "Anwendungen"
110msgstr "Anwendungen"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Häufig genutzte Anwendungen"
114msgstr "Häufig genutzte Anwendungen"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Zuletzt gehörte Musik"
118msgstr "Zuletzt gehörte Musik"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Beliebte Online-Videos"
122msgstr "Beliebte Online-Videos"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Start"
126msgstr "Start"
135
127
@@ -153,26 +145,6 @@ msgstr "Top Tabellenplatz"
153msgid "Music"
145msgid "Music"
154msgstr "Musik"
146msgstr "Musik"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr "Online Beliebt"
150msgstr "Online Beliebt"
@@ -193,18 +165,18 @@ msgstr "Darsteller:"
193msgid "Author:"
165msgid "Author:"
194msgstr "Autor:"
166msgstr "Autor:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198−msgstr ""
170+msgstr "Notruf"
199
171
200#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
201#, qt-format
173#, qt-format
202msgid "Hello %1"
174msgid "Hello %1"
203−msgstr ""
175+msgstr "Hallo %1"
204
176
205#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
206msgid "Hello"
178msgid "Hello"
207−msgstr ""
179+msgstr "Hallo"
208
180
209#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
210msgid "Confirm"
182msgid "Confirm"
@@ -234,19 +206,39 @@ msgstr "Gerät"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Flugmodus"
207msgstr "Flugmodus"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Suchen"
211msgstr "Suchen"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Entschuldigung, es wurden keine Treffer erzielt."
215msgstr "Entschuldigung, es wurden keine Treffer erzielt."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Startseite"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252−msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Greek <el@li.org>\n"
13"Language-Team: Greek <el@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Εφαρμογές"
110msgstr "Εφαρμογές"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Αρχή"
126msgstr "Αρχή"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Μουσική"
146msgstr "Μουσική"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Αναζήτηση"
211msgstr "Αναζήτηση"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να ταιριάζει στην αναζήτησή σας."
215msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να ταιριάζει στην αναζήτησή σας."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Αρχική οθόνη"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Πρόσωπα"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Αρχική οθόνη"
po/en_AU.po+36−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-18 20:36+0000\n"
11"PO-Revision-Date: 2013-06-18 20:36+0000\n"
12"Last-Translator: Jackson Doak <Doak.jackson@gmail.com>\n"
12"Last-Translator: Jackson Doak <Doak.jackson@gmail.com>\n"
13"Language-Team: English (Australia) <en_AU@li.org>\n"
13"Language-Team: English (Australia) <en_AU@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Available for download"
109msgid "Apps"
109msgid "Apps"
110msgstr "Apps"
110msgstr "Apps"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Frequent Apps"
114msgstr "Frequent Apps"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Recent Music"
118msgstr "Recent Music"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Videos Popular Online"
122msgstr "Videos Popular Online"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Home"
126msgstr "Home"
135
127
@@ -153,26 +145,6 @@ msgstr "Top Charting"
153msgid "Music"
145msgid "Music"
154msgstr "Music"
146msgstr "Music"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr "Popular Online"
150msgstr "Popular Online"
@@ -193,7 +165,7 @@ msgstr "Starring:"
193msgid "Author:"
165msgid "Author:"
194msgstr "Author:"
166msgstr "Author:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,39 @@ msgstr "Device"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Flight mode"
207msgstr "Flight mode"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Search"
211msgstr "Search"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Sorry, there is nothing that matches your search."
215msgstr "Sorry, there is nothing that matches your search."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Home screen"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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+41−49
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-14 12:43+0000\n"
11+"PO-Revision-Date: 2013-06-27 00:22+0000\n"
12"Last-Translator: Andi Chandler <Unknown>\n"
12"Last-Translator: Andi Chandler <Unknown>\n"
13"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
13"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Available for download"
109msgid "Apps"
109msgid "Apps"
110msgstr "Apps"
110msgstr "Apps"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Frequent Apps"
114msgstr "Frequent Apps"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Recent Music"
118msgstr "Recent Music"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Videos Popular Online"
122msgstr "Videos Popular Online"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Home"
126msgstr "Home"
135
127
@@ -153,26 +145,6 @@ msgstr "Top Charting"
153msgid "Music"
145msgid "Music"
154msgstr "Music"
146msgstr "Music"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr "Popular Online"
150msgstr "Popular Online"
@@ -193,18 +165,18 @@ msgstr "Starring:"
193msgid "Author:"
165msgid "Author:"
194msgstr "Author:"
166msgstr "Author:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198−msgstr ""
170+msgstr "Emergency call"
199
171
200#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
201#, qt-format
173#, qt-format
202msgid "Hello %1"
174msgid "Hello %1"
203−msgstr ""
175+msgstr "Hello %1"
204
176
205#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
206msgid "Hello"
178msgid "Hello"
207−msgstr ""
179+msgstr "Hello"
208
180
209#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
210msgid "Confirm"
182msgid "Confirm"
@@ -234,19 +206,39 @@ msgstr "Device"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Flight mode"
207msgstr "Flight mode"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Search"
211msgstr "Search"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Sorry, there is nothing that matches your search."
215msgstr "Sorry, there is nothing that matches your search."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Home screen"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252−msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Esperanto <eo@li.org>\n"
13"Language-Team: Esperanto <eo@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr ""
110msgstr ""
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr ""
126msgstr ""
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr ""
146msgstr ""
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,15 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr ""
211msgstr ""
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr ""
215msgstr ""
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
po/es.po+36−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-16 23:44+0000\n"
11"PO-Revision-Date: 2013-06-16 23:44+0000\n"
12"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
12"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
13"Language-Team: Spanish <es@li.org>\n"
13"Language-Team: Spanish <es@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Disponibles para descargar"
109msgid "Apps"
109msgid "Apps"
110msgstr "Aplicaciones"
110msgstr "Aplicaciones"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Aplicaciones frecuentes"
114msgstr "Aplicaciones frecuentes"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Música reciente"
118msgstr "Música reciente"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Vídeos populares en línea"
122msgstr "Vídeos populares en línea"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Inicio"
126msgstr "Inicio"
135
127
@@ -153,26 +145,6 @@ msgstr "Mejor posicionadas"
153msgid "Music"
145msgid "Music"
154msgstr "Música"
146msgstr "Música"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr "Populares en línea"
150msgstr "Populares en línea"
@@ -193,7 +165,7 @@ msgstr "Protagonistas:"
193msgid "Author:"
165msgid "Author:"
194msgstr "Autor:"
166msgstr "Autor:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,39 @@ msgstr "Dispositivo"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Modo de vuelo"
207msgstr "Modo de vuelo"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Buscar"
211msgstr "Buscar"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "No hay nada que coincida con su búsqueda."
215msgstr "No hay nada que coincida con su búsqueda."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Pantalla de inicio"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-10 16:19+0000\n"
11"PO-Revision-Date: 2013-06-10 16:19+0000\n"
12"Last-Translator: Jiri Grönroos <Unknown>\n"
12"Last-Translator: Jiri Grönroos <Unknown>\n"
13"Language-Team: Finnish <fi@li.org>\n"
13"Language-Team: Finnish <fi@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Ladattavissa"
109msgid "Apps"
109msgid "Apps"
110msgstr "Sovellukset"
110msgstr "Sovellukset"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Yleisimmät sovellukset"
114msgstr "Yleisimmät sovellukset"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Viimeisin musiikki"
118msgstr "Viimeisin musiikki"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Suositut verkkovideot"
122msgstr "Suositut verkkovideot"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Kotinäyttö"
126msgstr "Kotinäyttö"
135
127
@@ -153,26 +145,6 @@ msgstr "Nousukiidossa"
153msgid "Music"
145msgid "Music"
154msgstr "Musiikki"
146msgstr "Musiikki"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr "Suosittua verkossa"
150msgstr "Suosittua verkossa"
@@ -193,7 +165,7 @@ msgstr "Pääosissa:"
193msgid "Author:"
165msgid "Author:"
194msgstr "Laatinut:"
166msgstr "Laatinut:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,36 @@ msgstr "Laite"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Lentokonetila"
207msgstr "Lentokonetila"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Hae"
211msgstr "Hae"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Hakuun täsmääviä tuloksia ei löydy."
215msgstr "Hakuun täsmääviä tuloksia ei löydy."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Kotinäyttö"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Faroese <fo@li.org>\n"
13"Language-Team: Faroese <fo@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Nýtsluskipanir"
110msgstr "Nýtsluskipanir"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Heim"
126msgstr "Heim"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Tónleikur"
146msgstr "Tónleikur"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Leita"
211msgstr "Leita"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
215msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Heimaskíggi"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-26 15:11+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Anne <anneonyme017@gmail.com>\n"
13"Language-Team: French <fr@li.org>\n"
13"Language-Team: French <fr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
22−msgstr ""
22+msgstr "Téléphone"
23
23
24#: Applications/applications.js:29
24#: Applications/applications.js:29
25msgid "Camera"
25msgid "Camera"
26−msgstr ""
26+msgstr "Appareil photo"
27
27
28#: Applications/applications.js:35
28#: Applications/applications.js:35
29msgid "Gallery"
29msgid "Gallery"
30−msgstr ""
30+msgstr "Galerie"
31
31
32#: Applications/applications.js:40
32#: Applications/applications.js:40
33msgid "Facebook"
33msgid "Facebook"
34−msgstr ""
34+msgstr "Facebook"
35
35
36#: Applications/applications.js:46
36#: Applications/applications.js:46
37msgid "Browser"
37msgid "Browser"
38−msgstr ""
38+msgstr "Navigateur"
39
39
40#: Applications/applications.js:51
40#: Applications/applications.js:51
41msgid "Twitter"
41msgid "Twitter"
42−msgstr ""
42+msgstr "Twitter"
43
43
44#: Applications/applications.js:57
44#: Applications/applications.js:57
45msgid "GMail"
45msgid "GMail"
46−msgstr ""
46+msgstr "GMail"
47
47
48#: Applications/applications.js:62
48#: Applications/applications.js:62
49msgid "Weather"
49msgid "Weather"
50−msgstr ""
50+msgstr "Météo"
51
51
52#: Applications/applications.js:68
52#: Applications/applications.js:68
53msgid "Notepad"
53msgid "Notepad"
54−msgstr ""
54+msgstr "Bloc-notes"
55
55
56#: Applications/applications.js:74
56#: Applications/applications.js:74
57msgid "Calendar"
57msgid "Calendar"
58−msgstr ""
58+msgstr "Agenda"
59
59
60#: Applications/applications.js:80
60#: Applications/applications.js:80
61msgid "Media Player"
61msgid "Media Player"
62−msgstr ""
62+msgstr "Lecteur multimédia"
63
63
64#: Applications/applications.js:86
64#: Applications/applications.js:86
65msgid "Evernote"
65msgid "Evernote"
66−msgstr ""
66+msgstr "Evernote"
67
67
68#: Applications/applications.js:91
68#: Applications/applications.js:91
69msgid "Map"
69msgid "Map"
@@ -71,27 +71,27 @@ msgstr ""
71
71
72#: Applications/applications.js:96
72#: Applications/applications.js:96
73msgid "Pinterest"
73msgid "Pinterest"
74−msgstr ""
74+msgstr "Pinterest"
75
75
76#: Applications/applications.js:101
76#: Applications/applications.js:101
77msgid "SoundCloud"
77msgid "SoundCloud"
78−msgstr ""
78+msgstr "SoundCloud"
79
79
80#: Applications/applications.js:106
80#: Applications/applications.js:106
81msgid "Wikipedia"
81msgid "Wikipedia"
82−msgstr ""
82+msgstr "Wikipédia"
83
83
84#: Applications/applications.js:111
84#: Applications/applications.js:111
85msgid "YouTube"
85msgid "YouTube"
86−msgstr ""
86+msgstr "YouTube"
87
87
88#: Components/PageHeader.qml:300
88#: Components/PageHeader.qml:300
89msgid "Recent searches"
89msgid "Recent searches"
90−msgstr ""
90+msgstr "Recherches récentes"
91
91
92#: Dash/DashApps.qml:65
92#: Dash/DashApps.qml:65
93msgid "Running apps"
93msgid "Running apps"
94−msgstr ""
94+msgstr "Applications en cours d’exécution"
95
95
96#: Dash/DashApps.qml:68
96#: Dash/DashApps.qml:68
97msgid "Frequently used"
97msgid "Frequently used"
@@ -99,7 +99,7 @@ msgstr ""
99
99
100#: Dash/DashApps.qml:71
100#: Dash/DashApps.qml:71
101msgid "Installed"
101msgid "Installed"
102−msgstr ""
102+msgstr "Installées"
103
103
104#: Dash/DashApps.qml:74
104#: Dash/DashApps.qml:74
105msgid "Available for download"
105msgid "Available for download"
@@ -109,29 +109,21 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Applications"
110msgstr "Applications"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114−msgstr ""
114+msgstr "Applications fréquemment utilisées"
115−
116−#: Dash/DashHome.qml:46
117−msgid "Favourite People"
118−msgstr ""
119
115
120−#: Dash/DashHome.qml:49
116+#: Dash/DashHome.qml:43
121−msgid "People Recently in Touch"
122−msgstr ""
123−
124−#: Dash/DashHome.qml:52
125msgid "Recent Music"
117msgid "Recent Music"
126−msgstr ""
118+msgstr "Musique récente"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130−msgstr ""
122+msgstr "Vidéos populaires en ligne"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134−msgstr ""
126+msgstr "Accueil"
135
127
136#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
128#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
137msgid "Featured"
129msgid "Featured"
@@ -143,7 +135,7 @@ msgstr ""
143
135
144#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
145msgid "New Releases"
137msgid "New Releases"
146−msgstr ""
138+msgstr "Nouveautés"
147
139
148#: Dash/DashMusic.qml:30
140#: Dash/DashMusic.qml:30
149msgid "Top Charting"
141msgid "Top Charting"
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Musique"
146msgstr "Musique"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -183,44 +155,44 @@ msgstr "Vidéos"
183
155
184#: Dash/Video/VideoPreview.qml:98
156#: Dash/Video/VideoPreview.qml:98
185msgid "Directed by:"
157msgid "Directed by:"
186−msgstr ""
158+msgstr "Réalisé par :"
187
159
188#: Dash/Video/VideoPreview.qml:121
160#: Dash/Video/VideoPreview.qml:121
189msgid "Starring:"
161msgid "Starring:"
190−msgstr ""
162+msgstr "Acteurs :"
191
163
192#: Dash/Video/VideoPreview.qml:144
164#: Dash/Video/VideoPreview.qml:144
193msgid "Author:"
165msgid "Author:"
194−msgstr ""
166+msgstr "Auteur :"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
200#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
201#, qt-format
173#, qt-format
202msgid "Hello %1"
174msgid "Hello %1"
203−msgstr ""
175+msgstr "Bonjour %1"
204
176
205#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
206msgid "Hello"
178msgid "Hello"
207−msgstr ""
179+msgstr "Bonjour"
208
180
209#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
210msgid "Confirm"
182msgid "Confirm"
211−msgstr ""
183+msgstr "Confirmer"
212
184
213#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
185#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
214msgid "Type or say a command"
186msgid "Type or say a command"
215−msgstr ""
187+msgstr "Entrez ou dictez une commande"
216
188
217#: Hud/Hud.qml:84
189#: Hud/Hud.qml:84
218msgid "Loading. Please Wait..."
190msgid "Loading. Please Wait..."
219−msgstr ""
191+msgstr "Chargement. Veuillez patienter..."
220
192
221#: Hud/Hud.qml:89
193#: Hud/Hud.qml:89
222msgid "Speak Now..."
194msgid "Speak Now..."
223−msgstr ""
195+msgstr "Parlez maintenant..."
224
196
225#: Hud/Hud.qml:94
197#: Hud/Hud.qml:94
226msgid "Speaking..."
198msgid "Speaking..."
@@ -232,21 +204,38 @@ msgstr ""
232
204
233#: Panel/Menus/Overview/FlightModeWidget.qml:42
205#: Panel/Menus/Overview/FlightModeWidget.qml:42
234msgid "Flight mode"
206msgid "Flight mode"
235−msgstr ""
207+msgstr "Mode avion"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239−msgstr ""
211+msgstr "Rechercher"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243−msgstr ""
215+msgstr "Désolé, aucun résultat ne correspond à votre recherche."
244−
245−#: plugins/Unity/lenses.cpp:39
246−msgid "Home screen"
247−msgstr ""
248
216
249−#: Shell.qml:380
217+#: Shell.qml:383
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Galician <gl@li.org>\n"
13"Language-Team: Galician <gl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Dispoñíbel para descargar"
109msgid "Apps"
109msgid "Apps"
110msgstr "Aplicativos"
110msgstr "Aplicativos"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Aplicativos frecuentes"
114msgstr "Aplicativos frecuentes"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Música recente"
118msgstr "Música recente"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Vídeos populares en liña"
122msgstr "Vídeos populares en liña"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Cartafol persoal"
126msgstr "Cartafol persoal"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Música"
146msgstr "Música"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,27 @@ msgstr "Dispositivo"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Modo de voo"
207msgstr "Modo de voo"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Buscar"
211msgstr "Buscar"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Sentímolo, non hai nada que coincida con esta busca."
215msgstr "Sentímolo, non hai nada que coincida con esta busca."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Pantalla de inicio"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Hebrew <he@li.org>\n"
13"Language-Team: Hebrew <he@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "יישומים"
110msgstr "יישומים"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "בית"
126msgstr "בית"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "מוזיקה"
146msgstr "מוזיקה"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "חיפוש"
211msgstr "חיפוש"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה."
215msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "מסך הבית"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "אנשים"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "מסך הבית"
po/hr.po+18−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Croatian <hr@li.org>\n"
13"Language-Team: Croatian <hr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Aplikacije"
110msgstr "Aplikacije"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Početna"
126msgstr "Početna"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Glazba"
146msgstr "Glazba"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Pretraživanje"
211msgstr "Pretraživanje"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
215msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Početni zaslon"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Alkalmazások"
110msgstr "Alkalmazások"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Kezdőoldal"
126msgstr "Kezdőoldal"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Zene"
146msgstr "Zene"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr "Eszköz"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Keresés"
211msgstr "Keresés"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Elnézést, nincs találat a keresésre."
215msgstr "Elnézést, nincs találat a keresésre."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Kezdőképernyő"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-07 12:42+0000\n"
11"PO-Revision-Date: 2013-06-07 12:42+0000\n"
12"Last-Translator: iAbaS <sosabazyan@yandex.ru>\n"
12"Last-Translator: iAbaS <sosabazyan@yandex.ru>\n"
13"Language-Team: Armenian <hy@li.org>\n"
13"Language-Team: Armenian <hy@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Հասանելի ծրագրեր"
109msgid "Apps"
109msgid "Apps"
110msgstr "Ծրագրեր"
110msgstr "Ծրագրեր"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Հաճախակի ծրագրերը"
114msgstr "Հաճախակի ծրագրերը"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Վերջին երգերը"
118msgstr "Վերջին երգերը"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Հայտնի օնլայն վիդեոներ"
122msgstr "Հայտնի օնլայն վիդեոներ"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Տուն"
126msgstr "Տուն"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Երգեր"
146msgstr "Երգեր"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,27 @@ msgstr "Սարք"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Անկապ րեժիմ"
207msgstr "Անկապ րեժիմ"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Որոնում"
211msgstr "Որոնում"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
215msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Տուն"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Indonesian <id@li.org>\n"
13"Language-Team: Indonesian <id@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr ""
110msgstr ""
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr ""
126msgstr ""
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr ""
146msgstr ""
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,15 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr ""
211msgstr ""
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr ""
215msgstr ""
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
po/it.po+18−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Italian <it@li.org>\n"
13"Language-Team: Italian <it@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Applicazioni"
110msgstr "Applicazioni"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Home"
126msgstr "Home"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Musica"
146msgstr "Musica"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Cerca"
211msgstr "Cerca"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Nessun risultato corrispondente alla ricerca."
215msgstr "Nessun risultato corrispondente alla ricerca."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Home"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-15 14:12+0000\n"
11"PO-Revision-Date: 2013-06-15 14:12+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Japanese <ja@li.org>\n"
13"Language-Team: Japanese <ja@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr ""
110msgstr ""
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr ""
126msgstr ""
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr ""
146msgstr ""
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,15 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr ""
211msgstr ""
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr ""
215msgstr ""
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
po/kn.po+18−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Kannada <kn@li.org>\n"
13"Language-Team: Kannada <kn@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"
110msgstr "ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "ಮನೆ (Home)"
126msgstr "ಮನೆ (Home)"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "ಸಂಗೀತ"
146msgstr "ಸಂಗೀತ"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "ಹುಡುಕು"
211msgstr "ಹುಡುಕು"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯಾದ ಹೊಂದಾಣಿಕೆಗಳು ದೊರಕುತ್ತಿಲ್ಲ"
215msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯಾದ ಹೊಂದಾಣಿಕೆಗಳು ದೊರಕುತ್ತಿಲ್ಲ"
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "ಹೋಮ್ ಸ್ಕ್ರೀನ್"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "ಜನರು"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "ಹೋಮ್ ಸ್ಕ್ರೀನ್"
po/ko.po+12−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Korean <ko@li.org>\n"
13"Language-Team: Korean <ko@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "내려받을 수 있음"
109msgid "Apps"
109msgid "Apps"
110msgstr "앱"
110msgstr "앱"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "자주 쓰는 앱"
114msgstr "자주 쓰는 앱"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "요즈음 찾는 음악"
118msgstr "요즈음 찾는 음악"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr ""
126msgstr ""
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "음악"
146msgstr "음악"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,15 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "찾기"
211msgstr "찾기"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr ""
215msgstr ""
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
po/ky.po+18−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Kirghiz <ky@li.org>\n"
13"Language-Team: Kirghiz <ky@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Тиркемелер"
110msgstr "Тиркемелер"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Үй папкасы"
126msgstr "Үй папкасы"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Музыка"
146msgstr "Музыка"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Издөө"
211msgstr "Издөө"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Тилекке каршы, сиздин издөөңүзгө эч нерсе дал келген жок."
215msgstr "Тилекке каршы, сиздин издөөңүзгө эч нерсе дал келген жок."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Башкы экран"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Адамдар"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Башкы экран"
po/lv.po+18−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Latvian <lv@li.org>\n"
13"Language-Team: Latvian <lv@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Lietotnes"
110msgstr "Lietotnes"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Mājas"
126msgstr "Mājas"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Mūzika"
146msgstr "Mūzika"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Meklēt"
211msgstr "Meklēt"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
215msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Mājas ekrāns"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Burmese <my@li.org>\n"
13"Language-Team: Burmese <my@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Apps"
110msgstr "Apps"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "ပင်မ"
126msgstr "ပင်မ"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "တေးဂီတ"
146msgstr "တေးဂီတ"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,18 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "ရှာဖွေ"
211msgstr "ရှာဖွေ"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့်တူညီတာဘာမှမရှိပါ။"
215msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့်တူညီတာဘာမှမရှိပါ။"
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "လူ"
po/nb.po+18−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-17 09:10+0000\n"
11"PO-Revision-Date: 2013-06-17 09:10+0000\n"
12"Last-Translator: Joakim Langvand <jlangvand@gmail.com>\n"
12"Last-Translator: Joakim Langvand <jlangvand@gmail.com>\n"
13"Language-Team: Norwegian Bokmal <nb@li.org>\n"
13"Language-Team: Norwegian Bokmal <nb@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Tilgjengelig for nedlasting"
109msgid "Apps"
109msgid "Apps"
110msgstr "Programmer"
110msgstr "Programmer"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Hjem"
126msgstr "Hjem"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Musikk"
146msgstr "Musikk"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr "Enhet"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Flymodus"
207msgstr "Flymodus"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Søk"
211msgstr "Søk"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Søket ga ingen treff."
215msgstr "Søket ga ingen treff."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Hjemmeskjerm"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Dutch <nl@li.org>\n"
13"Language-Team: Dutch <nl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Apps"
110msgstr "Apps"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Hoofdvenster"
126msgstr "Hoofdvenster"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Muziek"
146msgstr "Muziek"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Zoeken"
211msgstr "Zoeken"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
215msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Startscherm"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:43+0000\n"
11"PO-Revision-Date: 2013-06-05 22:43+0000\n"
12"Last-Translator: Piotr Merski <Unknown>\n"
12"Last-Translator: Piotr Merski <Unknown>\n"
13"Language-Team: Polish <pl@li.org>\n"
13"Language-Team: Polish <pl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Dostępne do pobrania"
109msgid "Apps"
109msgid "Apps"
110msgstr "Aplikacje"
110msgstr "Aplikacje"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Często używane aplikacje"
114msgstr "Często używane aplikacje"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Najnowsza muzyka"
118msgstr "Najnowsza muzyka"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Wideo popularne online"
122msgstr "Wideo popularne online"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Dom"
126msgstr "Dom"
135
127
@@ -153,26 +145,6 @@ msgstr "Przeboje"
153msgid "Music"
145msgid "Music"
154msgstr "Muzyka"
146msgstr "Muzyka"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr "Popularne w sieci"
150msgstr "Popularne w sieci"
@@ -193,7 +165,7 @@ msgstr "Obsada:"
193msgid "Author:"
165msgid "Author:"
194msgstr "Autor:"
166msgstr "Autor:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,39 @@ msgstr "Urządzenie"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Tryb samolotowy"
207msgstr "Tryb samolotowy"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Szukaj"
211msgstr "Szukaj"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Nie znaleziono pasujących wyników."
215msgstr "Nie znaleziono pasujących wyników."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Ekran domowy"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
13"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Aplicativos"
110msgstr "Aplicativos"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Início"
126msgstr "Início"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Músicas"
146msgstr "Músicas"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Pesquisar"
211msgstr "Pesquisar"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
215msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Tela inicial"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Romanian <ro@li.org>\n"
13"Language-Team: Romanian <ro@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Aplicații"
110msgstr "Aplicații"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Acasă"
126msgstr "Acasă"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Muzică"
146msgstr "Muzică"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,20 +206,22 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Căutare"
211msgstr "Căutare"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr ""
215msgstr ""
244"Ne pare rău, nu este nimic care se potrivește căutării dumneavoastră."
216"Ne pare rău, nu este nimic care se potrivește căutării dumneavoastră."
245
217
246−#: plugins/Unity/lenses.cpp:39
218+#: Shell.qml:383
247−msgid "Home screen"
248−msgstr "Ecran principal"
249−
250−#: Shell.qml:380
251#, qt-format
219#, qt-format
252−msgid "Please enter %1:"
220+msgid "Please enter %1"
253msgstr ""
221msgstr ""
222+
223+#~ msgid "People"
224+#~ msgstr "Persoane"
225+
226+#~ msgid "Home screen"
227+#~ msgstr "Ecran principal"
po/ru.po+35−52
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-21 10:08+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Andrey Dedikov <iamawesome.ndr@gmail.com>\n"
13"Language-Team: Russian <ru@li.org>\n"
13"Language-Team: Russian <ru@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -63,7 +63,7 @@ msgstr ""
63
63
64#: Applications/applications.js:86
64#: Applications/applications.js:86
65msgid "Evernote"
65msgid "Evernote"
66−msgstr ""
66+msgstr "Evernote"
67
67
68#: Applications/applications.js:91
68#: Applications/applications.js:91
69msgid "Map"
69msgid "Map"
@@ -71,11 +71,11 @@ msgstr ""
71
71
72#: Applications/applications.js:96
72#: Applications/applications.js:96
73msgid "Pinterest"
73msgid "Pinterest"
74−msgstr ""
74+msgstr "Pinterest"
75
75
76#: Applications/applications.js:101
76#: Applications/applications.js:101
77msgid "SoundCloud"
77msgid "SoundCloud"
78−msgstr ""
78+msgstr "SoundCloud"
79
79
80#: Applications/applications.js:106
80#: Applications/applications.js:106
81msgid "Wikipedia"
81msgid "Wikipedia"
@@ -109,27 +109,19 @@ msgstr "Доступно для загрузки"
109msgid "Apps"
109msgid "Apps"
110msgstr "Приложения"
110msgstr "Приложения"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Часто используемые приложения"
114msgstr "Часто используемые приложения"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Недавно прослушанная музыка"
118msgstr "Недавно прослушанная музыка"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Популярные видео из сети"
122msgstr "Популярные видео из сети"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Главная"
126msgstr "Главная"
135
127
@@ -143,7 +135,7 @@ msgstr ""
143
135
144#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
145msgid "New Releases"
137msgid "New Releases"
146−msgstr ""
138+msgstr "Новые релизы"
147
139
148#: Dash/DashMusic.qml:30
140#: Dash/DashMusic.qml:30
149msgid "Top Charting"
141msgid "Top Charting"
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Музыка"
146msgstr "Музыка"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -183,17 +155,17 @@ msgstr "Видео"
183
155
184#: Dash/Video/VideoPreview.qml:98
156#: Dash/Video/VideoPreview.qml:98
185msgid "Directed by:"
157msgid "Directed by:"
186−msgstr ""
158+msgstr "Режиссёр"
187
159
188#: Dash/Video/VideoPreview.qml:121
160#: Dash/Video/VideoPreview.qml:121
189msgid "Starring:"
161msgid "Starring:"
190−msgstr ""
162+msgstr "В главных ролях"
191
163
192#: Dash/Video/VideoPreview.qml:144
164#: Dash/Video/VideoPreview.qml:144
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,30 @@ msgstr "Устройство"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Режим полета"
207msgstr "Режим полета"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Поиск"
211msgstr "Поиск"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Извините, поиск не дал результатов."
215msgstr "Извините, поиск не дал результатов."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Главный экран"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Sinhalese <si@li.org>\n"
13"Language-Team: Sinhalese <si@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr ""
110msgstr ""
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr ""
126msgstr ""
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr ""
146msgstr ""
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,15 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr ""
211msgstr ""
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr ""
215msgstr ""
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
po/sl.po+43−69
@@ -7,83 +7,83 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-09 10:23+0000\n"
11+"PO-Revision-Date: 2013-06-29 10:26+0000\n"
12"Last-Translator: Damir Jerovšek <Unknown>\n"
12"Last-Translator: Damir Jerovšek <Unknown>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16692)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
22−msgstr ""
22+msgstr "Telefon"
23
23
24#: Applications/applications.js:29
24#: Applications/applications.js:29
25msgid "Camera"
25msgid "Camera"
26−msgstr ""
26+msgstr "Fotoaparat"
27
27
28#: Applications/applications.js:35
28#: Applications/applications.js:35
29msgid "Gallery"
29msgid "Gallery"
30−msgstr ""
30+msgstr "Galerija"
31
31
32#: Applications/applications.js:40
32#: Applications/applications.js:40
33msgid "Facebook"
33msgid "Facebook"
34−msgstr ""
34+msgstr "Facebook"
35
35
36#: Applications/applications.js:46
36#: Applications/applications.js:46
37msgid "Browser"
37msgid "Browser"
38−msgstr ""
38+msgstr "Brskalnik"
39
39
40#: Applications/applications.js:51
40#: Applications/applications.js:51
41msgid "Twitter"
41msgid "Twitter"
42−msgstr ""
42+msgstr "Twitter"
43
43
44#: Applications/applications.js:57
44#: Applications/applications.js:57
45msgid "GMail"
45msgid "GMail"
46−msgstr ""
46+msgstr "GMail"
47
47
48#: Applications/applications.js:62
48#: Applications/applications.js:62
49msgid "Weather"
49msgid "Weather"
50−msgstr ""
50+msgstr "Vreme"
51
51
52#: Applications/applications.js:68
52#: Applications/applications.js:68
53msgid "Notepad"
53msgid "Notepad"
54−msgstr ""
54+msgstr "Beležnica"
55
55
56#: Applications/applications.js:74
56#: Applications/applications.js:74
57msgid "Calendar"
57msgid "Calendar"
58−msgstr ""
58+msgstr "Koledar"
59
59
60#: Applications/applications.js:80
60#: Applications/applications.js:80
61msgid "Media Player"
61msgid "Media Player"
62−msgstr ""
62+msgstr "Predvajalnik predstavnosti"
63
63
64#: Applications/applications.js:86
64#: Applications/applications.js:86
65msgid "Evernote"
65msgid "Evernote"
66−msgstr ""
66+msgstr "Evernote"
67
67
68#: Applications/applications.js:91
68#: Applications/applications.js:91
69msgid "Map"
69msgid "Map"
70−msgstr ""
70+msgstr "Zemljevid"
71
71
72#: Applications/applications.js:96
72#: Applications/applications.js:96
73msgid "Pinterest"
73msgid "Pinterest"
74−msgstr ""
74+msgstr "Pinterest"
75
75
76#: Applications/applications.js:101
76#: Applications/applications.js:101
77msgid "SoundCloud"
77msgid "SoundCloud"
78−msgstr ""
78+msgstr "SoundCloud"
79
79
80#: Applications/applications.js:106
80#: Applications/applications.js:106
81msgid "Wikipedia"
81msgid "Wikipedia"
82−msgstr ""
82+msgstr "Wikipedija"
83
83
84#: Applications/applications.js:111
84#: Applications/applications.js:111
85msgid "YouTube"
85msgid "YouTube"
86−msgstr ""
86+msgstr "YouTube"
87
87
88#: Components/PageHeader.qml:300
88#: Components/PageHeader.qml:300
89msgid "Recent searches"
89msgid "Recent searches"
@@ -109,27 +109,19 @@ msgstr "Na voljo za prejem"
109msgid "Apps"
109msgid "Apps"
110msgstr "Programi"
110msgstr "Programi"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Nedavna glasba"
118msgstr "Nedavna glasba"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Domov"
126msgstr "Domov"
135
127
@@ -139,11 +131,11 @@ msgstr ""
139
131
140#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
132#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
141msgid "Recent"
133msgid "Recent"
142−msgstr ""
134+msgstr "Nedavno"
143
135
144#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
145msgid "New Releases"
137msgid "New Releases"
146−msgstr ""
138+msgstr "Nove izdaje"
147
139
148#: Dash/DashMusic.qml:30
140#: Dash/DashMusic.qml:30
149msgid "Top Charting"
141msgid "Top Charting"
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Glasba"
146msgstr "Glasba"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -191,20 +163,20 @@ msgstr ""
191
163
192#: Dash/Video/VideoPreview.qml:144
164#: Dash/Video/VideoPreview.qml:144
193msgid "Author:"
165msgid "Author:"
194−msgstr ""
166+msgstr "Avtor:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198−msgstr ""
170+msgstr "Klic v sili"
199
171
200#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
201#, qt-format
173#, qt-format
202msgid "Hello %1"
174msgid "Hello %1"
203−msgstr ""
175+msgstr "Pozdravljeni, %1"
204
176
205#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
206msgid "Hello"
178msgid "Hello"
207−msgstr ""
179+msgstr "Pozdravljeni"
208
180
209#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
210msgid "Confirm"
182msgid "Confirm"
@@ -234,19 +206,21 @@ msgstr "Naprava"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Način letenja"
207msgstr "Način letenja"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Iskanje"
211msgstr "Iskanje"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Nič se ne ujema z vašim iskalnim nizom."
215msgstr "Nič se ne ujema z vašim iskalnim nizom."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Domači zaslon"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252−msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Serbian <sr@li.org>\n"
13"Language-Team: Serbian <sr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:36+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr "Програми"
110msgstr "Програми"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Почетна"
126msgstr "Почетна"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Музика"
146msgstr "Музика"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,21 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Претрага"
211msgstr "Претрага"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Нажалост, претрага није наишла на икакво подударање."
215msgstr "Нажалост, претрага није наишла на икакво подударање."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Почетни екран"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
221+
222+#~ msgid "People"
223+#~ msgstr "Људи"
224+
225+#~ msgid "Home screen"
226+#~ msgstr "Почетни екран"
po/sv.po+12−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Swedish <sv@li.org>\n"
13"Language-Team: Swedish <sv@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr ""
110msgstr ""
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr ""
126msgstr ""
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr ""
146msgstr ""
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,15 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr ""
211msgstr ""
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr ""
215msgstr ""
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
po/te.po+12−44
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Telugu <te@li.org>\n"
13"Language-Team: Telugu <te@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr ""
109msgid "Apps"
109msgid "Apps"
110msgstr ""
110msgstr ""
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr ""
114msgstr ""
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr ""
118msgstr ""
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr ""
122msgstr ""
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "నివాసం"
126msgstr "నివాసం"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "సంగీతం"
146msgstr "సంగీతం"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,15 @@ msgstr ""
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr ""
207msgstr ""
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr ""
211msgstr ""
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr ""
215msgstr ""
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr ""
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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+59−70
@@ -7,59 +7,59 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-24 17:24+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Adar Cem EREN <adarcemeren34@gmail.com>\n"
13"Language-Team: Turkish <tr@li.org>\n"
13"Language-Team: Turkish <tr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
22−msgstr ""
22+msgstr "Telefon"
23
23
24#: Applications/applications.js:29
24#: Applications/applications.js:29
25msgid "Camera"
25msgid "Camera"
26−msgstr ""
26+msgstr "Kamera"
27
27
28#: Applications/applications.js:35
28#: Applications/applications.js:35
29msgid "Gallery"
29msgid "Gallery"
30−msgstr ""
30+msgstr "Galeri"
31
31
32#: Applications/applications.js:40
32#: Applications/applications.js:40
33msgid "Facebook"
33msgid "Facebook"
34−msgstr ""
34+msgstr "Facebook"
35
35
36#: Applications/applications.js:46
36#: Applications/applications.js:46
37msgid "Browser"
37msgid "Browser"
38−msgstr ""
38+msgstr "Tarayıcı"
39
39
40#: Applications/applications.js:51
40#: Applications/applications.js:51
41msgid "Twitter"
41msgid "Twitter"
42−msgstr ""
42+msgstr "Twitter"
43
43
44#: Applications/applications.js:57
44#: Applications/applications.js:57
45msgid "GMail"
45msgid "GMail"
46−msgstr ""
46+msgstr "GMail"
47
47
48#: Applications/applications.js:62
48#: Applications/applications.js:62
49msgid "Weather"
49msgid "Weather"
50−msgstr ""
50+msgstr "Hava Durumu"
51
51
52#: Applications/applications.js:68
52#: Applications/applications.js:68
53msgid "Notepad"
53msgid "Notepad"
54−msgstr ""
54+msgstr "Not Defteri"
55
55
56#: Applications/applications.js:74
56#: Applications/applications.js:74
57msgid "Calendar"
57msgid "Calendar"
58−msgstr ""
58+msgstr "Takvim"
59
59
60#: Applications/applications.js:80
60#: Applications/applications.js:80
61msgid "Media Player"
61msgid "Media Player"
62−msgstr ""
62+msgstr "Ortam Oynatıcı"
63
63
64#: Applications/applications.js:86
64#: Applications/applications.js:86
65msgid "Evernote"
65msgid "Evernote"
@@ -67,7 +67,7 @@ msgstr ""
67
67
68#: Applications/applications.js:91
68#: Applications/applications.js:91
69msgid "Map"
69msgid "Map"
70−msgstr ""
70+msgstr "Harita"
71
71
72#: Applications/applications.js:96
72#: Applications/applications.js:96
73msgid "Pinterest"
73msgid "Pinterest"
@@ -79,15 +79,15 @@ msgstr ""
79
79
80#: Applications/applications.js:106
80#: Applications/applications.js:106
81msgid "Wikipedia"
81msgid "Wikipedia"
82−msgstr ""
82+msgstr "Vikipedi"
83
83
84#: Applications/applications.js:111
84#: Applications/applications.js:111
85msgid "YouTube"
85msgid "YouTube"
86−msgstr ""
86+msgstr "YouTube"
87
87
88#: Components/PageHeader.qml:300
88#: Components/PageHeader.qml:300
89msgid "Recent searches"
89msgid "Recent searches"
90−msgstr "Son aramalar"
90+msgstr "Son Arananlar"
91
91
92#: Dash/DashApps.qml:65
92#: Dash/DashApps.qml:65
93msgid "Running apps"
93msgid "Running apps"
@@ -109,37 +109,29 @@ msgstr "İndirilebilir durumda"
109msgid "Apps"
109msgid "Apps"
110msgstr "Uygulamalar"
110msgstr "Uygulamalar"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Sıkça Kullanılan Uygulamalar"
114msgstr "Sıkça Kullanılan Uygulamalar"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "En Son Müzik"
118msgstr "En Son Müzik"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Çevrimiçi Yaygın Videolar"
122msgstr "Çevrimiçi Yaygın Videolar"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134−msgstr "Ev"
126+msgstr "Ana Sayfa"
135
127
136#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
128#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
137msgid "Featured"
129msgid "Featured"
138−msgstr ""
130+msgstr "Öne Çıkanlar"
139
131
140#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
132#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
141msgid "Recent"
133msgid "Recent"
142−msgstr ""
134+msgstr "En Son"
143
135
144#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
145msgid "New Releases"
137msgid "New Releases"
@@ -153,29 +145,9 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "Müzik"
146msgstr "Müzik"
155
147
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 "Kişiler"
175−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178−msgstr ""
150+msgstr "Genellikle Çevrimiçi"
179
151
180#: Dash/DashVideos.qml:155
152#: Dash/DashVideos.qml:155
181msgid "Videos"
153msgid "Videos"
@@ -183,7 +155,7 @@ msgstr "Videolar"
183
155
184#: Dash/Video/VideoPreview.qml:98
156#: Dash/Video/VideoPreview.qml:98
185msgid "Directed by:"
157msgid "Directed by:"
186−msgstr ""
158+msgstr "Yönetmen"
187
159
188#: Dash/Video/VideoPreview.qml:121
160#: Dash/Video/VideoPreview.qml:121
189msgid "Starring:"
161msgid "Starring:"
@@ -191,11 +163,11 @@ msgstr ""
191
163
192#: Dash/Video/VideoPreview.qml:144
164#: Dash/Video/VideoPreview.qml:144
193msgid "Author:"
165msgid "Author:"
194−msgstr ""
166+msgstr "Yazar:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198−msgstr ""
170+msgstr "Acil Arama"
199
171
200#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
201#, qt-format
173#, qt-format
@@ -204,7 +176,7 @@ msgstr ""
204
176
205#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
206msgid "Hello"
178msgid "Hello"
207−msgstr ""
179+msgstr "Merhaba"
208
180
209#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
210msgid "Confirm"
182msgid "Confirm"
@@ -232,21 +204,38 @@ msgstr "Aygıt"
232
204
233#: Panel/Menus/Overview/FlightModeWidget.qml:42
205#: Panel/Menus/Overview/FlightModeWidget.qml:42
234msgid "Flight mode"
206msgid "Flight mode"
235−msgstr "Uçak kipi"
207+msgstr "Uçak Modu"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Ara"
211msgstr "Ara"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
215msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Başlangıç ekranı"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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+59−70
@@ -7,23 +7,23 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-06 07:40+0000\n"
11+"PO-Revision-Date: 2013-06-28 04:36+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Gheyret T.Kenji <Unknown>\n"
13"Language-Team: Uyghur <ug@li.org>\n"
13"Language-Team: Uyghur <ug@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16692)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
22−msgstr ""
22+msgstr "تېلېفون"
23
23
24#: Applications/applications.js:29
24#: Applications/applications.js:29
25msgid "Camera"
25msgid "Camera"
26−msgstr ""
26+msgstr "كامېرا"
27
27
28#: Applications/applications.js:35
28#: Applications/applications.js:35
29msgid "Gallery"
29msgid "Gallery"
@@ -31,59 +31,59 @@ msgstr ""
31
31
32#: Applications/applications.js:40
32#: Applications/applications.js:40
33msgid "Facebook"
33msgid "Facebook"
34−msgstr ""
34+msgstr "فېيىسبۇك(Facebook)"
35
35
36#: Applications/applications.js:46
36#: Applications/applications.js:46
37msgid "Browser"
37msgid "Browser"
38−msgstr ""
38+msgstr "توركۆرگۈ"
39
39
40#: Applications/applications.js:51
40#: Applications/applications.js:51
41msgid "Twitter"
41msgid "Twitter"
42−msgstr ""
42+msgstr "تىۋىتتېر(Twitter)"
43
43
44#: Applications/applications.js:57
44#: Applications/applications.js:57
45msgid "GMail"
45msgid "GMail"
46−msgstr ""
46+msgstr "GMail"
47
47
48#: Applications/applications.js:62
48#: Applications/applications.js:62
49msgid "Weather"
49msgid "Weather"
50−msgstr ""
50+msgstr "ھاۋا رايى"
51
51
52#: Applications/applications.js:68
52#: Applications/applications.js:68
53msgid "Notepad"
53msgid "Notepad"
54−msgstr ""
54+msgstr "خاتىرە دەپتەر(Notepad)"
55
55
56#: Applications/applications.js:74
56#: Applications/applications.js:74
57msgid "Calendar"
57msgid "Calendar"
58−msgstr ""
58+msgstr "يىلنامە"
59
59
60#: Applications/applications.js:80
60#: Applications/applications.js:80
61msgid "Media Player"
61msgid "Media Player"
62−msgstr ""
62+msgstr "ۋاسىتە قويغۇ"
63
63
64#: Applications/applications.js:86
64#: Applications/applications.js:86
65msgid "Evernote"
65msgid "Evernote"
66−msgstr ""
66+msgstr "Evernote"
67
67
68#: Applications/applications.js:91
68#: Applications/applications.js:91
69msgid "Map"
69msgid "Map"
70−msgstr ""
70+msgstr "خەرىتە"
71
71
72#: Applications/applications.js:96
72#: Applications/applications.js:96
73msgid "Pinterest"
73msgid "Pinterest"
74−msgstr ""
74+msgstr "Pinterest"
75
75
76#: Applications/applications.js:101
76#: Applications/applications.js:101
77msgid "SoundCloud"
77msgid "SoundCloud"
78−msgstr ""
78+msgstr "SoundCloud"
79
79
80#: Applications/applications.js:106
80#: Applications/applications.js:106
81msgid "Wikipedia"
81msgid "Wikipedia"
82−msgstr ""
82+msgstr "ۋىكىپېدىيە"
83
83
84#: Applications/applications.js:111
84#: Applications/applications.js:111
85msgid "YouTube"
85msgid "YouTube"
86−msgstr ""
86+msgstr "YouTube"
87
87
88#: Components/PageHeader.qml:300
88#: Components/PageHeader.qml:300
89msgid "Recent searches"
89msgid "Recent searches"
@@ -109,41 +109,33 @@ msgstr "چۈشۈرگىلى بولىدىغانلىرى"
109msgid "Apps"
109msgid "Apps"
110msgstr "ئەپلەر"
110msgstr "ئەپلەر"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "دائىم ئىشلىتىلىدىغان ئەپلەر"
114msgstr "دائىم ئىشلىتىلىدىغان ئەپلەر"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "يېقىندا ئاڭلىغان مۇزىكىلار"
118msgstr "يېقىندا ئاڭلىغان مۇزىكىلار"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "توردىكى ئالقىشقا ئېرىشكەن سىنلار"
122msgstr "توردىكى ئالقىشقا ئېرىشكەن سىنلار"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "ماكان"
126msgstr "ماكان"
135
127
136#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
128#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
137msgid "Featured"
129msgid "Featured"
138−msgstr ""
130+msgstr "داڭلىق"
139
131
140#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
132#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
141msgid "Recent"
133msgid "Recent"
142−msgstr ""
134+msgstr "يېقىنقى"
143
135
144#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
145msgid "New Releases"
137msgid "New Releases"
146−msgstr ""
138+msgstr "يېڭى ئېلان قىلىنغانلىرى"
147
139
148#: Dash/DashMusic.qml:30
140#: Dash/DashMusic.qml:30
149msgid "Top Charting"
141msgid "Top Charting"
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "مۇزىكا"
146msgstr "مۇزىكا"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -191,20 +163,20 @@ msgstr ""
191
163
192#: Dash/Video/VideoPreview.qml:144
164#: Dash/Video/VideoPreview.qml:144
193msgid "Author:"
165msgid "Author:"
194−msgstr ""
166+msgstr "ئاپتور:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198−msgstr ""
170+msgstr "جىددىي تېلېفون"
199
171
200#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
201#, qt-format
173#, qt-format
202msgid "Hello %1"
174msgid "Hello %1"
203−msgstr ""
175+msgstr "سالام %1"
204
176
205#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
206msgid "Hello"
178msgid "Hello"
207−msgstr ""
179+msgstr "سالام"
208
180
209#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
210msgid "Confirm"
182msgid "Confirm"
@@ -234,19 +206,36 @@ msgstr "ئۈسكۈنە"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "ئايروپىلاندا"
207msgstr "ئايروپىلاندا"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "ئىزدە"
211msgstr "ئىزدە"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپىلمىدى."
215msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپىلمىدى."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "ماكان ئېكران"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252−msgstr ""
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+42−50
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-14 11:26+0000\n"
11+"PO-Revision-Date: 2013-06-29 14:27+0000\n"
12−"Last-Translator: Yuri Chornoivan <yurchor@gmail.com>\n"
12+"Last-Translator: Roman Koshkin <mar2008m@rambler.ru>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16692)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "Доступно до завантаження"
109msgid "Apps"
109msgid "Apps"
110msgstr "Програми"
110msgstr "Програми"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "Часто використовувані програми"
114msgstr "Часто використовувані програми"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "Нещодавно прослухана музика"
118msgstr "Нещодавно прослухана музика"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "Популярні в мережі відео"
122msgstr "Популярні в мережі відео"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "Домівка"
126msgstr "Домівка"
135
127
@@ -153,26 +145,6 @@ msgstr "З високими оцінками"
153msgid "Music"
145msgid "Music"
154msgstr "Музика"
146msgstr "Музика"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr "Популярне у мережі"
150msgstr "Популярне у мережі"
@@ -193,18 +165,18 @@ msgstr "Актори:"
193msgid "Author:"
165msgid "Author:"
194msgstr "Автор:"
166msgstr "Автор:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198−msgstr ""
170+msgstr "Екстрений виклик"
199
171
200#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
201#, qt-format
173#, qt-format
202msgid "Hello %1"
174msgid "Hello %1"
203−msgstr ""
175+msgstr "Привіт, %1"
204
176
205#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
206msgid "Hello"
178msgid "Hello"
207−msgstr ""
179+msgstr "Привіт!"
208
180
209#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
210msgid "Confirm"
182msgid "Confirm"
@@ -234,19 +206,39 @@ msgstr "Пристрій"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "Автономний режим"
207msgstr "Автономний режим"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "Пошук"
211msgstr "Пошук"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "Вибачте, для вказаних вами ключових слів нічого не знайдено."
215msgstr "Вибачте, для вказаних вами ключових слів нічого не знайдено."
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "Екран домівки"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252−msgstr ""
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 ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"
10"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
11+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -165,7 +165,7 @@ msgstr ""
165msgid "Author:"
165msgid "Author:"
166msgstr ""
166msgstr ""
167
167
168−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
169msgid "Emergency call"
169msgid "Emergency call"
170msgstr ""
170msgstr ""
171
171
@@ -214,12 +214,7 @@ msgstr ""
214msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
215msgstr ""
215msgstr ""
216
216
217−#: Shell.qml:380
217+#: Shell.qml:383
218#, qt-format
218#, qt-format
219−msgid "Please enter %1:"
219+msgid "Please enter %1"
220−msgstr ""
221−
222−#: Shell.qml:380
223−#, qt-format
224−msgid "Please enter %1:"
225msgstr ""
220msgstr ""
po/zh_CN.po+41−49
@@ -7,15 +7,15 @@ msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-13 11:35+0000\n"
11+"PO-Revision-Date: 2013-06-22 21:20+0000\n"
12−"Last-Translator: Wylmer Wang <Unknown>\n"
12+"Last-Translator: Anthony Wong <anthony.wong@canonical.com>\n"
13"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
13"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "可供下载"
109msgid "Apps"
109msgid "Apps"
110msgstr "应用程序"
110msgstr "应用程序"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "常用软件"
114msgstr "常用软件"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "近期听过的音乐"
118msgstr "近期听过的音乐"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "热门在线视频"
122msgstr "热门在线视频"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "主页"
126msgstr "主页"
135
127
@@ -153,26 +145,6 @@ msgstr "排行榜图"
153msgid "Music"
145msgid "Music"
154msgstr "音乐"
146msgstr "音乐"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr "经常在线"
150msgstr "经常在线"
@@ -193,18 +165,18 @@ msgstr "主演:"
193msgid "Author:"
165msgid "Author:"
194msgstr "作者:"
166msgstr "作者:"
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198−msgstr ""
170+msgstr "紧急呼救"
199
171
200#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
201#, qt-format
173#, qt-format
202msgid "Hello %1"
174msgid "Hello %1"
203−msgstr ""
175+msgstr "你好,%1"
204
176
205#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
206msgid "Hello"
178msgid "Hello"
207−msgstr ""
179+msgstr "你好"
208
180
209#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
210msgid "Confirm"
182msgid "Confirm"
@@ -234,19 +206,39 @@ msgstr "设备"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "飞行模式"
207msgstr "飞行模式"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "搜索"
211msgstr "搜索"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "对不起,没有找到您想要的结果。"
215msgstr "对不起,没有找到您想要的结果。"
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "主页"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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 ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10−"POT-Creation-Date: 2013-06-19 17:06+0200\n"
10+"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11"PO-Revision-Date: 2013-06-05 22:20+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
13"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-20 06:37+0000\n"
17+"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16673)\n"
18+"X-Generator: Launchpad (build 16681)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -109,27 +109,19 @@ msgstr "可供下載"
109msgid "Apps"
109msgid "Apps"
110msgstr "程式"
110msgstr "程式"
111
111
112−#: Dash/DashHome.qml:43
112+#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114msgstr "常用的程式"
114msgstr "常用的程式"
115
115
116−#: Dash/DashHome.qml:46
116+#: Dash/DashHome.qml:43
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
125msgid "Recent Music"
117msgid "Recent Music"
126msgstr "最近聽過的音樂"
118msgstr "最近聽過的音樂"
127
119
128−#: Dash/DashHome.qml:55
120+#: Dash/DashHome.qml:46
129msgid "Videos Popular Online"
121msgid "Videos Popular Online"
130msgstr "線上熱門的影片"
122msgstr "線上熱門的影片"
131
123
132−#: Dash/DashHome.qml:197 plugins/Unity/lenses.cpp:38
124+#: Dash/DashHome.qml:175
133msgid "Home"
125msgid "Home"
134msgstr "家屋"
126msgstr "家屋"
135
127
@@ -153,26 +145,6 @@ msgstr ""
153msgid "Music"
145msgid "Music"
154msgstr "音樂"
146msgstr "音樂"
155
147
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−
176#: Dash/DashVideos.qml:31
148#: Dash/DashVideos.qml:31
177msgid "Popular Online"
149msgid "Popular Online"
178msgstr ""
150msgstr ""
@@ -193,7 +165,7 @@ msgstr ""
193msgid "Author:"
165msgid "Author:"
194msgstr ""
166msgstr ""
195
167
196−#: Greeter/Lockscreen.qml:126
168+#: Greeter/Lockscreen.qml:133
197msgid "Emergency call"
169msgid "Emergency call"
198msgstr ""
170msgstr ""
199
171
@@ -234,19 +206,27 @@ msgstr "裝置"
234msgid "Flight mode"
206msgid "Flight mode"
235msgstr "飛航模式"
207msgstr "飛航模式"
236
208
237−#: Panel/SearchIndicator.qml:26 plugins/Unity/lenses.cpp:40
209+#: Panel/SearchIndicator.qml:26
238msgid "Search"
210msgid "Search"
239msgstr "搜尋"
211msgstr "搜尋"
240
212
241−#: plugins/Unity/lens.cpp:333
213+#: plugins/Unity/scope.cpp:268
242msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
243msgstr "很抱歉,找不到符合您想搜尋的結果。"
215msgstr "很抱歉,找不到符合您想搜尋的結果。"
244
216
245−#: plugins/Unity/lenses.cpp:39
217+#: Shell.qml:383
246−msgid "Home screen"
247−msgstr "家屋畫面"
248−
249−#: Shell.qml:380
250#, qt-format
218#, qt-format
251−msgid "Please enter %1:"
219+msgid "Please enter %1"
252msgstr ""
220msgstr ""
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+3−4
@@ -1,7 +1,6 @@
1#!/bin/sh
1#!/bin/sh
2
2
3QML_PHONE_SHELL_PATH=./builddir/unity8
3QML_PHONE_SHELL_PATH=./builddir/unity8
4−export LD_LIBRARY_PATH=$PWD/../unity_build/build/lib
5GDB=false
4GDB=false
6FAKE=false
5FAKE=false
7PINLOCK=false
6PINLOCK=false
@@ -42,17 +41,17 @@ done
42
41
43if $FAKE; then
42if $FAKE; then
44 export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins
43 export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins
45− export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/single
44+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single
46fi
45fi
47
46
48if $PINLOCK; then
47if $PINLOCK; then
49 export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins
48 export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins
50− export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/single-pin
49+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-pin
51fi
50fi
52
51
53if $KEYLOCK; then
52if $KEYLOCK; then
54 export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins
53 export QML2_IMPORT_PATH=$PWD/builddir/tests/mocks:$PWD/builddir/plugins
55− export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/LightDM/single-passphrase
54+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/tests/mocks/libusermetrics:$PWD/builddir/tests/mocks/LightDM/single-passphrase
56fi
55fi
57
56
58# Force icon theme if running on the desktop, otherwise gnome theme (if running
57# Force icon theme if running on the desktop, otherwise gnome theme (if running
run_on_device+26−9
@@ -15,6 +15,8 @@ PINLOCK=false
15KEYLOCK=false
15KEYLOCK=false
16SUDO="echo $PASSWORD | sudo -S"
16SUDO="echo $PASSWORD | sudo -S"
17NUM_JOBS='$(( `grep -c ^processor /proc/cpuinfo` + 1 ))'
17NUM_JOBS='$(( `grep -c ^processor /proc/cpuinfo` + 1 ))'
18+FLIPPED=false
19+CHROOT_PREFIX="/data/ubuntu"
18
20
19usage() {
21usage() {
20 echo "usage: run_on_device [OPTIONS]\n"
22 echo "usage: run_on_device [OPTIONS]\n"
@@ -35,7 +37,11 @@ exec_with_ssh() {
35}
37}
36
38
37exec_with_adb() {
39exec_with_adb() {
38− adb shell chroot /data/ubuntu /usr/bin/env -i PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin "$@"
40+ if $FLIPPED; then
41+ adb shell $@
42+ else
43+ adb shell chroot /data/ubuntu /usr/bin/env -i PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin "$@"
44+ fi
39}
45}
40
46
41adb_root() {
47adb_root() {
@@ -45,7 +51,7 @@ adb_root() {
45
51
46install_ssh_key() {
52install_ssh_key() {
47 ssh-keygen -R $TARGET_IP
53 ssh-keygen -R $TARGET_IP
48− HOME_DIR=/data/ubuntu/home/phablet
54+ HOME_DIR="${CHROOT_PREFIX}/home/phablet"
49 adb push ~/.ssh/id_rsa.pub $HOME_DIR/.ssh/authorized_keys
55 adb push ~/.ssh/id_rsa.pub $HOME_DIR/.ssh/authorized_keys
50 adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh
56 adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh
51 adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh/authorized_keys
57 adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh/authorized_keys
@@ -69,7 +75,7 @@ install_dependencies() {
69sync_code() {
75sync_code() {
70 [ -e .bzr ] && bzr export --uncommitted --format=dir /tmp/$CODE_DIR
76 [ -e .bzr ] && bzr export --uncommitted --format=dir /tmp/$CODE_DIR
71 [ -e .git ] && git checkout-index -a -f --prefix=/tmp/$CODE_DIR/
77 [ -e .git ] && git checkout-index -a -f --prefix=/tmp/$CODE_DIR/
72− 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/
73 rm -rf /tmp/$CODE_DIR
79 rm -rf /tmp/$CODE_DIR
74}
80}
75
81
@@ -79,16 +85,16 @@ build() {
79}
85}
80
86
81run() {
87run() {
82− SERVICEFILE="/data/ubuntu/etc/device-services"
88+ SERVICEFILE="${CHROOT_PREFIX}/etc/device-services"
83− adb shell "egrep '$BINARY|qml-phone-shell' $SERVICEFILE"
89+ adb shell "egrep '$BINARY' $SERVICEFILE"
84 CONTAINS_SHELL=$?
90 CONTAINS_SHELL=$?
85 if [ $CONTAINS_SHELL -eq 0 ]; then
91 if [ $CONTAINS_SHELL -eq 0 ]; then
86 echo "Modifying $SERVICEFILE on device. Old contents will be saved in $SERVICEFILE.backup"
92 echo "Modifying $SERVICEFILE on device. Old contents will be saved in $SERVICEFILE.backup"
87 adb shell cp $SERVICEFILE $SERVICEFILE.backup
93 adb shell cp $SERVICEFILE $SERVICEFILE.backup
88− adb shell sed -i "/$BINARY\\\\\|qml-phone-shell/d" $SERVICEFILE
94+ adb shell sed -i "/$BINARY/d" $SERVICEFILE
89− adb shell "chroot /data/ubuntu /usr/bin/service ubuntu-session restart"
95+ if $FLIPPED; then exec_with_adb /usr/bin/service ubuntu-touch-session restart
96+ else exec_with_adb /usr/bin/service ubuntu-session restart; fi
90 fi
97 fi
91− adb shell pkill qml-phone-shell
92 adb shell pkill $BINARY
98 adb shell pkill $BINARY
93 ARGS="--nomousetouch"
99 ARGS="--nomousetouch"
94 if $GDB; then
100 if $GDB; then
@@ -106,7 +112,8 @@ run() {
106 if [ $CONTAINS_SHELL -eq 0 ]; then
112 if [ $CONTAINS_SHELL -eq 0 ]; then
107 echo "Restoring $SERVICEFILE on device from $SERVICEFILE.backup"
113 echo "Restoring $SERVICEFILE on device from $SERVICEFILE.backup"
108 adb shell cp $SERVICEFILE.backup $SERVICEFILE
114 adb shell cp $SERVICEFILE.backup $SERVICEFILE
109− adb shell "chroot /data/ubuntu /usr/bin/service ubuntu-session restart"
115+ if $FLIPPED; then exec_with_adb /usr/bin/service ubuntu-touch-session restart
116+ else exec_with_adb /usr/bin/service ubuntu-session restart; fi
110 fi
117 fi
111}
118}
112
119
@@ -130,6 +137,16 @@ done
130adb_root
137adb_root
131[ "${TARGET_IP}" = "127.0.0.1" ] && setup_adb_forwarding
138[ "${TARGET_IP}" = "127.0.0.1" ] && setup_adb_forwarding
132
139
140+if [ "`adb shell 'grep -q Ubuntu /etc/lsb-release 2> /dev/null && echo -n FLIPPED'`" = "FLIPPED" ]; then
141+ FLIPPED=true
142+ CHROOT_PREFIX=""
143+ if [ "${TARGET_IP}" != "127.0.0.1" ]; then
144+ echo "ERROR: Flipped image detected, adb over TCP/IP isn't supported, yet :/"
145+ echo "Unset TARGET_IP and try again."
146+ exit 2
147+ fi
148+fi
149+
133if $SETUP; then
150if $SETUP; then
134 echo "Setting up environment for building shell.."
151 echo "Setting up environment for building shell.."
135 install_ssh_key
152 install_ssh_key
tests/autopilot/setup.pynew file+21
@@ -0,0 +1,21 @@
1+#!/usr/bin/python
2+
3+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
4+# Copyright 2013 Canonical
5+#
6+# This program is free software: you can redistribute it and/or modify it
7+# under the terms of the GNU General Public License version 3, as published
8+# by the Free Software Foundation.
9+
10+
11+from distutils.core import setup
12+from setuptools import find_packages
13+
14+setup(
15+ name='unity',
16+ version='8.0',
17+ description='Unity 8 autopilot tests.',
18+ url='https://launchpad.net/unity',
19+ license='GPLv3',
20+ packages=find_packages(),
21+)
tests/autopilot/unity8/tests/__init__.py+6−4
@@ -8,6 +8,7 @@
8"""unity8 autopilot tests."""
8"""unity8 autopilot tests."""
9
9
10import os.path
10import os.path
11+import sysconfig
11
12
12from autopilot.testcase import AutopilotTestCase
13from autopilot.testcase import AutopilotTestCase
13from autopilot.matchers import Eventually
14from autopilot.matchers import Eventually
@@ -23,6 +24,7 @@ class ShellTestCase(AutopilotTestCase):
23
24
24 """A common test case class that provides several useful methods for shell tests."""
25 """A common test case class that provides several useful methods for shell tests."""
25
26
27+ libdir = "/usr/lib/{0}/unity8".format(sysconfig.get_config_var('MULTIARCH'))
26 lightdm_mock = "full"
28 lightdm_mock = "full"
27
29
28 def setUp(self, geometry, grid_size):
30 def setUp(self, geometry, grid_size):
@@ -39,8 +41,8 @@ class ShellTestCase(AutopilotTestCase):
39 self.launch_test_local(geometry)
41 self.launch_test_local(geometry)
40
42
41 def launch_test_local(self, geometry):
43 def launch_test_local(self, geometry):
42− os.environ['LD_LIBRARY_PATH'] = "../../../unity_build/build/lib:../../builddir/tests/mocks/LightDM/" + self.lightdm_mock
44+ os.environ['LD_LIBRARY_PATH'] = "../../builddir/tests/mocks/libusermetrics:../../builddir/tests/mocks/LightDM" + self.lightdm_mock
43− os.environ['QML2_IMPORT_PATH'] = "../../builddir/tests/mocks:../../builddir/plugins"
45+ os.environ['QML2_IMPORT_PATH'] = "../../builddir/tests/mocks"
44 if geometry != "0x0":
46 if geometry != "0x0":
45 self.app = self.launch_test_application(
47 self.app = self.launch_test_application(
46 "../../builddir/unity8", "-geometry", geometry, "-frameless", app_type='qt')
48 "../../builddir/unity8", "-geometry", geometry, "-frameless", app_type='qt')
@@ -49,8 +51,8 @@ class ShellTestCase(AutopilotTestCase):
49 "../../builddir/unity8", "-fullscreen", app_type='qt')
51 "../../builddir/unity8", "-fullscreen", app_type='qt')
50
52
51 def launch_test_installed(self, geometry):
53 def launch_test_installed(self, geometry):
52− os.environ['LD_LIBRARY_PATH'] = "/usr/share/unity8/plugins/mocks/LightDM/" + self.lightdm_mock
54+ os.environ['LD_LIBRARY_PATH'] = "{0}/qml/mocks/libusermetrics:{0}/qml/mocks/LightDM/{1}".format(self.libdir, self.lightdm_mock)
53− os.environ['QML2_IMPORT_PATH'] = "/usr/share/unity8/plugins/mocks:/usr/share/unity8/plugins"
55+ os.environ['QML2_IMPORT_PATH'] = "{0}/qml/mocks".format(self.libdir)
54 if model() == 'Desktop' and geometry != "0x0":
56 if model() == 'Desktop' and geometry != "0x0":
55 self.app = self.launch_test_application(
57 self.app = self.launch_test_application(
56 "unity8", "-geometry", geometry, "-frameless", app_type='qt')
58 "unity8", "-geometry", geometry, "-frameless", app_type='qt')
tests/autopilot/unity8/tests/helpers.py+2−1
@@ -98,7 +98,8 @@ class TestShellHelpers(object):
98 # go to the void for the first time because there's no real way to know what the display has
98 # go to the void for the first time because there's no real way to know what the display has
99 # painted already. Give it another (max retries) chance.
99 # painted already. Give it another (max retries) chance.
100 try:
100 try:
101− self.assertThat(lambda: getattr(bottombar, "__applicationInFocus"), Eventually(Equals(True)))
101+ self.assertThat(lambda: getattr(bottombar, "applicationIsOnForeground"),
102+ Eventually(Equals(True)))
102 except:
103 except:
103 if retries > 0:
104 if retries > 0:
104 logger.warning("Failed to launch app. Retrying...")
105 logger.warning("Failed to launch app. Retrying...")
tests/mocks/CMakeLists.txt+3
@@ -1,2 +1,5 @@
1+add_subdirectory(libusermetrics)
1add_subdirectory(LightDM)
2add_subdirectory(LightDM)
2add_subdirectory(Ubuntu)
3add_subdirectory(Ubuntu)
4+add_subdirectory(Unity)
5+add_subdirectory(HudClient)
tests/qmltests/plugins/HudClient/CMakeLists.txt → tests/mocks/HudClient/CMakeLists.txtrenamed

The content is the same.

tests/qmltests/plugins/HudClient/fake_hud_plugin.cpp → tests/mocks/HudClient/fake_hud_plugin.cpprenamed

The content is the same.

tests/qmltests/plugins/HudClient/fake_hud_plugin.h → tests/mocks/HudClient/fake_hud_plugin.hrenamed

The content is the same.

tests/qmltests/plugins/HudClient/fake_libhud_client.cpp → tests/mocks/HudClient/fake_libhud_client.cpprenamed

The content is the same.

tests/qmltests/plugins/HudClient/libhud_client_stub.cpp → tests/mocks/HudClient/libhud_client_stub.cpprenamed

The content is the same.

tests/qmltests/plugins/HudClient/libhud_client_stub.h → tests/mocks/HudClient/libhud_client_stub.hrenamed

The content is the same.

tests/qmltests/plugins/HudClient/qmldir → tests/mocks/HudClient/qmldirrenamed

The content is the same.

tests/mocks/LightDM/CMakeLists.txt+5−2
@@ -13,6 +13,7 @@ add_subdirectory(single-passphrase)
13include_directories(
13include_directories(
14 ${CMAKE_CURRENT_SOURCE_DIR}
14 ${CMAKE_CURRENT_SOURCE_DIR}
15 ${CMAKE_CURRENT_BINARY_DIR}
15 ${CMAKE_CURRENT_BINARY_DIR}
16+ ${CMAKE_SOURCE_DIR}/tests/mocks/libusermetrics
16)
17)
17
18
18set(QMLPLUGIN_SRC
19set(QMLPLUGIN_SRC
@@ -34,6 +35,8 @@ add_dependencies(MockLightDM-qml MockLightDM-full)
34target_link_libraries(MockLightDM-qml
35target_link_libraries(MockLightDM-qml
35 -L${CMAKE_CURRENT_BINARY_DIR}/full
36 -L${CMAKE_CURRENT_BINARY_DIR}/full
36 -llightdm-qt5-2
37 -llightdm-qt5-2
38+ -L${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics
39+ -lusermetricsoutput
37 )
40 )
38
41
39qt5_use_modules(MockLightDM-qml Gui Qml)
42qt5_use_modules(MockLightDM-qml Gui Qml)
@@ -44,9 +47,9 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
44 )
47 )
45
48
46install(TARGETS MockLightDM-qml
49install(TARGETS MockLightDM-qml
47− DESTINATION ${SHELL_APP_DIR}/plugins/mocks/LightDM
50+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM
48 )
51 )
49
52
50install(FILES qmldir
53install(FILES qmldir
51− DESTINATION ${SHELL_APP_DIR}/plugins/mocks/LightDM
54+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM
52 )
55 )
tests/mocks/LightDM/InfographicModel.cppdeleted−416
@@ -1,416 +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− * Author: Pete Woods <pete.woods@canonical.com>
17− */
18−
19−#include "InfographicModelPrivate.h"
20−#include "InfographicModel.h"
21−
22−#include <QtCore/QDir>
23−#include <QtCore/QString>
24−#include <QtGui/QIcon>
25−#include <QMultiMap>
26−
27−using namespace QLightDM;
28−
29−namespace QLightDM
30−{
31−
32−class InfographicColorThemePrivate: QObject
33−{
34−public:
35− explicit InfographicColorThemePrivate(InfographicColorTheme *parent = 0);
36−
37− InfographicColorThemePrivate(const QColor &start, const QColor &main,
38− const QColor &end, InfographicColorTheme *parent = 0);
39−
40− ~InfographicColorThemePrivate();
41−
42− InfographicColorTheme * const q_ptr;
43−
44− QColor m_start;
45−
46− QColor m_main;
47−
48− QColor m_end;
49−
50−protected:
51− int calculateLength();
52−
53−private:
54− Q_DECLARE_PUBLIC(InfographicColorTheme)
55−};
56−
57−class InfographicDataPrivate: QObject
58−{
59−public:
60− explicit InfographicDataPrivate(InfographicData *parent);
61−
62− InfographicDataPrivate(const QString &label,
63− const InfographicColorTheme &firstColor,
64− const QVariantList &firstMonth,
65− const InfographicColorTheme &secondColor,
66− const QVariantList &secondMonth, InfographicData *parent);
67−
68− ~InfographicDataPrivate();
69−
70− InfographicData * const q_ptr;
71− QString m_label;
72− InfographicColorTheme m_firstColor;
73− QVariantList m_firstMonth;
74− InfographicColorTheme m_secondColor;
75− QVariantList m_secondMonth;
76− int m_length;
77−
78−protected:
79− int calculateLength();
80−
81−private:
82− Q_DECLARE_PUBLIC(InfographicData)
83−};
84−
85−}
86−
87−InfographicColorThemePrivate::InfographicColorThemePrivate(
88− InfographicColorTheme *parent) :
89− q_ptr(parent)
90−{
91−}
92−
93−InfographicColorThemePrivate::InfographicColorThemePrivate(const QColor &start,
94− const QColor &main, const QColor &end, InfographicColorTheme *parent) :
95− q_ptr(parent), m_start(start), m_main(main), m_end(end)
96−{
97−}
98−
99−InfographicColorThemePrivate::~InfographicColorThemePrivate()
100−{
101−}
102−
103−InfographicColorTheme::InfographicColorTheme(QObject *parent) :
104− QObject(parent), d_ptr(new InfographicColorThemePrivate(this))
105−{
106−}
107−
108−InfographicColorTheme::InfographicColorTheme(QColor &first, QColor &main,
109− QColor &end, QObject *parent) :
110− QObject(parent), d_ptr(
111− new InfographicColorThemePrivate(first, main, end, this))
112−{
113−
114−}
115−
116−InfographicColorTheme & InfographicColorTheme::operator=(
117− const InfographicColorTheme & other)
118−{
119− if (d_ptr->m_start != other.d_ptr->m_start)
120− {
121− d_ptr->m_start = other.d_ptr->m_start;
122− startChanged(d_ptr->m_start);
123− }
124− if (d_ptr->m_main != other.d_ptr->m_main)
125− {
126− d_ptr->m_main = other.d_ptr->m_main;
127− mainChanged(d_ptr->m_main);
128− }
129−
130− if (d_ptr->m_end != other.d_ptr->m_end)
131− {
132− d_ptr->m_end = other.d_ptr->m_end;
133− endChanged(d_ptr->m_end);
134− }
135−
136− return *this;
137−}
138−
139−InfographicColorTheme::~InfographicColorTheme()
140−{
141− delete d_ptr;
142−}
143−
144−QColor InfographicColorTheme::start() const
145−{
146− return d_ptr->m_start;
147−}
148−
149−QColor InfographicColorTheme::main() const
150−{
151− return d_ptr->m_main;
152−}
153−
154−QColor InfographicColorTheme::end() const
155−{
156− return d_ptr->m_end;
157−}
158−
159−InfographicDataPrivate::InfographicDataPrivate(InfographicData *parent) :
160− q_ptr(parent), m_firstColor(this), m_secondColor(this)
161−{
162− m_length = calculateLength();
163−}
164−
165−InfographicDataPrivate::InfographicDataPrivate(const QString &label,
166− const InfographicColorTheme &firstColor, const QVariantList &firstMonth,
167− const InfographicColorTheme &secondColor,
168− const QVariantList &secondMonth, InfographicData *parent) :
169− q_ptr(parent), m_label(label), m_firstColor(this), m_firstMonth(
170− firstMonth), m_secondColor(this), m_secondMonth(secondMonth)
171−{
172− m_length = calculateLength();
173− m_firstColor = firstColor;
174− m_secondColor = secondColor;
175−}
176−
177−InfographicDataPrivate::~InfographicDataPrivate()
178−{
179−}
180−
181−int InfographicDataPrivate::calculateLength()
182−{
183− int day(m_firstMonth.size());
184− auto it = m_firstMonth.end(), end = m_firstMonth.begin();
185− while (it != end)
186− {
187− --it;
188− --day;
189− if (!it->isNull())
190− {
191− return day;
192− }
193− }
194−
195− return -1;
196−}
197−
198−InfographicData::InfographicData(QObject *parent) :
199− QObject(parent), d_ptr(new InfographicDataPrivate(this))
200−{
201−}
202−
203−InfographicData::InfographicData(const QString &label,
204− const InfographicColorTheme &firstColor, const QVariantList &firstMonth,
205− const InfographicColorTheme &secondColor,
206− const QVariantList &secondMonth, QObject* parent) :
207− QObject(parent), d_ptr(
208− new InfographicDataPrivate(label, firstColor, firstMonth,
209− secondColor, secondMonth, this))
210−{
211−}
212−
213−InfographicData::~InfographicData()
214−{
215− delete d_ptr;
216−}
217−
218−const QString & InfographicData::label() const
219−{
220− return d_ptr->m_label;
221−}
222−
223−const InfographicColorTheme & InfographicData::firstColor() const
224−{
225− return d_ptr->m_firstColor;
226−}
227−
228−const QVariantList & InfographicData::firstMonth() const
229−{
230− return d_ptr->m_firstMonth;
231−}
232−
233−const InfographicColorTheme & InfographicData::secondColor() const
234−{
235− return d_ptr->m_secondColor;
236−}
237−
238−const QVariantList & InfographicData::secondMonth() const
239−{
240− return d_ptr->m_secondMonth;
241−}
242−
243−int InfographicData::length() const
244−{
245− return d_ptr->m_length;
246−}
247−
248−InfographicModelPrivate::InfographicModelPrivate(InfographicModel *parent) :
249− q_ptr(parent), m_currentDay(0)
250−{
251− m_fakeData.insert("", InfographicDataPtr(new InfographicData(this)));
252−}
253−
254−InfographicModelPrivate::~InfographicModelPrivate()
255−{
256−}
257−
258−void InfographicModelPrivate::setUsername(const QString &username)
259−{
260− if(m_username == username) {
261− return;
262− }
263−
264− m_username = username;
265−
266− m_dataIndex = m_fakeData.constFind(m_username);
267− if (m_dataIndex == m_fakeData.end())
268− {
269− m_dataIndex = m_fakeData.constFind("");
270− }
271−
272− loadFakeData();
273−
274− q_ptr->usernameChanged(m_username);
275−}
276−
277−void InfographicModelPrivate::loadFakeData()
278−{
279− m_newData = *m_dataIndex;
280−
281− bool oldLabelEmpty = m_label.isEmpty();
282− bool newLabelEmpty = m_newData->label().isEmpty();
283−
284− if (oldLabelEmpty && !newLabelEmpty)
285− {
286− q_ptr->dataAboutToAppear();
287− finishSetFakeData();
288− } else if (!oldLabelEmpty && newLabelEmpty)
289− {
290− q_ptr->dataAboutToDisappear();
291− } else if (!oldLabelEmpty && !newLabelEmpty)
292− {
293− q_ptr->dataAboutToChange();
294− }
295− // we emit no signal if the data has stayed empty
296−}
297−
298−void InfographicModelPrivate::finishSetFakeData()
299−{
300− bool oldLabelEmpty = m_label.isEmpty();
301− bool newLabelEmpty = m_newData->label().isEmpty();
302−
303− m_label = m_newData->label();
304− m_firstColor = m_newData->firstColor();
305− m_firstMonth.setVariantList(m_newData->firstMonth());
306− m_secondColor = m_newData->secondColor();
307− m_secondMonth.setVariantList(m_newData->secondMonth());
308−
309− bool currentDayChanged = m_currentDay != m_newData->length();
310− m_currentDay = m_newData->length();
311−
312− q_ptr->labelChanged(m_label);
313− if (currentDayChanged)
314− {
315− q_ptr->currentDayChanged(m_currentDay);
316− }
317−
318− if (oldLabelEmpty && !newLabelEmpty)
319− {
320− q_ptr->dataAppeared();
321− } else if (!oldLabelEmpty && newLabelEmpty)
322− {
323− q_ptr->dataDisappeared();
324− } else if (!oldLabelEmpty && !newLabelEmpty)
325− {
326− q_ptr->dataChanged();
327− }
328− // we emit no signal if the data has stayed empty
329−}
330−
331−void InfographicModelPrivate::nextFakeData()
332−{
333− ++m_dataIndex;
334− if (m_dataIndex == m_fakeData.end() || m_dataIndex.key() != m_username)
335− {
336− m_dataIndex = m_fakeData.constFind(m_username);
337− }
338−
339− loadFakeData();
340−}
341−
342−InfographicModel::InfographicModel(QObject *parent) :
343− QObject(parent), d_ptr(new InfographicModelPrivate(this))
344−{
345− d_ptr->generateFakeData();
346− setUsername("");
347−
348− connect(this, SIGNAL(nextDataSource()), this, SLOT(nextDataSourceSlot()),
349− Qt::QueuedConnection);
350− connect(this, SIGNAL(readyForDataChange()), this,
351− SLOT(readyForDataChangeSlot()), Qt::QueuedConnection);
352−}
353−
354−InfographicModel::~InfographicModel()
355−{
356− delete d_ptr;
357−}
358−
359−QString InfographicModel::label() const
360−{
361− return d_ptr->m_label;
362−}
363−
364−QString InfographicModel::username() const
365−{
366− return d_ptr->m_username;
367−}
368−
369−void InfographicModel::setUsername(const QString &username)
370−{
371− d_ptr->setUsername(username);
372−}
373−
374−InfographicColorTheme * InfographicModel::firstColor() const
375−{
376− return &d_ptr->m_firstColor;
377−}
378−
379−InfographicColorTheme * InfographicModel::secondColor() const
380−{
381− return &d_ptr->m_secondColor;
382−}
383−
384−QAbstractItemModel * InfographicModel::firstMonth() const
385−{
386− return &d_ptr->m_firstMonth;
387−}
388−
389−QAbstractItemModel * InfographicModel::secondMonth() const
390−{
391− return &d_ptr->m_secondMonth;
392−}
393−
394−int InfographicModel::currentDay() const
395−{
396− return d_ptr->m_currentDay;
397−}
398−
399−void InfographicModel::nextDataSourceSlot()
400−{
401− d_ptr->nextFakeData();
402−}
403−
404−void InfographicModel::readyForDataChangeSlot()
405−{
406− d_ptr->finishSetFakeData();
407−}
408−
409−/**
410− * Factory methods
411− */
412−
413−InfographicModel * InfographicModel::getInstance()
414−{
415− return new InfographicModel();
416−}
tests/mocks/LightDM/InfographicModelPrivate.hdeleted−99
@@ -1,99 +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− * Author: Pete Woods <pete.woods@canonical.com>
17− */
18−
19−#ifndef INFOGRAPHICMODEL_PRIVATE_H
20−#define INFOGRAPHICMODEL_PRIVATE_H
21−
22−#include <QtCore/QSharedPointer>
23−
24−#include "InfographicModel.h"
25−#include "plugins/Utils/qvariantlistmodel.h"
26−
27−namespace QLightDM
28−{
29−class InfographicDataPrivate;
30−
31−class Q_DECL_EXPORT InfographicData: public QObject
32−{
33−public:
34− explicit InfographicData(QObject *parent);
35−
36− InfographicData(const QString &label,
37− const InfographicColorTheme &firstColor,
38− const QVariantList &firstMonth,
39− const InfographicColorTheme &secondColor,
40− const QVariantList &secondMonth, QObject* parent);
41−
42− ~InfographicData();
43−
44−protected:
45− InfographicDataPrivate * const d_ptr;
46−
47−public:
48− const QString & label() const;
49− const InfographicColorTheme & firstColor() const;
50− const QVariantList & firstMonth() const;
51− const InfographicColorTheme & secondColor() const;
52− const QVariantList & secondMonth() const;
53− int length() const;
54−
55−private:
56− Q_DECLARE_PRIVATE(InfographicData)
57−};
58−
59−class InfographicModelPrivate: QObject
60−{
61−
62−public:
63− explicit InfographicModelPrivate(InfographicModel *parent);
64−
65− ~InfographicModelPrivate();
66−
67−public:
68− typedef QSharedPointer<InfographicData> InfographicDataPtr;
69− typedef QMultiMap<QString, InfographicDataPtr> FakeDataMap;
70−
71− InfographicModel * const q_ptr;
72− QString m_label;
73− InfographicColorTheme m_firstColor;
74− QVariantListModel m_firstMonth;
75− InfographicColorTheme m_secondColor;
76− QVariantListModel m_secondMonth;
77− int m_currentDay;
78− QString m_username;
79− FakeDataMap::const_iterator m_dataIndex;
80− InfographicDataPtr m_newData;
81− FakeDataMap m_fakeData;
82−
83− void setUsername(const QString &username);
84−
85−protected:
86− void nextFakeData();
87−
88− void generateFakeData();
89−
90− void loadFakeData();
91−
92− void finishSetFakeData();
93−
94−private:
95− Q_DECLARE_PUBLIC(InfographicModel)
96−};
97−}
98−
99−#endif // INFOGRAPHICMODEL_PRIVATE_H
tests/mocks/LightDM/demo/CMakeLists.txt+11−2
@@ -1,13 +1,22 @@
1+include(FindPkgConfig)
2+pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
3+
1set(LibLightDM_SOURCES
4set(LibLightDM_SOURCES
2 ../Greeter.cpp
5 ../Greeter.cpp
3 ../UsersModel.cpp
6 ../UsersModel.cpp
4− ../InfographicModel.cpp
5 GreeterPrivate.cpp
7 GreeterPrivate.cpp
6 UsersModelPrivate.cpp
8 UsersModelPrivate.cpp
7− InfographicModelPrivate.cpp
8 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
9 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
9 )
10 )
10
11
11add_library(MockLightDM-demo STATIC ${LibLightDM_SOURCES})
12add_library(MockLightDM-demo STATIC ${LibLightDM_SOURCES})
12
13
14+include_directories(
15+ ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
16+)
17+
18+target_link_libraries(MockLightDM-demo
19+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
20+ )
21+
13qt5_use_modules(MockLightDM-demo Gui)
22qt5_use_modules(MockLightDM-demo Gui)
tests/mocks/LightDM/demo/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
26{
26{
27 entries =
27 entries =
28 {
28 {
29− { "guest", "Guest", 0, 0, false, false, 0, 0 },
29+ { "single", "Guest", 0, 0, false, false, 0, 0 },
30 };
30 };
31}
31}
32
32
tests/mocks/LightDM/full/CMakeLists.txt+1−3
@@ -1,10 +1,8 @@
1set(LibLightDM_SOURCES
1set(LibLightDM_SOURCES
2 ../Greeter.cpp
2 ../Greeter.cpp
3 ../UsersModel.cpp
3 ../UsersModel.cpp
4− ../InfographicModel.cpp
5 GreeterPrivate.cpp
4 GreeterPrivate.cpp
6 UsersModelPrivate.cpp
5 UsersModelPrivate.cpp
7− InfographicModelPrivate.cpp
8 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
6 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
9 )
7 )
10
8
@@ -16,5 +14,5 @@ set_target_properties(MockLightDM-full PROPERTIES
16 OUTPUT_NAME lightdm-qt5-2)
14 OUTPUT_NAME lightdm-qt5-2)
17
15
18install(TARGETS MockLightDM-full
16install(TARGETS MockLightDM-full
19− DESTINATION ${SHELL_APP_DIR}/plugins/mocks/LightDM/full
17+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM/full
20 )
18 )
tests/mocks/LightDM/single-passphrase/CMakeLists.txt+1−3
@@ -1,10 +1,8 @@
1set(LibLightDM_SOURCES
1set(LibLightDM_SOURCES
2 ../Greeter.cpp
2 ../Greeter.cpp
3 ../UsersModel.cpp
3 ../UsersModel.cpp
4− ../InfographicModel.cpp
5 GreeterPrivate.cpp
4 GreeterPrivate.cpp
6 UsersModelPrivate.cpp
5 UsersModelPrivate.cpp
7− InfographicModelPrivate.cpp
8 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
6 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
9 )
7 )
10
8
@@ -17,5 +15,5 @@ set_target_properties(MockLightDM-single-passphrase PROPERTIES
17 OUTPUT_NAME lightdm-qt5-2)
15 OUTPUT_NAME lightdm-qt5-2)
18
16
19install(TARGETS MockLightDM-single-passphrase
17install(TARGETS MockLightDM-single-passphrase
20− DESTINATION ${SHELL_APP_DIR}/plugins/mocks/LightDM/single-passphrase
18+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM/single-passphrase
21 )
19 )
tests/mocks/LightDM/single-passphrase/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
26{
26{
27 entries =
27 entries =
28 {
28 {
29− { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 },
29+ { "single", "Has Passphrase", 0, 0, false, false, 0, 0 },
30 };
30 };
31}
31}
32
32
tests/mocks/LightDM/single-pin/CMakeLists.txt+1−3
@@ -1,10 +1,8 @@
1set(LibLightDM_SOURCES
1set(LibLightDM_SOURCES
2 ../Greeter.cpp
2 ../Greeter.cpp
3 ../UsersModel.cpp
3 ../UsersModel.cpp
4− ../InfographicModel.cpp
5 GreeterPrivate.cpp
4 GreeterPrivate.cpp
6 UsersModelPrivate.cpp
5 UsersModelPrivate.cpp
7− InfographicModelPrivate.cpp
8 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
6 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
9 )
7 )
10
8
@@ -17,5 +15,5 @@ set_target_properties(MockLightDM-single-pin PROPERTIES
17 OUTPUT_NAME lightdm-qt5-2)
15 OUTPUT_NAME lightdm-qt5-2)
18
16
19install(TARGETS MockLightDM-single-pin
17install(TARGETS MockLightDM-single-pin
20− DESTINATION ${SHELL_APP_DIR}/plugins/mocks/LightDM/single-pin
18+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM/single-pin
21 )
19 )
tests/mocks/LightDM/single-pin/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
26{
26{
27 entries =
27 entries =
28 {
28 {
29− { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 },
29+ { "single", "Has PIN", 0, 0, false, false, 0, 0 },
30 };
30 };
31}
31}
32
32
tests/mocks/LightDM/single/CMakeLists.txt+1−3
@@ -1,9 +1,7 @@
1set(LibLightDM_SOURCES
1set(LibLightDM_SOURCES
2 ../Greeter.cpp
2 ../Greeter.cpp
3− ../InfographicModel.cpp
4 ../UsersModel.cpp
3 ../UsersModel.cpp
5 GreeterPrivate.cpp
4 GreeterPrivate.cpp
6− InfographicModelPrivate.cpp
7 UsersModelPrivate.cpp
5 UsersModelPrivate.cpp
8 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
6 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
9 )
7 )
@@ -16,5 +14,5 @@ set_target_properties(MockLightDM-single PROPERTIES
16 OUTPUT_NAME lightdm-qt5-2)
14 OUTPUT_NAME lightdm-qt5-2)
17
15
18install(TARGETS MockLightDM-single
16install(TARGETS MockLightDM-single
19− DESTINATION ${SHELL_APP_DIR}/plugins/mocks/LightDM/single
17+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/LightDM/single
20 )
18 )
tests/mocks/LightDM/single/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
26{
26{
27 entries =
27 entries =
28 {
28 {
29− { "one", "Only User", 0, 0, false, false, 0, 0 },
29+ { "single", "Single User", 0, 0, false, false, 0, 0 },
30 };
30 };
31}
31}
32
32
tests/mocks/Ubuntu/Application/CMakeLists.txt+2−2
@@ -27,9 +27,9 @@ add_custom_target(InputFilterAreaQmlFile ALL
27)
27)
28
28
29install(TARGETS FakeUbuntuApplicationQml
29install(TARGETS FakeUbuntuApplicationQml
30− DESTINATION ${SHELL_APP_DIR}/plugins/mocks/Ubuntu/Application
30+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/Ubuntu/Application
31 )
31 )
32
32
33install(FILES qmldir InputFilterArea.qml
33install(FILES qmldir InputFilterArea.qml
34− DESTINATION ${SHELL_APP_DIR}/plugins/mocks/Ubuntu/Application
34+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/Ubuntu/Application
35 )
35 )
tests/mocks/Ubuntu/CMakeLists.txt+1
@@ -1 +1,2 @@
1add_subdirectory(Application)
1add_subdirectory(Application)
2+add_subdirectory(ChewieUI)
tests/qmltests/plugins/Ubuntu/ChewieUI/CMakeLists.txt → tests/mocks/Ubuntu/ChewieUI/CMakeLists.txtrenamed

The content is the same.

tests/qmltests/plugins/Ubuntu/ChewieUI/fake_chewie_plugin.cpp → tests/mocks/Ubuntu/ChewieUI/fake_chewie_plugin.cpprenamed

The content is the same.

tests/qmltests/plugins/Ubuntu/ChewieUI/fake_chewie_plugin.h → tests/mocks/Ubuntu/ChewieUI/fake_chewie_plugin.hrenamed

The content is the same.

tests/qmltests/plugins/Ubuntu/ChewieUI/fake_pluginmodel.cpp → tests/mocks/Ubuntu/ChewieUI/fake_pluginmodel.cpprenamed

The content is the same.

tests/qmltests/plugins/Ubuntu/ChewieUI/fake_pluginmodel.h → tests/mocks/Ubuntu/ChewieUI/fake_pluginmodel.hrenamed

The content is the same.

tests/qmltests/plugins/Ubuntu/ChewieUI/qmldir → tests/mocks/Ubuntu/ChewieUI/qmldirrenamed

The content is the same.

tests/qmltests/plugins/Unity/CMakeLists.txt → tests/mocks/Unity/CMakeLists.txtrenamed

The content is the same.

tests/qmltests/plugins/Unity/Notifications/notification.js → tests/mocks/Unity/Notifications/notification.jsrenamed

The content is the same.

tests/qmltests/plugins/Unity/Notifications/qmldir → tests/mocks/Unity/Notifications/qmldirrenamed

The content is the same.

tests/qmltests/plugins/Unity/fake_launchermodel.cpp → tests/mocks/Unity/fake_launchermodel.cpprenamed

The content is the same.

tests/qmltests/plugins/Unity/fake_launchermodel.h → tests/mocks/Unity/fake_launchermodel.hrenamed

The content is the same.

tests/qmltests/plugins/Unity/fake_scope.cpp → tests/mocks/Unity/fake_scope.cpprenamed

The content is the same.

tests/qmltests/plugins/Unity/fake_scope.h → tests/mocks/Unity/fake_scope.hrenamed

The content is the same.

tests/qmltests/plugins/Unity/fake_scopes.cpp → tests/mocks/Unity/fake_scopes.cpprenamed

The content is the same.

tests/qmltests/plugins/Unity/fake_scopes.h → tests/mocks/Unity/fake_scopes.hrenamed

The content is the same.

tests/qmltests/plugins/Unity/fake_unity_plugin.cpp → tests/mocks/Unity/fake_unity_plugin.cpprenamed

The content is the same.

tests/qmltests/plugins/Unity/fake_unity_plugin.h → tests/mocks/Unity/fake_unity_plugin.hrenamed

The content is the same.

tests/qmltests/plugins/Unity/qmldir → tests/mocks/Unity/qmldirrenamed

The content is the same.

tests/mocks/libusermetrics/CMakeLists.txtnew file+17
@@ -0,0 +1,17 @@
1+set(mock_SOURCES
2+ ColorTheme.cpp
3+ UserMetrics.cpp
4+ ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
5+ )
6+
7+add_library(MockUserMetrics SHARED ${mock_SOURCES})
8+
9+qt5_use_modules(MockUserMetrics Gui)
10+
11+set_target_properties(MockUserMetrics PROPERTIES
12+ OUTPUT_NAME usermetricsoutput
13+ VERSION 1)
14+
15+install(TARGETS MockUserMetrics
16+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/mocks/libusermetrics
17+ )
tests/mocks/libusermetrics/ColorTheme.cppnew file+128
@@ -0,0 +1,128 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Pete Woods <pete.woods@canonical.com>
17+ */
18+
19+#include "ColorTheme.h"
20+
21+#include <QtCore/QDir>
22+#include <QtCore/QString>
23+#include <QtGui/QIcon>
24+#include <QMultiMap>
25+
26+using namespace UserMetricsOutput;
27+
28+namespace UserMetricsOutput
29+{
30+
31+class ColorThemePrivate: QObject
32+{
33+public:
34+ explicit ColorThemePrivate(ColorTheme *parent = 0);
35+
36+ ColorThemePrivate(const QColor &start, const QColor &main,
37+ const QColor &end, ColorTheme *parent = 0);
38+
39+ ~ColorThemePrivate();
40+
41+ ColorTheme * const q_ptr;
42+
43+ QColor m_start;
44+
45+ QColor m_main;
46+
47+ QColor m_end;
48+
49+protected:
50+ int calculateLength();
51+
52+private:
53+ Q_DECLARE_PUBLIC(ColorTheme)
54+};
55+
56+}
57+
58+ColorThemePrivate::ColorThemePrivate(
59+ ColorTheme *parent) :
60+ q_ptr(parent)
61+{
62+}
63+
64+ColorThemePrivate::ColorThemePrivate(const QColor &start,
65+ const QColor &main, const QColor &end, ColorTheme *parent) :
66+ q_ptr(parent), m_start(start), m_main(main), m_end(end)
67+{
68+}
69+
70+ColorThemePrivate::~ColorThemePrivate()
71+{
72+}
73+
74+ColorTheme::ColorTheme(QObject *parent) :
75+ QObject(parent), d_ptr(new ColorThemePrivate(this))
76+{
77+}
78+
79+ColorTheme::ColorTheme(QColor &first, QColor &main,
80+ QColor &end, QObject *parent) :
81+ QObject(parent), d_ptr(
82+ new ColorThemePrivate(first, main, end, this))
83+{
84+
85+}
86+
87+ColorTheme & ColorTheme::operator=(
88+ const ColorTheme & other)
89+{
90+ if (d_ptr->m_start != other.d_ptr->m_start)
91+ {
92+ d_ptr->m_start = other.d_ptr->m_start;
93+ startChanged(d_ptr->m_start);
94+ }
95+ if (d_ptr->m_main != other.d_ptr->m_main)
96+ {
97+ d_ptr->m_main = other.d_ptr->m_main;
98+ mainChanged(d_ptr->m_main);
99+ }
100+
101+ if (d_ptr->m_end != other.d_ptr->m_end)
102+ {
103+ d_ptr->m_end = other.d_ptr->m_end;
104+ endChanged(d_ptr->m_end);
105+ }
106+
107+ return *this;
108+}
109+
110+ColorTheme::~ColorTheme()
111+{
112+ delete d_ptr;
113+}
114+
115+QColor ColorTheme::start() const
116+{
117+ return d_ptr->m_start;
118+}
119+
120+QColor ColorTheme::main() const
121+{
122+ return d_ptr->m_main;
123+}
124+
125+QColor ColorTheme::end() const
126+{
127+ return d_ptr->m_end;
128+}
tests/mocks/libusermetrics/ColorTheme.hnew file+68
@@ -0,0 +1,68 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Pete Woods <pete.woods@canonical.com>
17+ */
18+
19+#ifndef UNITY_MOCK_COLORTHEME_H
20+#define UNITY_MOCK_COLORTHEME_H
21+
22+#include <QtGui/QColor>
23+
24+namespace UserMetricsOutput
25+{
26+class ColorThemePrivate;
27+
28+class Q_DECL_EXPORT ColorTheme: public QObject
29+{
30+Q_OBJECT
31+
32+Q_PROPERTY(QColor start READ start NOTIFY startChanged FINAL)
33+Q_PROPERTY(QColor main READ main NOTIFY mainChanged FINAL)
34+Q_PROPERTY(QColor end READ end NOTIFY endChanged FINAL)
35+
36+public:
37+ explicit ColorTheme(QObject *parent = 0);
38+
39+ explicit ColorTheme(QColor &first, QColor &main, QColor &end,
40+ QObject *parent = 0);
41+
42+ ColorTheme & operator=(const ColorTheme & other);
43+
44+ ~ColorTheme();
45+
46+ QColor start() const;
47+
48+ QColor main() const;
49+
50+ QColor end() const;
51+
52+Q_SIGNALS:
53+ void startChanged(const QColor &color);
54+
55+ void mainChanged(const QColor &color);
56+
57+ void endChanged(const QColor &color);
58+
59+protected:
60+ ColorThemePrivate * const d_ptr;
61+
62+ Q_DECLARE_PRIVATE(ColorTheme)
63+
64+};
65+
66+}
67+
68+#endif // UNITY_MOCK_COLORTHEME_H
tests/mocks/libusermetrics/UserMetrics.cppnew file+465
@@ -0,0 +1,465 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Pete Woods <pete.woods@canonical.com>
17+ */
18+
19+#include "UserMetrics.h"
20+#include "plugins/Utils/qvariantlistmodel.h"
21+
22+#include <QtCore/QDir>
23+#include <QtCore/QString>
24+#include <QtGui/QIcon>
25+#include <QMultiMap>
26+
27+using namespace UserMetricsOutput;
28+
29+namespace UserMetricsOutput
30+{
31+class UserMetricsDataPrivate;
32+class UserMetricsPrivate;
33+
34+class Q_DECL_EXPORT UserMetricsData: public QObject
35+{
36+public:
37+ explicit UserMetricsData(QObject *parent);
38+
39+ UserMetricsData(const QString &label,
40+ const ColorTheme &firstColor,
41+ const QVariantList &firstMonth,
42+ const ColorTheme &secondColor,
43+ const QVariantList &secondMonth, QObject* parent);
44+
45+ ~UserMetricsData();
46+
47+protected:
48+ UserMetricsDataPrivate * const d_ptr;
49+
50+public:
51+ const QString & label() const;
52+ const ColorTheme & firstColor() const;
53+ const QVariantList & firstMonth() const;
54+ const ColorTheme & secondColor() const;
55+ const QVariantList & secondMonth() const;
56+ int length() const;
57+
58+private:
59+ Q_DECLARE_PRIVATE(UserMetricsData)
60+};
61+
62+class UserMetricsPrivate: QObject
63+{
64+public:
65+ explicit UserMetricsPrivate(UserMetrics *parent);
66+
67+ ~UserMetricsPrivate();
68+
69+public:
70+ typedef QSharedPointer<UserMetricsData> UserMetricsDataPtr;
71+ typedef QMultiMap<QString, UserMetricsDataPtr> FakeDataMap;
72+
73+ UserMetrics * const q_ptr;
74+ QString m_label;
75+ ColorTheme m_firstColor;
76+ QVariantListModel m_firstMonth;
77+ ColorTheme m_secondColor;
78+ QVariantListModel m_secondMonth;
79+ int m_currentDay;
80+ QString m_username;
81+ FakeDataMap::const_iterator m_dataIndex;
82+ UserMetricsDataPtr m_newData;
83+ FakeDataMap m_fakeData;
84+
85+ void setUsername(const QString &username);
86+
87+protected:
88+ void nextFakeData();
89+
90+ void generateFakeData();
91+
92+ void loadFakeData();
93+
94+ void finishSetFakeData();
95+
96+private:
97+ Q_DECLARE_PUBLIC(UserMetrics)
98+};
99+
100+class UserMetricsDataPrivate: QObject
101+{
102+public:
103+ explicit UserMetricsDataPrivate(UserMetricsData *parent);
104+
105+ UserMetricsDataPrivate(const QString &label,
106+ const ColorTheme &firstColor,
107+ const QVariantList &firstMonth,
108+ const ColorTheme &secondColor,
109+ const QVariantList &secondMonth, UserMetricsData *parent);
110+
111+ ~UserMetricsDataPrivate();
112+
113+ UserMetricsData * const q_ptr;
114+ QString m_label;
115+ ColorTheme m_firstColor;
116+ QVariantList m_firstMonth;
117+ ColorTheme m_secondColor;
118+ QVariantList m_secondMonth;
119+ int m_length;
120+
121+protected:
122+ int calculateLength();
123+
124+private:
125+ Q_DECLARE_PUBLIC(UserMetricsData)
126+};
127+
128+}
129+
130+UserMetricsDataPrivate::UserMetricsDataPrivate(UserMetricsData *parent) :
131+ q_ptr(parent), m_firstColor(this), m_secondColor(this)
132+{
133+ m_length = calculateLength();
134+}
135+
136+UserMetricsDataPrivate::UserMetricsDataPrivate(const QString &label,
137+ const ColorTheme &firstColor, const QVariantList &firstMonth,
138+ const ColorTheme &secondColor,
139+ const QVariantList &secondMonth, UserMetricsData *parent) :
140+ q_ptr(parent), m_label(label), m_firstColor(this), m_firstMonth(
141+ firstMonth), m_secondColor(this), m_secondMonth(secondMonth)
142+{
143+ m_length = calculateLength();
144+ m_firstColor = firstColor;
145+ m_secondColor = secondColor;
146+}
147+
148+UserMetricsDataPrivate::~UserMetricsDataPrivate()
149+{
150+}
151+
152+int UserMetricsDataPrivate::calculateLength()
153+{
154+ int day(m_firstMonth.size());
155+ auto it = m_firstMonth.end(), end = m_firstMonth.begin();
156+ while (it != end)
157+ {
158+ --it;
159+ --day;
160+ if (!it->isNull())
161+ {
162+ return day;
163+ }
164+ }
165+
166+ return -1;
167+}
168+
169+UserMetricsData::UserMetricsData(QObject *parent) :
170+ QObject(parent), d_ptr(new UserMetricsDataPrivate(this))
171+{
172+}
173+
174+UserMetricsData::UserMetricsData(const QString &label,
175+ const ColorTheme &firstColor, const QVariantList &firstMonth,
176+ const ColorTheme &secondColor,
177+ const QVariantList &secondMonth, QObject* parent) :
178+ QObject(parent), d_ptr(
179+ new UserMetricsDataPrivate(label, firstColor, firstMonth,
180+ secondColor, secondMonth, this))
181+{
182+}
183+
184+UserMetricsData::~UserMetricsData()
185+{
186+ delete d_ptr;
187+}
188+
189+const QString & UserMetricsData::label() const
190+{
191+ return d_ptr->m_label;
192+}
193+
194+const ColorTheme & UserMetricsData::firstColor() const
195+{
196+ return d_ptr->m_firstColor;
197+}
198+
199+const QVariantList & UserMetricsData::firstMonth() const
200+{
201+ return d_ptr->m_firstMonth;
202+}
203+
204+const ColorTheme & UserMetricsData::secondColor() const
205+{
206+ return d_ptr->m_secondColor;
207+}
208+
209+const QVariantList & UserMetricsData::secondMonth() const
210+{
211+ return d_ptr->m_secondMonth;
212+}
213+
214+int UserMetricsData::length() const
215+{
216+ return d_ptr->m_length;
217+}
218+
219+UserMetricsPrivate::UserMetricsPrivate(UserMetrics *parent) :
220+ q_ptr(parent), m_firstColor(this), m_secondColor(this)
221+{
222+ m_fakeData.insert("", UserMetricsDataPtr(new UserMetricsData(this)));
223+}
224+
225+UserMetricsPrivate::~UserMetricsPrivate()
226+{
227+}
228+
229+void UserMetricsPrivate::setUsername(const QString &username)
230+{
231+ if (m_username == username) {
232+ return;
233+ }
234+
235+ m_username = username;
236+
237+ m_dataIndex = m_fakeData.constFind(m_username);
238+ if (m_dataIndex == m_fakeData.end())
239+ {
240+ m_dataIndex = m_fakeData.constFind("");
241+ }
242+
243+ loadFakeData();
244+
245+ q_ptr->usernameChanged(m_username);
246+}
247+
248+void UserMetricsPrivate::generateFakeData()
249+{
250+ std::default_random_engine generator;
251+ std::normal_distribution<qreal> distribution(0.5, 0.2);
252+ auto rand = std::bind(distribution, generator);
253+
254+ QVector<QColor> colours;
255+ colours.push_back(QColor::fromRgbF(0.3, 0.27, 0.32));
256+ colours.push_back(QColor::fromRgbF(0.83, 0.49, 0.58));
257+ colours.push_back(QColor::fromRgbF(0.63, 0.51, 0.59));
258+
259+ colours.push_back(QColor::fromRgbF(0.28, 0.26, 0.4));
260+ colours.push_back(QColor::fromRgbF(0.47, 0.38, 0.56));
261+ colours.push_back(QColor::fromRgbF(0.69, 0.65, 0.78));
262+
263+ colours.push_back(QColor::fromRgbF(0.32, 0.21, 0.16));
264+ colours.push_back(QColor::fromRgbF(0.55, 0.45, 0.32));
265+ colours.push_back(QColor::fromRgbF(0.85, 0.74, 0.53));
266+
267+ colours.push_back(QColor::fromRgbF(0.25, 0.31, 0.19));
268+ colours.push_back(QColor::fromRgbF(0.63, 0.53, 0.3));
269+ colours.push_back(QColor::fromRgbF(0.89, 0.56, 0.31));
270+
271+ ColorTheme first(colours[0], colours[1], colours[2]);
272+ ColorTheme second(colours[3], colours[4], colours[5]);
273+ ColorTheme eighth(colours[6], colours[7], colours[8]);
274+ ColorTheme ninth(colours[9], colours[10], colours[11]);
275+
276+ {
277+ QVariantList firstMonth;
278+ while (firstMonth.size() < 17)
279+ firstMonth.push_back(QVariant(rand()));
280+ while (firstMonth.size() < 31)
281+ firstMonth.push_back(QVariant());
282+ QVariantList secondMonth;
283+ while (secondMonth.size() < 31)
284+ secondMonth.push_back(QVariant(rand()));
285+ QSharedPointer<UserMetricsData> data(
286+ new UserMetricsData("<b>52km</b> travelled", first, firstMonth,
287+ ninth, secondMonth, this));
288+ m_fakeData.insert("single", data);
289+ }
290+
291+ {
292+ QVariantList firstMonth;
293+ while (firstMonth.size() < 17)
294+ firstMonth.push_back(QVariant(rand()));
295+ while (firstMonth.size() < 31)
296+ firstMonth.push_back(QVariant());
297+ QVariantList secondMonth;
298+ while (secondMonth.size() < 31)
299+ secondMonth.push_back(QVariant(rand()));
300+ QSharedPointer<UserMetricsData> data(
301+ new UserMetricsData("<b>33</b> messages today", second,
302+ firstMonth, eighth, secondMonth, this));
303+ m_fakeData.insert("single", data);
304+ }
305+
306+ {
307+ QVariantList firstMonth;
308+ while (firstMonth.size() < 17)
309+ firstMonth.push_back(QVariant(rand()));
310+ while (firstMonth.size() < 31)
311+ firstMonth.push_back(QVariant());
312+ QVariantList secondMonth;
313+ while (secondMonth.size() < 31)
314+ secondMonth.push_back(QVariant(rand()));
315+ QSharedPointer<UserMetricsData> data(
316+ new UserMetricsData("<b>19</b> minutes talk time", eighth,
317+ firstMonth, second, secondMonth, this));
318+ m_fakeData.insert("single", data);
319+ // Also use same data for some tablet users
320+ m_fakeData.insert("has-password", data);
321+ m_fakeData.insert("no-password", data);
322+ m_fakeData.insert("empty-name", data);
323+ }
324+}
325+
326+void UserMetricsPrivate::loadFakeData()
327+{
328+ m_newData = *m_dataIndex;
329+
330+ bool oldLabelEmpty = m_label.isEmpty();
331+ bool newLabelEmpty = m_newData->label().isEmpty();
332+
333+ if (oldLabelEmpty && !newLabelEmpty)
334+ {
335+ q_ptr->dataAboutToAppear();
336+ finishSetFakeData();
337+ } else if (!oldLabelEmpty && newLabelEmpty)
338+ {
339+ q_ptr->dataAboutToDisappear();
340+ } else if (!oldLabelEmpty && !newLabelEmpty)
341+ {
342+ q_ptr->dataAboutToChange();
343+ }
344+ // we emit no signal if the data has stayed empty
345+}
346+
347+void UserMetricsPrivate::finishSetFakeData()
348+{
349+ bool oldLabelEmpty = m_label.isEmpty();
350+ bool newLabelEmpty = m_newData->label().isEmpty();
351+
352+ m_label = m_newData->label();
353+ m_firstColor = m_newData->firstColor();
354+ m_firstMonth.setVariantList(m_newData->firstMonth());
355+ m_secondColor = m_newData->secondColor();
356+ m_secondMonth.setVariantList(m_newData->secondMonth());
357+
358+ bool currentDayChanged = m_currentDay != m_newData->length();
359+ m_currentDay = m_newData->length();
360+
361+ q_ptr->labelChanged(m_label);
362+ if (currentDayChanged)
363+ {
364+ q_ptr->currentDayChanged(m_currentDay);
365+ }
366+
367+ if (oldLabelEmpty && !newLabelEmpty)
368+ {
369+ q_ptr->dataAppeared();
370+ } else if (!oldLabelEmpty && newLabelEmpty)
371+ {
372+ q_ptr->dataDisappeared();
373+ } else if (!oldLabelEmpty && !newLabelEmpty)
374+ {
375+ q_ptr->dataChanged();
376+ }
377+ // we emit no signal if the data has stayed empty
378+}
379+
380+void UserMetricsPrivate::nextFakeData()
381+{
382+ ++m_dataIndex;
383+ if (m_dataIndex == m_fakeData.end() || m_dataIndex.key() != m_username)
384+ {
385+ m_dataIndex = m_fakeData.constFind(m_username);
386+ }
387+
388+ loadFakeData();
389+}
390+
391+UserMetrics::UserMetrics(QObject *parent) :
392+ QObject(parent), d_ptr(new UserMetricsPrivate(this))
393+{
394+ d_ptr->generateFakeData();
395+ setUsername("");
396+
397+ connect(this, SIGNAL(nextDataSource()), this, SLOT(nextDataSourceSlot()),
398+ Qt::QueuedConnection);
399+ connect(this, SIGNAL(readyForDataChange()), this,
400+ SLOT(readyForDataChangeSlot()), Qt::QueuedConnection);
401+}
402+
403+UserMetrics::~UserMetrics()
404+{
405+ delete d_ptr;
406+}
407+
408+QString UserMetrics::label() const
409+{
410+ return d_ptr->m_label;
411+}
412+
413+QString UserMetrics::username() const
414+{
415+ return d_ptr->m_username;
416+}
417+
418+void UserMetrics::setUsername(const QString &username)
419+{
420+ d_ptr->setUsername(username);
421+}
422+
423+ColorTheme *UserMetrics::firstColor() const
424+{
425+ return &d_ptr->m_firstColor;
426+}
427+
428+ColorTheme *UserMetrics::secondColor() const
429+{
430+ return &d_ptr->m_secondColor;
431+}
432+
433+QAbstractItemModel *UserMetrics::firstMonth() const
434+{
435+ return &d_ptr->m_firstMonth;
436+}
437+
438+QAbstractItemModel *UserMetrics::secondMonth() const
439+{
440+ return &d_ptr->m_secondMonth;
441+}
442+
443+int UserMetrics::currentDay() const
444+{
445+ return d_ptr->m_currentDay;
446+}
447+
448+void UserMetrics::nextDataSourceSlot()
449+{
450+ d_ptr->nextFakeData();
451+}
452+
453+void UserMetrics::readyForDataChangeSlot()
454+{
455+ d_ptr->finishSetFakeData();
456+}
457+
458+/**
459+ * Factory methods
460+ */
461+
462+UserMetrics * UserMetrics::getInstance()
463+{
464+ return new UserMetrics();
465+}
tests/mocks/LightDM/InfographicModel.h → tests/mocks/libusermetrics/UserMetrics.hrenamed+22−60
@@ -16,74 +16,34 @@
16 * Author: Pete Woods <pete.woods@canonical.com>
16 * Author: Pete Woods <pete.woods@canonical.com>
17 */
17 */
18
18
19−#ifndef LIGHTDM_INFOGRAPHICMODEL_H
19+#ifndef UNITY_MOCK_USERMETRICS_H
20−#define LIGHTDM_INFOGRAPHICMODEL_H
20+#define UNITY_MOCK_USERMETRICS_H
21
21
22+#include "ColorTheme.h"
23+#include <QtCore/QAbstractListModel>
22#include <QtCore/QString>
24#include <QtCore/QString>
23−#include <QtGui/qcolor.h>
25+#include <QtGui/QColor>
24−#include <QAbstractListModel>
25
26
26−namespace QLightDM
27+namespace UserMetricsOutput
27{
28{
28−class InfographicColorThemePrivate;
29+class UserMetricsPrivate;
29
30
30−class Q_DECL_EXPORT InfographicColorTheme: public QObject
31+class Q_DECL_EXPORT UserMetrics: public QObject
31−{
32−Q_OBJECT
33−
34−Q_PROPERTY(QColor start READ start NOTIFY startChanged FINAL)
35−Q_PROPERTY(QColor main READ main NOTIFY mainChanged FINAL)
36−Q_PROPERTY(QColor end READ end NOTIFY endChanged FINAL)
37−
38−public:
39− explicit InfographicColorTheme(QObject *parent = 0);
40−
41− explicit InfographicColorTheme(QColor &first, QColor &main, QColor &end,
42− QObject *parent = 0);
43−
44− InfographicColorTheme & operator=(const InfographicColorTheme & other);
45−
46− ~InfographicColorTheme();
47−
48− QColor start() const;
49−
50− QColor main() const;
51−
52− QColor end() const;
53−
54−Q_SIGNALS:
55− void startChanged(const QColor &color);
56−
57− void mainChanged(const QColor &color);
58−
59− void endChanged(const QColor &color);
60−
61−protected:
62− InfographicColorThemePrivate * const d_ptr;
63−
64− Q_DECLARE_PRIVATE(InfographicColorTheme)
65−
66−};
67−
68−class InfographicModelPrivate;
69−
70−class Q_DECL_EXPORT InfographicModel: public QObject
71{
32{
72Q_OBJECT
33Q_OBJECT
73
34
74Q_PROPERTY(QString label READ label NOTIFY labelChanged FINAL)
35Q_PROPERTY(QString label READ label NOTIFY labelChanged FINAL)
75Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged FINAL)
36Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged FINAL)
76−Q_PROPERTY(QLightDM::InfographicColorTheme* firstColor READ firstColor NOTIFY firstColorChanged FINAL)
37+Q_PROPERTY(UserMetricsOutput::ColorTheme* firstColor READ firstColor NOTIFY firstColorChanged FINAL)
77−Q_PROPERTY(QLightDM::InfographicColorTheme* secondColor READ secondColor NOTIFY secondColorChanged FINAL)
38+Q_PROPERTY(UserMetricsOutput::ColorTheme* secondColor READ secondColor NOTIFY secondColorChanged FINAL)
78Q_PROPERTY(QAbstractItemModel *firstMonth READ firstMonth NOTIFY firstMonthChanged FINAL)
39Q_PROPERTY(QAbstractItemModel *firstMonth READ firstMonth NOTIFY firstMonthChanged FINAL)
79Q_PROPERTY(QAbstractItemModel *secondMonth READ secondMonth NOTIFY secondMonthChanged FINAL)
40Q_PROPERTY(QAbstractItemModel *secondMonth READ secondMonth NOTIFY secondMonthChanged FINAL)
80Q_PROPERTY(int currentDay READ currentDay NOTIFY currentDayChanged FINAL)
41Q_PROPERTY(int currentDay READ currentDay NOTIFY currentDayChanged FINAL)
81
42
82public:
43public:
83− static InfographicModel *getInstance();
44+ static UserMetrics *getInstance();
84
45
85− explicit InfographicModel(QObject *parent = 0);
46+ ~UserMetrics();
86− ~InfographicModel();
87
47
88 QString label() const;
48 QString label() const;
89
49
@@ -91,13 +51,13 @@ public:
91
51
92 void setUsername(const QString &username);
52 void setUsername(const QString &username);
93
53
94− InfographicColorTheme * firstColor() const;
54+ ColorTheme * firstColor() const;
95
55
96 QAbstractItemModel *firstMonth() const;
56 QAbstractItemModel *firstMonth() const;
97
57
98 int currentDay() const;
58 int currentDay() const;
99
59
100− InfographicColorTheme * secondColor() const;
60+ ColorTheme * secondColor() const;
101
61
102 QAbstractItemModel *secondMonth() const;
62 QAbstractItemModel *secondMonth() const;
103
63
@@ -106,13 +66,13 @@ Q_SIGNALS:
106
66
107 void usernameChanged(const QString &username);
67 void usernameChanged(const QString &username);
108
68
109− void firstColorChanged(InfographicColorTheme *color);
69+ void firstColorChanged(ColorTheme *color);
110
70
111 void firstMonthChanged(QAbstractItemModel *firstMonth);
71 void firstMonthChanged(QAbstractItemModel *firstMonth);
112
72
113 void currentDayChanged(int length);
73 void currentDayChanged(int length);
114
74
115− void secondColorChanged(InfographicColorTheme *color);
75+ void secondColorChanged(ColorTheme *color);
116
76
117 void secondMonthChanged(QAbstractItemModel *secondMonth);
77 void secondMonthChanged(QAbstractItemModel *secondMonth);
118
78
@@ -138,13 +98,15 @@ protected Q_SLOTS:
138 void readyForDataChangeSlot();
98 void readyForDataChangeSlot();
139
99
140protected:
100protected:
141− InfographicModelPrivate * const d_ptr;
101+ UserMetricsPrivate * const d_ptr;
102+
103+ explicit UserMetrics(QObject *parent = 0);
142
104
143− Q_DISABLE_COPY(InfographicModel)
105+ Q_DISABLE_COPY(UserMetrics)
144− Q_DECLARE_PRIVATE(InfographicModel)
106+ Q_DECLARE_PRIVATE(UserMetrics)
145
107
146};
108};
147
109
148}
110}
149
111
150−#endif // LIGHTDM_INFOGRAPHICMODEL_H
112+#endif // UNITY_MOCK_USERMETRICS_H
tests/mocks/libusermetrics/libusermetricsoutput/ColorTheme.hnew file+1
@@ -0,0 +1 @@
1+../ColorTheme.h
tests/mocks/libusermetrics/libusermetricsoutput/UserMetrics.hnew file+1
@@ -0,0 +1 @@
1+../UserMetrics.h
tests/plugins/CMakeLists.txt+2
@@ -1,2 +1,4 @@
1add_subdirectory(Utils)
1add_subdirectory(Utils)
2add_subdirectory(Ubuntu)
2add_subdirectory(Ubuntu)
3+add_subdirectory(Unity)
4+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+1317
@@ -0,0 +1,1317 @@
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+ void testCrashShowHeaderWithNoHeader()
1303+ {
1304+ lvwph->setHeader(nullptr);
1305+ lvwph->showHeader();
1306+ }
1307+
1308+private:
1309+ QQuickView *view;
1310+ ListViewWithPageHeader *lvwph;
1311+ QQuickListModel *model;
1312+ QQmlComponent *otherDelegate;
1313+};
1314+
1315+QTEST_MAIN(ListViewWithPageHeaderTest)
1316+
1317+#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 @@
20
20
21#include <AxisVelocityCalculator.h>
21#include <AxisVelocityCalculator.h>
22
22
23−class FakeTimeSource : public AxisVelocityCalculator::TimeSource {
23+class FakeTimeSource : public UbuntuGestures::TimeSource {
24public:
24public:
25 FakeTimeSource() : m_value(0) {}
25 FakeTimeSource() : m_value(0) {}
26
26
@@ -44,71 +44,85 @@ class tst_AxisVelocityCalculator : public QObject
44{
44{
45 Q_OBJECT
45 Q_OBJECT
46private Q_SLOTS:
46private 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+
47 void simpleSamples();
50 void simpleSamples();
48 void noSamples();
51 void noSamples();
49 void overflowSamples();
52 void overflowSamples();
50 void average();
53 void average();
54+
55+private:
56+ AxisVelocityCalculator *velCalc;
57+ FakeTimeSource *fakeTimeSource;
51};
58};
52
59
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+
53void tst_AxisVelocityCalculator::simpleSamples()
74void tst_AxisVelocityCalculator::simpleSamples()
54{
75{
55− FakeTimeSource *fakeTimeSource = new FakeTimeSource;
56− AxisVelocityCalculator velCalc(fakeTimeSource);
57 qreal pos = 0;
76 qreal pos = 0;
58
77
59− velCalc.setTrackedPosition(pos);
78+ velCalc->setTrackedPosition(pos);
60− velCalc.reset();
79+ velCalc->reset();
61
80
62 fakeTimeSource->setMsecsSinceReference(10);
81 fakeTimeSource->setMsecsSinceReference(10);
63 pos += 20;
82 pos += 20;
64− velCalc.setTrackedPosition(pos);
83+ velCalc->setTrackedPosition(pos);
65
84
66 fakeTimeSource->setMsecsSinceReference(20);
85 fakeTimeSource->setMsecsSinceReference(20);
67 pos += 20;
86 pos += 20;
68− velCalc.setTrackedPosition(pos);
87+ velCalc->setTrackedPosition(pos);
69
88
70 fakeTimeSource->setMsecsSinceReference(30);
89 fakeTimeSource->setMsecsSinceReference(30);
71 pos += 20;
90 pos += 20;
72− velCalc.setTrackedPosition(pos);
91+ velCalc->setTrackedPosition(pos);
73
92
74− qreal velocity = velCalc.calculate();
93+ qreal velocity = velCalc->calculate();
75
94
76 QCOMPARE(velocity, 2.0f);
95 QCOMPARE(velocity, 2.0f);
77}
96}
78
97
79void tst_AxisVelocityCalculator::noSamples()
98void tst_AxisVelocityCalculator::noSamples()
80{
99{
81− FakeTimeSource *fakeTimeSource = new FakeTimeSource;
100+ float velocity = velCalc->calculate();
82− AxisVelocityCalculator velCalc(fakeTimeSource);
83−
84− float velocity = velCalc.calculate();
85
101
86 QCOMPARE(velocity, 0.0f);
102 QCOMPARE(velocity, 0.0f);
87}
103}
88
104
89void tst_AxisVelocityCalculator::overflowSamples()
105void tst_AxisVelocityCalculator::overflowSamples()
90{
106{
91− FakeTimeSource *fakeTimeSource = new FakeTimeSource;
92− AxisVelocityCalculator velCalc(fakeTimeSource);
93 qreal pos = 0;
107 qreal pos = 0;
94
108
95− velCalc.setTrackedPosition(pos);
109+ velCalc->setTrackedPosition(pos);
96− velCalc.reset();
110+ velCalc->reset();
97
111
98 for (int i = 0; i < 1000; ++i) {
112 for (int i = 0; i < 1000; ++i) {
99 fakeTimeSource->increaseMsecsSinceReference(10);
113 fakeTimeSource->increaseMsecsSinceReference(10);
100 pos += 20;
114 pos += 20;
101− velCalc.setTrackedPosition(pos);
115+ velCalc->setTrackedPosition(pos);
102 }
116 }
103
117
104 /* overwrite all existing samples with faster ones */
118 /* overwrite all existing samples with faster ones */
105 for (int i = 0; i < AxisVelocityCalculator::MAX_SAMPLES; ++i) {
119 for (int i = 0; i < AxisVelocityCalculator::MAX_SAMPLES; ++i) {
106 fakeTimeSource->increaseMsecsSinceReference(10);
120 fakeTimeSource->increaseMsecsSinceReference(10);
107 pos += 40;
121 pos += 40;
108− velCalc.setTrackedPosition(pos);
122+ velCalc->setTrackedPosition(pos);
109 }
123 }
110
124
111− float velocity = velCalc.calculate();
125+ float velocity = velCalc->calculate();
112
126
113 /* check that the calculated velocity correspond to the latest, faster, samples */
127 /* check that the calculated velocity correspond to the latest, faster, samples */
114 QCOMPARE(velocity, 4.0f);
128 QCOMPARE(velocity, 4.0f);
@@ -116,28 +130,26 @@ void tst_AxisVelocityCalculator::overflowSamples()
116
130
117void tst_AxisVelocityCalculator::average()
131void tst_AxisVelocityCalculator::average()
118{
132{
119− FakeTimeSource *fakeTimeSource = new FakeTimeSource;
120− AxisVelocityCalculator velCalc(fakeTimeSource);
121 qreal pos = 0;
133 qreal pos = 0;
122
134
123− velCalc.setTrackedPosition(pos);
135+ velCalc->setTrackedPosition(pos);
124− velCalc.reset();
136+ velCalc->reset();
125
137
126 fakeTimeSource->increaseMsecsSinceReference(10);
138 fakeTimeSource->increaseMsecsSinceReference(10);
127 pos += 20;
139 pos += 20;
128− velCalc.setTrackedPosition(pos);
140+ velCalc->setTrackedPosition(pos);
129
141
130 fakeTimeSource->increaseMsecsSinceReference(10);
142 fakeTimeSource->increaseMsecsSinceReference(10);
131 pos += 20;
143 pos += 20;
132− velCalc.setTrackedPosition(pos);
144+ velCalc->setTrackedPosition(pos);
133
145
134 /* the last sample is an erratic one and would yield a big velocity if
146 /* the last sample is an erratic one and would yield a big velocity if
135 considered isolatedly */
147 considered isolatedly */
136 fakeTimeSource->increaseMsecsSinceReference(10);
148 fakeTimeSource->increaseMsecsSinceReference(10);
137 pos += 100;
149 pos += 100;
138− velCalc.setTrackedPosition(pos);
150+ velCalc->setTrackedPosition(pos);
139
151
140− float velocity = velCalc.calculate();
152+ float velocity = velCalc->calculate();
141
153
142 /* calculated velocity is lower than the one from the last sample */
154 /* calculated velocity is lower than the one from the last sample */
143 QVERIFY(velocity < 9.0f);
155 QVERIFY(velocity < 9.0f);
tests/plugins/Ubuntu/Gestures/tst_DirectionalDragArea.cpp+99−11
@@ -38,7 +38,7 @@ private:
38 int m_duration;
38 int m_duration;
39};
39};
40
40
41−class FakeTimeSource : public AxisVelocityCalculator::TimeSource
41+class FakeTimeSource : public UbuntuGestures::TimeSource
42{
42{
43public:
43public:
44 FakeTimeSource() { m_msecsSinceReference = 0; }
44 FakeTimeSource() { m_msecsSinceReference = 0; }
@@ -65,6 +65,9 @@ private Q_SLOTS:
65 void minSpeed_data();
65 void minSpeed_data();
66 void recognitionTimerUsage();
66 void recognitionTimerUsage();
67 void maxSilenceTime();
67 void maxSilenceTime();
68+ void sceneXAndX();
69+ void sceneYAndY();
70+ void emitDraggingChangedOnDirectRecognition();
68
71
69private:
72private:
70 QQuickView *createView();
73 QQuickView *createView();
@@ -72,7 +75,6 @@ private:
72 QTouchDevice *device;
75 QTouchDevice *device;
73 FakeTimer *fakeTimer;
76 FakeTimer *fakeTimer;
74 FakeTimeSource *fakeTimeSource;
77 FakeTimeSource *fakeTimeSource;
75− AxisVelocityCalculator *velCalcWithFakeTiming;
76};
78};
77
79
78void tst_DirectionalDragArea::initTestCase()
80void tst_DirectionalDragArea::initTestCase()
@@ -101,7 +103,6 @@ void tst_DirectionalDragArea::init()
101
103
102 fakeTimer = new FakeTimer;
104 fakeTimer = new FakeTimer;
103 fakeTimeSource = new FakeTimeSource;
105 fakeTimeSource = new FakeTimeSource;
104− velCalcWithFakeTiming = new AxisVelocityCalculator(fakeTimeSource);
105}
106}
106
107
107void tst_DirectionalDragArea::cleanup()
108void tst_DirectionalDragArea::cleanup()
@@ -112,10 +113,8 @@ void tst_DirectionalDragArea::cleanup()
112 delete fakeTimer;
113 delete fakeTimer;
113 fakeTimer = 0;
114 fakeTimer = 0;
114
115
115− // will bring fakeTimeSource down with it
116+ delete fakeTimeSource;
116− delete velCalcWithFakeTiming;
117 fakeTimeSource = 0;
117 fakeTimeSource = 0;
118− velCalcWithFakeTiming = 0;
119}
118}
120
119
121QQuickView *tst_DirectionalDragArea::createView()
120QQuickView *tst_DirectionalDragArea::createView()
@@ -187,7 +186,7 @@ void tst_DirectionalDragArea::edgeDrag()
187 view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
186 view->rootObject()->findChild<DirectionalDragArea*>(dragAreaObjectName);
188 QVERIFY(edgeDragArea != 0);
187 QVERIFY(edgeDragArea != 0);
189 edgeDragArea->setRecognitionTimer(fakeTimer);
188 edgeDragArea->setRecognitionTimer(fakeTimer);
190− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
189+ edgeDragArea->setTimeSource(fakeTimeSource);
191
190
192 QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
191 QSignalSpy draggingSpy(edgeDragArea, SIGNAL(draggingChanged(bool)));
193
192
@@ -292,7 +291,7 @@ void tst_DirectionalDragArea::dragWithShortDirectionChange()
292 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
291 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
293 QVERIFY(edgeDragArea != 0);
292 QVERIFY(edgeDragArea != 0);
294 edgeDragArea->setRecognitionTimer(fakeTimer);
293 edgeDragArea->setRecognitionTimer(fakeTimer);
295− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
294+ edgeDragArea->setTimeSource(fakeTimeSource);
296
295
297 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
296 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
298 QPointF touchPoint = initialTouchPos;
297 QPointF touchPoint = initialTouchPos;
@@ -337,7 +336,7 @@ void tst_DirectionalDragArea::minSpeed()
337 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
336 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
338 QVERIFY(edgeDragArea != 0);
337 QVERIFY(edgeDragArea != 0);
339 edgeDragArea->setRecognitionTimer(fakeTimer);
338 edgeDragArea->setRecognitionTimer(fakeTimer);
340− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
339+ edgeDragArea->setTimeSource(fakeTimeSource);
341
340
342 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
341 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
343 QPointF touchPoint = initialTouchPos;
342 QPointF touchPoint = initialTouchPos;
@@ -390,7 +389,7 @@ void tst_DirectionalDragArea::recognitionTimerUsage()
390 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
389 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
391 QVERIFY(edgeDragArea != 0);
390 QVERIFY(edgeDragArea != 0);
392 edgeDragArea->setRecognitionTimer(fakeTimer);
391 edgeDragArea->setRecognitionTimer(fakeTimer);
393− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
392+ edgeDragArea->setTimeSource(fakeTimeSource);
394
393
395 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
394 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
396 QPointF touchPoint = initialTouchPos;
395 QPointF touchPoint = initialTouchPos;
@@ -431,7 +430,7 @@ void tst_DirectionalDragArea::maxSilenceTime()
431 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
430 view->rootObject()->findChild<DirectionalDragArea*>("hpDragArea");
432 QVERIFY(edgeDragArea != 0);
431 QVERIFY(edgeDragArea != 0);
433 edgeDragArea->setRecognitionTimer(fakeTimer);
432 edgeDragArea->setRecognitionTimer(fakeTimer);
434− edgeDragArea->setAxisVelocityCalculator(velCalcWithFakeTiming);
433+ edgeDragArea->setTimeSource(fakeTimeSource);
435
434
436 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
435 QPointF initialTouchPos = calculateInitialTouchPos(edgeDragArea, view);
437 QPointF touchPoint = initialTouchPos;
436 QPointF touchPoint = initialTouchPos;
@@ -458,6 +457,95 @@ void tst_DirectionalDragArea::maxSilenceTime()
458 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Rejected);
457 QCOMPARE((int)edgeDragArea->status(), (int)DirectionalDragArea::Rejected);
459}
458}
460
459
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+
461QTEST_MAIN(tst_DirectionalDragArea)
549QTEST_MAIN(tst_DirectionalDragArea)
462
550
463#include "tst_DirectionalDragArea.moc"
551#include "tst_DirectionalDragArea.moc"
tests/plugins/Unity/CMakeLists.txtnew file+38
@@ -0,0 +1,38 @@
1+pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0)
2+pkg_check_modules(LIBUNITYPROTO REQUIRED unity-protocol-private)
3+
4+include_directories(
5+ ${Unity-qml_SOURCE_DIR}
6+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../plugins/Unity
7+ ${CMAKE_CURRENT_BINARY_DIR}
8+ ${LIBUNITYPROTO_INCLUDE_DIRS}
9+ ${UNITYCORE_INCLUDE_DIRS}
10+ )
11+
12+macro(run_tests)
13+ set(_test_list "")
14+ foreach(_test ${ARGN})
15+ set(testCommand
16+ ${CMAKE_CURRENT_BINARY_DIR}/${_test}Exec
17+ -o ${CMAKE_BINARY_DIR}/${_test}.xml,xunitxml
18+ -o -,txt)
19+ add_test(NAME test${CLASSNAME}${_test} COMMAND ${testCommand})
20+ add_custom_target(${_test} ${testCommand})
21+ add_executable(${_test}Exec ${_test}.cpp previewbindingstest.cpp)
22+ qt5_use_modules(${_test}Exec Test Core Qml)
23+ set_tests_properties(test${CLASSNAME}${_test}
24+ PROPERTIES ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Unity:${LIBUNITYPROTO_LIBRARY_DIRS})
25+
26+ target_link_libraries(${_test}Exec
27+ Unity-qml
28+ ${UNITYCORE_LDFLAGS}
29+ ${LIBUNITYPROTO_LDFLAGS}
30+ )
31+
32+ set(_test_list "${_test_list};${_test}")
33+ endforeach()
34+endmacro(run_tests)
35+
36+run_tests(
37+ previewbindingstest
38+ )
tests/plugins/Unity/previewbindingstest.cppnew file+114
@@ -0,0 +1,114 @@
1+/*
2+ * Copyright (C) 2011, 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 "previewbindingstest.h"
18+#include <QTest>
19+
20+#include <UnityCore/Preview.h>
21+#include <UnityCore/GLibWrapper.h>
22+#include <unity-protocol.h>
23+
24+#include "genericpreview.h"
25+#include "applicationpreview.h"
26+#include "moviepreview.h"
27+#include "musicpreview.h"
28+
29+void PreviewBindingsTest::initTestCase()
30+{
31+}
32+
33+void PreviewBindingsTest::testGenericPreview()
34+{
35+ auto raw_preview = (GObject *)unity_protocol_generic_preview_new();
36+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Metallica");
37+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Ride The Lightning");
38+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
39+ unity::glib::Object<GObject> gen_prv(raw_preview);
40+
41+ auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
42+ auto prv = Preview::newFromUnityPreview(core_prv);
43+
44+ QCOMPARE(prv != nullptr, true);
45+ QCOMPARE(prv->title(), QString("Metallica"));
46+ QCOMPARE(prv->subtitle(), QString("Ride The Lightning"));
47+ QCOMPARE(prv->description(), QString("Lorem ipsum dolor sit amet"));
48+}
49+
50+void PreviewBindingsTest::testApplicationPreview()
51+{
52+ auto raw_preview = (GObject *)unity_protocol_application_preview_new();
53+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Firefox");
54+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Web Browser");
55+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
56+ unity_protocol_application_preview_set_license(UNITY_PROTOCOL_APPLICATION_PREVIEW(raw_preview), "GPL");
57+ unity_protocol_application_preview_set_rating(UNITY_PROTOCOL_APPLICATION_PREVIEW(raw_preview), 0.5f);
58+ unity_protocol_application_preview_set_num_ratings(UNITY_PROTOCOL_APPLICATION_PREVIEW(raw_preview), 4);
59+ unity::glib::Object<GObject> gen_prv(raw_preview);
60+
61+ auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
62+ auto prv = Preview::newFromUnityPreview(core_prv);
63+ auto app_prv = dynamic_cast<ApplicationPreview*>(prv);
64+
65+ QCOMPARE(app_prv != nullptr, true);
66+ QCOMPARE(app_prv->title(), QString("Firefox"));
67+ QCOMPARE(app_prv->subtitle(), QString("Web Browser"));
68+ QCOMPARE(app_prv->description(), QString("Lorem ipsum dolor sit amet"));
69+ QCOMPARE(app_prv->license(), QString("GPL"));
70+ QCOMPARE(app_prv->rating(), 0.5f);
71+ QCOMPARE(app_prv->numRatings(), unsigned (4));
72+}
73+
74+void PreviewBindingsTest::testMoviePreview()
75+{
76+ auto raw_preview = (GObject *)unity_protocol_movie_preview_new();
77+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Blade Runner");
78+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Ridley Scott");
79+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
80+ unity_protocol_movie_preview_set_year(UNITY_PROTOCOL_MOVIE_PREVIEW(raw_preview), "1982");
81+ unity::glib::Object<GObject> gen_prv(raw_preview);
82+
83+ auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
84+ auto prv = Preview::newFromUnityPreview(core_prv);
85+ auto movie_prv = dynamic_cast<MoviePreview*>(prv);
86+
87+ QCOMPARE(movie_prv != nullptr, true);
88+ QCOMPARE(movie_prv->title(), QString("Blade Runner"));
89+ QCOMPARE(movie_prv->subtitle(), QString("Ridley Scott"));
90+ QCOMPARE(movie_prv->description(), QString("Lorem ipsum dolor sit amet"));
91+ QCOMPARE(movie_prv->year(), QString("1982"));
92+}
93+
94+void PreviewBindingsTest::testMusicPreview()
95+{
96+ auto raw_preview = (GObject *)unity_protocol_music_preview_new();
97+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Metallica");
98+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Death Magnetic");
99+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
100+ unity::glib::Object<GObject> gen_prv(raw_preview);
101+
102+ auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
103+ auto prv = Preview::newFromUnityPreview(core_prv);
104+ auto music_prv = dynamic_cast<MusicPreview*>(prv);
105+
106+ QCOMPARE(music_prv != nullptr, true);
107+ QCOMPARE(music_prv->title(), QString("Metallica"));
108+ QCOMPARE(music_prv->subtitle(), QString("Death Magnetic"));
109+ QCOMPARE(music_prv->description(), QString("Lorem ipsum dolor sit amet"));
110+}
111+
112+QTEST_MAIN(PreviewBindingsTest)
113+
114+#include "previewbindingstest.moc"
plugins/LightDM/InfographicModel.h → tests/plugins/Unity/previewbindingstest.hrenamed+15−8
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2012,2013 Canonical, Ltd.
2+ * Copyright (C) 2011, 2013 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -12,16 +12,23 @@
12 *
12 *
13 * You should have received a copy of the GNU General Public License
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/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Pete Woods <pete.woods@canonical.com>
17 */
15 */
18
16
19−#ifndef INFOGRAPHICMODEL_H
17+#ifndef PREVIEWBINDINGSTEST_H
20−#define INFOGRAPHICMODEL_H
18+#define PREVIEWBINDINGSTEST_H
19+
20+#include <QObject>
21
21
22−#include <QLightDM/InfographicModel>
22+class PreviewBindingsTest : public QObject
23+{
24+ Q_OBJECT
23
25
24−typedef QLightDM::InfographicModel InfographicModel;
26+ private Q_SLOTS:
25−typedef QLightDM::InfographicColorTheme InfographicColorTheme;
27+ void initTestCase();
28+ void testGenericPreview();
29+ void testApplicationPreview();
30+ void testMoviePreview();
31+ void testMusicPreview();
32+};
26
33
27#endif
34#endif
tests/plugins/Utils/qlimitproxymodeltest.cpp+15
@@ -446,6 +446,7 @@ private Q_SLOTS:
446
446
447 ModelTest t1(&proxy);
447 ModelTest t1(&proxy);
448 }
448 }
449+
449 void testModelChanged() {
450 void testModelChanged() {
450 QLimitProxyModelQML proxy;
451 QLimitProxyModelQML proxy;
451 MockListModel model, model2;
452 MockListModel model, model2;
@@ -464,6 +465,20 @@ private Q_SLOTS:
464 proxy.setModel(&model);
465 proxy.setModel(&model);
465 QCOMPARE(spyOnModelChanged.count(), 3);
466 QCOMPARE(spyOnModelChanged.count(), 3);
466 }
467 }
468+
469+ void setSameModelTwice() {
470+ QLimitProxyModelQML proxy;
471+ MockListModel model;
472+
473+ proxy.setModel(&model);
474+ proxy.setModel(&model);
475+
476+ QSignalSpy spyOnCountChanged(&proxy, SIGNAL(countChanged()));
477+
478+ model.insertRows(0, 5);
479+ QCOMPARE(proxy.rowCount(), 5);
480+ QCOMPARE(spyOnCountChanged.count(), 1);
481+ }
467};
482};
468
483
469QTEST_MAIN(QLimitProxyModelTest)
484QTEST_MAIN(QLimitProxyModelTest)
tests/qmltests/CMakeLists.txt+15−15
@@ -1,11 +1,11 @@
1# add_qml_test macro
1# add_qml_test macro
2include(QmlTest)
2include(QmlTest)
3
3
4−add_subdirectory(plugins)
4+add_subdirectory(Components)
5
5
6set(qmltest_DEFAULT_IMPORT_PATHS
6set(qmltest_DEFAULT_IMPORT_PATHS
7− ${CMAKE_CURRENT_BINARY_DIR}/plugins
8 ${CMAKE_BINARY_DIR}/tests/utils/modules
7 ${CMAKE_BINARY_DIR}/tests/utils/modules
8+ ${CMAKE_BINARY_DIR}/tests/mocks
9)
9)
10
10
11set(qmltest_DEFAULT_TARGETS qmlunittests)
11set(qmltest_DEFAULT_TARGETS qmlunittests)
@@ -25,9 +25,9 @@ add_qml_test(utils/Unity/Test UnityTest)
25set(qmltest_DEFAULT_TARGETS qmluitests)
25set(qmltest_DEFAULT_TARGETS qmluitests)
26set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
26set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
27set(qmltest_DEFAULT_PROPERTIES "")
27set(qmltest_DEFAULT_PROPERTIES "")
28+add_manual_qml_test(Components DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
28add_qml_test(Components DraggingArea)
29add_qml_test(Components DraggingArea)
29add_qml_test(Components FilterGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
30add_qml_test(Components FilterGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
30−add_qml_test(Components ListViewWithPageHeader)
31add_qml_test(Components ResponsiveFlowView)
31add_qml_test(Components ResponsiveFlowView)
32add_qml_test(Components ResponsiveGridView)
32add_qml_test(Components ResponsiveGridView)
33add_qml_test(Components Revealer)
33add_qml_test(Components Revealer)
@@ -42,27 +42,27 @@ add_qml_test(Dash DashBar IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRE
42add_qml_test(Dash DashContent IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS})
42add_qml_test(Dash DashContent IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS})
43add_qml_test(Dash DashPreview)
43add_qml_test(Dash DashPreview)
44add_qml_test(Dash GenericScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
44add_qml_test(Dash GenericScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
45−add_qml_test(Dash ScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_BINARY_DIR}/plugins)
45+add_qml_test(Dash ScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
46add_qml_test(Dash FilterGrids IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins
46add_qml_test(Dash FilterGrids IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins
47 ${CMAKE_BINARY_DIR}/tests/mocks)
47 ${CMAKE_BINARY_DIR}/tests/mocks)
48add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
48add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
49−add_qml_test(Greeter Lockscreen IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_BINARY_DIR}/tests/mocks
49+add_qml_test(Greeter Lockscreen IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
50− PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
50+ PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
51−add_qml_test(Greeter Tablet IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_BINARY_DIR}/tests/mocks
51+add_qml_test(Greeter Tablet IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
52− ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
52+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
53−add_qml_test(Greeter Phone IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_BINARY_DIR}/tests/mocks
53+add_qml_test(Greeter Phone IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
54− ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
54+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
55−add_qml_test(Greeter Infographics IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_BINARY_DIR}/tests/mocks
55+add_qml_test(Greeter Infographics IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
56− ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
56+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
57add_qml_test(Hud Hud)
57add_qml_test(Hud Hud)
58add_qml_test(Hud Result)
58add_qml_test(Hud Result)
59add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
59add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
60−add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_CURRENT_SOURCE_DIR}/plugins)
60+add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_SOURCE_DIR}/tests/mocks)
61add_qml_test(Panel IndicatorRow)
61add_qml_test(Panel IndicatorRow)
62−add_qml_test(Panel Indicators)
62+add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
63add_qml_test(Panel MenuContent)
63add_qml_test(Panel MenuContent)
64add_qml_test(Panel Overview)
64add_qml_test(Panel Overview)
65−add_qml_test(Panel Panel)
65+add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
66add_qml_test(Panel SearchIndicator)
66add_qml_test(Panel SearchIndicator)
67add_qml_test(Panel/Menus IndicatorMenuWindow IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS})
67add_qml_test(Panel/Menus IndicatorMenuWindow IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS})
68add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
68add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
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 {
233
233
234 var touchX = stage.width - (stage.rightEdgeDraggingAreaWidth / 2)
234 var touchX = stage.width - (stage.rightEdgeDraggingAreaWidth / 2)
235 var touchY = stage.height / 2
235 var touchY = stage.height / 2
236− touchFlick(stage, touchX, touchY,
236+ touchFlick(stage, touchX, touchY, stage.width * 0.25, touchY)
237− touchX - units.gu(5), touchY)
238
237
239 // wait until animations end, if any
238 // wait until animations end, if any
240 tryCompare(stage, "usingScreenshots", false)
239 tryCompare(stage, "usingScreenshots", false)
tests/qmltests/Greeter/tst_Lockscreen.qml+7−1
@@ -187,8 +187,8 @@ Rectangle {
187 unlockedCheckBox.checked = false
187 unlockedCheckBox.checked = false
188 LightDM.Greeter.authenticate(data.username)
188 LightDM.Greeter.authenticate(data.username)
189
189
190+ var inputField = findChild(lockscreen, "pinentryField")
190 if (data.alphanumeric) {
191 if (data.alphanumeric) {
191− var inputField = findChild(lockscreen, "pinentryField")
192 mouseClick(inputField, units.gu(1), units.gu(1))
192 mouseClick(inputField, units.gu(1), units.gu(1))
193 typeString(data.password)
193 typeString(data.password)
194 keyClick(Qt.Key_Enter)
194 keyClick(Qt.Key_Enter)
@@ -200,6 +200,12 @@ Rectangle {
200 }
200 }
201 }
201 }
202 tryCompare(unlockedCheckBox, "checked", data.unlockedSignal)
202 tryCompare(unlockedCheckBox, "checked", data.unlockedSignal)
203+ if (!data.unlockedSignal) {
204+ // make sure the input is cleared on wrong input
205+ tryCompareFunction(function() {return inputField.text.length == 0}, true)
206+ } else {
207+ tryCompareFunction(function() {return inputField.text.length > 0}, true)
208+ }
203 }
209 }
204 }
210 }
205}
211}
tests/qmltests/Greeter/tst_Phone.qml+40−1
@@ -28,7 +28,17 @@ Item {
28
28
29 Greeter {
29 Greeter {
30 id: greeter
30 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+ }
32 }
42 }
33
43
34 SignalSpy {
44 SignalSpy {
@@ -63,5 +73,34 @@ Item {
63 tryCompare(greeter, "leftTeaserPressed", false)
73 tryCompare(greeter, "leftTeaserPressed", false)
64 tryCompare(greeter, "rightTeaserPressed", false)
74 tryCompare(greeter, "rightTeaserPressed", false)
65 }
75 }
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+ }
66 }
105 }
67}
106}
tests/qmltests/Launcher/tst_Launcher.qml+40
@@ -43,6 +43,18 @@ Item {
43 onDashItemSelected: {
43 onDashItemSelected: {
44 dashItemSelected_count++;
44 dashItemSelected_count++;
45 }
45 }
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+ }
46 }
58 }
47
59
48 UT.UnityTestCase {
60 UT.UnityTestCase {
@@ -126,5 +138,33 @@ Item {
126 var panel = findChild(launcher, "launcherPanel")
138 var panel = findChild(launcher, "launcherPanel")
127 tryCompare(panel, "x", -panel.width, 1000)
139 tryCompare(panel, "x", -panel.width, 1000)
128 }
140 }
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+ }
129 }
169 }
130}
170}
tests/qmltests/Notifications/tst_Notifications.qml+48−7
@@ -53,7 +53,10 @@ Row {
53 icon: "../graphics/avatars/funky.png",
53 icon: "../graphics/avatars/funky.png",
54 secondaryIcon: "../graphics/applicationIcons/facebook.png",
54 secondaryIcon: "../graphics/applicationIcons/facebook.png",
55 actions: [{ id: "ok_id", label: "Ok"},
55 actions: [{ id: "ok_id", label: "Ok"},
56− { id: "cancel_id", label: "Cancel"}]
56+ { id: "cancel_id", label: "Cancel"},
57+ { id: "notreally_id", label: "Not really"},
58+ { id: "noway_id", label: "No way"},
59+ { id: "nada_id", label: "Nada"}]
57 }
60 }
58
61
59 mockModel.append(n)
62 mockModel.append(n)
@@ -132,7 +135,7 @@ Row {
132 id: interactiveControls
135 id: interactiveControls
133
136
134 width: units.gu(30)
137 width: units.gu(30)
135− height: units.gu(71)
138+ height: units.gu(81)
136 color: "grey"
139 color: "grey"
137
140
138 Column {
141 Column {
@@ -193,7 +196,10 @@ Row {
193 icon: "../graphics/avatars/funky.png",
196 icon: "../graphics/avatars/funky.png",
194 secondaryIcon: "../graphics/applicationIcons/facebook.png",
197 secondaryIcon: "../graphics/applicationIcons/facebook.png",
195 actions: [{ id: "ok_id", label: "Ok"},
198 actions: [{ id: "ok_id", label: "Ok"},
196− { id: "cancel_id", label: "Cancel"}],
199+ { id: "cancel_id", label: "Cancel"},
200+ { id: "notreally_id", label: "Not really"},
201+ { id: "noway_id", label: "No way"},
202+ { id: "nada_id", label: "Nada"}],
197 summaryVisible: true,
203 summaryVisible: true,
198 bodyVisible: true,
204 bodyVisible: true,
199 interactiveAreaEnabled: false,
205 interactiveAreaEnabled: false,
@@ -341,15 +347,50 @@ Row {
341 var buttonAccept = findChild(buttonRow, "button0")
347 var buttonAccept = findChild(buttonRow, "button0")
342
348
343 waitForRendering(notification)
349 waitForRendering(notification)
344− mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
345− actionSpy.wait()
346− compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
347− actionSpy.clear()
348
350
351+ // only test the left/cancel-button if two actions have been passed in
352+ if (data.actions.length == 2) {
353+ mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
354+ actionSpy.wait()
355+ compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
356+ actionSpy.clear()
357+ }
358+
359+ // click the positive/right button
349 mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2)
360 mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2)
350 actionSpy.wait()
361 actionSpy.wait()
351 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action")
362 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action")
352 actionSpy.clear()
363 actionSpy.clear()
364+
365+ // check if there's more than one negative choice
366+ if (data.actions.length > 2) {
367+ var initialHeight = notification.height
368+
369+ // click to expand
370+ mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
371+ waitForRendering(notification)
372+ actionSpy.clear()
373+ 
374+ // test the additional buttons
375+ for (var i = 2; i < data.actions.length; i++) {
376+ waitForRendering(notification)
377+ var buttonColumn = findChild(notification, "buttonColumn")
378+ var button = findChild(buttonColumn, "button" + i)
379+ mouseClick(button, button.width / 2, button.height / 2)
380+ actionSpy.wait()
381+ compare(actionSpy.signalArguments[0][0], data.actions[i]["id"], "got wrong id for additional negative action")
382+ actionSpy.clear()
383+ }
384+
385+ // click to collapse
386+ mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
387+ waitForRendering(notification)
388+ tryCompare(notification, "height", initialHeight)
389+ } else {
390+ mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
391+ actionSpy.wait()
392+ compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
393+ }
353 }
394 }
354 }
395 }
355 }
396 }
tests/qmltests/Panel/tst_Indicators.qml+34−45

This diff is too big to show here.

tests/qmltests/Panel/tst_Panel.qml+65−113

This diff is too big to show here.

tests/qmltests/plugins/CMakeLists.txtdeleted−3

This diff is too big to show here.

tests/qmltests/plugins/Dee/qmldirdeleted−3

This diff is too big to show here.

tests/qmltests/plugins/Ubuntu/CMakeLists.txtdeleted−1

This diff is too big to show here.