Merge lp:~phablet-team/ubuntu-settings-components/fingerprint into lp:ubuntu-settings-components

Proposed by Jonas G. Drange
Status: Merged
Approved by: Ken VanDine
Approved revision: 168
Merged at revision: 151
Proposed branch: lp:~phablet-team/ubuntu-settings-components/fingerprint
Merge into: lp:ubuntu-settings-components
Diff against target: 4441 lines (+4059/-19)
56 files modified
debian/changelog (+8/-1)
debian/control (+5/-2)
examples/Fingerprint.qml (+43/-0)
plugins/Ubuntu/Settings/CMakeLists.txt (+1/-0)
plugins/Ubuntu/Settings/Fingerprint/CMakeLists.txt (+15/-0)
plugins/Ubuntu/Settings/Fingerprint/CircularSegment.qml (+64/-0)
plugins/Ubuntu/Settings/Fingerprint/DirectionVisual.qml (+103/-0)
plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml (+133/-0)
plugins/Ubuntu/Settings/Fingerprint/FingerprintVisual.qml (+72/-0)
plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml (+439/-0)
plugins/Ubuntu/Settings/Fingerprint/SegmentBoundingBoxes.qml (+81/-0)
plugins/Ubuntu/Settings/Fingerprint/SegmentRenderer.qml (+95/-0)
plugins/Ubuntu/Settings/Fingerprint/SegmentedImage.qml (+52/-0)
plugins/Ubuntu/Settings/Fingerprint/Setup.qml (+387/-0)
plugins/Ubuntu/Settings/Fingerprint/StatusLabel.qml (+84/-0)
plugins/Ubuntu/Settings/Fingerprint/assets.qrc (+11/-0)
plugins/Ubuntu/Settings/Fingerprint/assets/fingerprint_boxes.json (+1/-0)
plugins/Ubuntu/Settings/Fingerprint/assets/shape-down@27.sci (+7/-0)
plugins/Ubuntu/Settings/Fingerprint/assets/shape-up@27.sci (+7/-0)
plugins/Ubuntu/Settings/Fingerprint/plugin.cpp (+35/-0)
plugins/Ubuntu/Settings/Fingerprint/plugin.h (+30/-0)
plugins/Ubuntu/Settings/Fingerprint/qmldir (+7/-0)
plugins/Ubuntu/Settings/Fingerprint/ubuntusettingsfingerprint.cpp (+39/-0)
plugins/Ubuntu/Settings/Fingerprint/ubuntusettingsfingerprint.h (+37/-0)
plugins/Ubuntu/Settings/Fingerprint/utils/segment.py (+84/-0)
po/ubuntu-settings-components.pot (+101/-16)
tests/qmltests/CMakeLists.txt (+7/-0)
tests/qmltests/Fingerprint/tst_FingerprintNames.qml (+364/-0)
tests/qmltests/Fingerprint/tst_FingerprintSetup.qml (+236/-0)
tests/qmltests/Fingerprint/tst_FingerprintVisual.qml (+132/-0)
tests/qmltests/Fingerprint/tst_Fingerprints.qml (+230/-0)
tests/qmltests/mocks/Biometryd/CMakeLists.txt (+20/-0)
tests/qmltests/mocks/Biometryd/MockDevice.cpp (+30/-0)
tests/qmltests/mocks/Biometryd/MockDevice.h (+38/-0)
tests/qmltests/mocks/Biometryd/MockFingerprintReader.cpp (+49/-0)
tests/qmltests/mocks/Biometryd/MockFingerprintReader.h (+65/-0)
tests/qmltests/mocks/Biometryd/MockObserver.cpp (+88/-0)
tests/qmltests/mocks/Biometryd/MockObserver.h (+52/-0)
tests/qmltests/mocks/Biometryd/MockOperation.cpp (+34/-0)
tests/qmltests/mocks/Biometryd/MockOperation.h (+36/-0)
tests/qmltests/mocks/Biometryd/MockService.cpp (+42/-0)
tests/qmltests/mocks/Biometryd/MockService.h (+46/-0)
tests/qmltests/mocks/Biometryd/MockTemplateStore.cpp (+56/-0)
tests/qmltests/mocks/Biometryd/MockTemplateStore.h (+86/-0)
tests/qmltests/mocks/Biometryd/MockUser.cpp (+33/-0)
tests/qmltests/mocks/Biometryd/MockUser.h (+38/-0)
tests/qmltests/mocks/Biometryd/plugin.cpp (+60/-0)
tests/qmltests/mocks/Biometryd/plugin.h (+31/-0)
tests/qmltests/mocks/Biometryd/qmldir (+2/-0)
tests/qmltests/mocks/CMakeLists.txt (+32/-0)
tests/qmltests/mocks/GSettings.1.0/CMakeLists.txt (+20/-0)
tests/qmltests/mocks/GSettings.1.0/fake_gsettings.cpp (+124/-0)
tests/qmltests/mocks/GSettings.1.0/fake_gsettings.h (+101/-0)
tests/qmltests/mocks/GSettings.1.0/plugin.cpp (+33/-0)
tests/qmltests/mocks/GSettings.1.0/plugin.h (+31/-0)
tests/qmltests/mocks/GSettings.1.0/qmldir (+2/-0)
To merge this branch: bzr merge lp:~phablet-team/ubuntu-settings-components/fingerprint
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Approve
Ken VanDine Needs Fixing
PS Jenkins bot continuous-integration Pending
Review via email: mp+297451@code.launchpad.net

Commit message

components for allowing a user to manage fingerprints

Description of the change

* Are there any related MPs required for this MP to build/function as expected? Please list.
 Yes, fingerprint bindings, see silo 41
 * Did you perform an exploratory manual test run of your code change and any related functionality?
 Yes
 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
 Done
 * If you changed the UI, has there been a design review?
 TBD
 * If you changed localized strings, has the POT file been updated?
 Yes

Rationale: https://docs.google.com/document/d/1d8gEataSjJMRacQbdSy0W4pSFA9q1UKA660CvXk-wNI/edit

To post a comment you must log in.
164. By Jonas G. Drange

bump version

165. By Jonas G. Drange

clearer cancel logic

166. By Jonas G. Drange

remove brackets in changelog

167. By Jonas G. Drange

readd silly space

168. By Jonas G. Drange

update pot

Revision history for this message
Ken VanDine (ken-vandine) wrote :

The code looks good, but there are a few places where there is code left in commented out. Let's get that removed.

review: Needs Fixing
169. By Ken VanDine

removed commented out code

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:
https://unity8-jenkins.ubuntu.com/job/lp-ubuntu-settings-components-ci/40/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2038
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2066
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1977
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1977
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1977
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1967
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1967/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1967
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1967/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1967
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1967/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1967
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1967/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1967
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1967/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1967
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1967/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1967
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1967/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1967
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1967/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1967
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1967/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-ubuntu-settings-components-ci/40/rebuild

review: Approve (continuous-integration)
170. By Jonas G. Drange

change the arrow so that it points outwards

171. By Jonas G. Drange

rename initial label, as well as the one showing during the enrollment

172. By Jonas G. Drange

sync with trunk, udpate pot

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2016-06-17 13:02:38 +0000
3+++ debian/changelog 2016-06-20 13:58:28 +0000
4@@ -1,3 +1,10 @@
5+ubuntu-settings-components (0.8+16.10.20160615-0ubuntu1) UNRELEASED; urgency=medium
6+
7+ jonas-drange
8+ * Add components for Fingerprint management.
9+
10+ -- Jonas G. Drange <jonas.drange@canonical.com> Wed, 15 June 2016 13:17:23 +0200
11+
12 ubuntu-settings-components (0.7+16.10.20160617-0ubuntu1) yakkety; urgency=medium
13
14 [ Lukáš Tinkl ]
15@@ -239,7 +246,7 @@
16 ubuntu-settings-components (0.2+14.10.20140701.2-0ubuntu2) utopic; urgency=medium
17
18 * debian/control:
19- list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
20+ list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
21 choice, since provides are not versionned, should restore installability
22 on amd64 and i386
23
24
25=== modified file 'debian/control'
26--- debian/control 2016-03-01 15:37:36 +0000
27+++ debian/control 2016-06-20 13:58:28 +0000
28@@ -27,7 +27,10 @@
29 Architecture: any
30 Multi-Arch: same
31 Pre-Depends: dpkg (>= 1.15.6~)
32-Depends: qml-module-qtquick-layouts,
33+Depends: gsettings-ubuntu-schemas (>= 0.0.7),
34+ qml-module-biometryd,
35+ qml-module-qtquick-layouts,
36+ qtdeclarative5-gsettings1.0 (>=0.1+14.10.20140801.1),
37 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1),
38 suru-icon-theme,
39 ${misc:Depends},
40@@ -35,4 +38,4 @@
41 Breaks: qtdeclarative5-ubuntu-settings-components-assets (<< 0.3),
42 Replaces: qtdeclarative5-ubuntu-settings-components-assets (<< 0.3),
43 Description: Ubuntu Settings Components
44- Ubuntu settings components for Unity
45\ No newline at end of file
46+ Ubuntu settings components for Unity
47
48=== added file 'examples/Fingerprint.qml'
49--- examples/Fingerprint.qml 1970-01-01 00:00:00 +0000
50+++ examples/Fingerprint.qml 2016-06-20 13:58:28 +0000
51@@ -0,0 +1,43 @@
52+/*
53+ * Copyright 2016 Canonical Ltd.
54+ *
55+ * This program is free software; you can redistribute it and/or modify
56+ * it under the terms of the GNU Lesser General Public License as published by
57+ * the Free Software Foundation; version 3.
58+ *
59+ * This program is distributed in the hope that it will be useful,
60+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
61+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62+ * GNU Lesser General Public License for more details.
63+ *
64+ * You should have received a copy of the GNU Lesser General Public License
65+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
66+ *
67+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
68+ */
69+
70+import QtQuick 2.4
71+import QtQuick.Layouts 1.2
72+import Ubuntu.Components 1.3
73+import Ubuntu.Components.Popups 1.3
74+import Ubuntu.Components.ListItems 1.3 as ListItems
75+import Ubuntu.Settings.Components 0.1
76+import Ubuntu.Settings.Fingerprint 0.1
77+
78+MainView {
79+ width: units.gu(50)
80+ height: units.gu(90)
81+
82+ PageStack {
83+ id: pageStack
84+
85+ Component.onCompleted: push(fingerprintPage)
86+
87+ Component {
88+ id: fingerprintPage
89+ Fingerprints {
90+ onRequestPasscode: passcodeSet = !passcodeSet
91+ }
92+ }
93+ }
94+}
95
96=== modified file 'plugins/Ubuntu/Settings/CMakeLists.txt'
97--- plugins/Ubuntu/Settings/CMakeLists.txt 2016-02-05 23:42:02 +0000
98+++ plugins/Ubuntu/Settings/CMakeLists.txt 2016-06-20 13:58:28 +0000
99@@ -1,3 +1,4 @@
100 add_subdirectory(Components)
101+add_subdirectory(Fingerprint)
102 add_subdirectory(Menus)
103 add_subdirectory(Vpn)
104
105=== added directory 'plugins/Ubuntu/Settings/Fingerprint'
106=== added file 'plugins/Ubuntu/Settings/Fingerprint/CMakeLists.txt'
107--- plugins/Ubuntu/Settings/Fingerprint/CMakeLists.txt 1970-01-01 00:00:00 +0000
108+++ plugins/Ubuntu/Settings/Fingerprint/CMakeLists.txt 2016-06-20 13:58:28 +0000
109@@ -0,0 +1,15 @@
110+project(UbuntuSettingsFingerprintQml)
111+
112+include_directories(
113+ ${CMAKE_CURRENT_SOURCE_DIR}
114+ ${CMAKE_CURRENT_BINARY_DIR}
115+)
116+add_definitions(-DUBUNTUSETTINGSFINGERPRINT_LIBRARY)
117+QT5_ADD_RESOURCES(assets assets.qrc)
118+add_library(UbuntuSettingsFingerprintQml MODULE
119+ plugin.cpp
120+ ubuntusettingsfingerprint.cpp
121+ ${assets}
122+)
123+qt5_use_modules(UbuntuSettingsFingerprintQml Core Qml Quick)
124+add_usc_plugin(Ubuntu.Settings.Fingerprint 0.1 Ubuntu/Settings/Fingerprint TARGETS UbuntuSettingsFingerprintQml)
125
126=== added file 'plugins/Ubuntu/Settings/Fingerprint/CircularSegment.qml'
127--- plugins/Ubuntu/Settings/Fingerprint/CircularSegment.qml 1970-01-01 00:00:00 +0000
128+++ plugins/Ubuntu/Settings/Fingerprint/CircularSegment.qml 2016-06-20 13:58:28 +0000
129@@ -0,0 +1,64 @@
130+/*
131+ * Copyright 2016 Canonical Ltd.
132+ *
133+ * This program is free software; you can redistribute it and/or modify
134+ * it under the terms of the GNU Lesser General Public License as published by
135+ * the Free Software Foundation; version 3.
136+ *
137+ * This program is distributed in the hope that it will be useful,
138+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
139+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
140+ * GNU Lesser General Public License for more details.
141+ *
142+ * You should have received a copy of the GNU Lesser General Public License
143+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
144+ *
145+ * Authored by Florian Boucault <florian.boucault@canonical.com>
146+ */
147+
148+import QtQuick 2.4
149+import Ubuntu.Components 1.3
150+
151+ShaderEffect {
152+ implicitWidth: units.gu(20)
153+ implicitHeight: units.gu(20)
154+ height: width
155+
156+ property color color: "#3EB34F"
157+ property real thickness: units.dp(3)
158+ property real angleStop: 90
159+
160+ property real _texturePixel: 1/width
161+ property real _thicknessTex: thickness/width
162+ property real _angleStopRadians: angleStop * (Math.PI / 180)
163+
164+ fragmentShader: "
165+ varying mediump vec2 qt_TexCoord0;
166+ uniform lowp float qt_Opacity;
167+ uniform lowp vec4 color;
168+ uniform lowp float _texturePixel;
169+ uniform lowp float _thicknessTex;
170+ uniform lowp float _angleStopRadians;
171+
172+ void main() {
173+ mediump vec2 center = vec2(0.5);
174+ mediump float circleX = (qt_TexCoord0.x - center.x);
175+ mediump float circleY = (qt_TexCoord0.y - center.y);
176+ mediump float distanceToCenter = circleX*circleX + circleY*circleY;
177+ const mediump float PI = 3.1415926535897932384626433832795;
178+ mediump float angle = atan(-circleX, circleY) + PI;
179+
180+ mediump float radius = 0.5;
181+ mediump float radiusSquare = radius * radius;
182+ mediump float radiusInner = radius - _thicknessTex;
183+ mediump float radiusInnerSquare = radiusInner * radiusInner;
184+
185+ lowp vec4 fillColor = mix(vec4(0),
186+ mix(color, vec4(0), smoothstep(distanceToCenter-_texturePixel, distanceToCenter+_texturePixel, radiusInnerSquare)),
187+ smoothstep(distanceToCenter-_texturePixel, distanceToCenter+_texturePixel, radiusSquare));
188+ fillColor = mix(fillColor, vec4(0), step(_angleStopRadians, angle));
189+ gl_FragColor = fillColor * qt_Opacity;
190+ }
191+ "
192+}
193+
194
195=== added file 'plugins/Ubuntu/Settings/Fingerprint/DirectionVisual.qml'
196--- plugins/Ubuntu/Settings/Fingerprint/DirectionVisual.qml 1970-01-01 00:00:00 +0000
197+++ plugins/Ubuntu/Settings/Fingerprint/DirectionVisual.qml 2016-06-20 13:58:28 +0000
198@@ -0,0 +1,103 @@
199+/*
200+ * Copyright 2016 Canonical Ltd.
201+ *
202+ * This program is free software; you can redistribute it and/or modify
203+ * it under the terms of the GNU Lesser General Public License as published by
204+ * the Free Software Foundation; version 3.
205+ *
206+ * This program is distributed in the hope that it will be useful,
207+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
208+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
209+ * GNU Lesser General Public License for more details.
210+ *
211+ * You should have received a copy of the GNU Lesser General Public License
212+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
213+ *
214+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
215+ */
216+
217+import Biometryd 0.0
218+import QtQuick 2.4
219+import Ubuntu.Components 1.3
220+import Ubuntu.Settings.Fingerprint 0.1
221+
222+Item {
223+ property int direction: FingerprintReader.NotAvailable
224+ opacity: direction !== FingerprintReader.NotAvailable ? 1 : 0
225+ Behavior on opacity { UbuntuNumberAnimation {} }
226+
227+ UbuntuNumberAnimation {
228+ id: rotationAnimation
229+ alwaysRunToEnd: true
230+
231+ target: directionContainer
232+ property: "rotation"
233+
234+ function normalizeAngle(v) {
235+ if (v < 0)
236+ return 360 + v;
237+ else
238+ return v % 360;
239+ }
240+
241+ onStopped: {
242+ directionContainer.rotation = normalizeAngle(directionContainer.rotation);
243+ }
244+ }
245+
246+ onDirectionChanged: {
247+ var v1 = rotation;
248+ var v2;
249+ var length;
250+
251+ switch (direction) {
252+ case FingerprintReader.North:
253+ v2 = 0; break;
254+ case FingerprintReader.NorthEast:
255+ v2 = 45; break;
256+ case FingerprintReader.East:
257+ v2 = 90; break;
258+ case FingerprintReader.SouthEast:
259+ v2 = 135; break;
260+ case FingerprintReader.South:
261+ v2 = 180; break;
262+ case FingerprintReader.SouthWest:
263+ v2 = 225; break;
264+ case FingerprintReader.West:
265+ v2 = 270; break;
266+ case FingerprintReader.NorthWest:
267+ v2 = 315; break;
268+ }
269+
270+ length = Math.min(Math.abs(v1 - v2),
271+ Math.abs(v1 - 360 - v2),
272+ Math.abs(v1 + 360 - v2));
273+
274+ if (length !== 180)
275+ length = length % 180;
276+
277+ if (((length + v1) % 360) === v2)
278+ v1 = v1 + length;
279+ else
280+ v1 = v1 -length;
281+
282+ rotationAnimation.from = rotation;
283+ rotationAnimation.to = v1;
284+ rotationAnimation.start();
285+ }
286+
287+ Icon {
288+ id: directionArrow
289+ objectName: "fingerprintDirectionLabel"
290+ anchors {
291+ top: parent.top
292+ topMargin: -units.gu(2)
293+ horizontalCenter: parent.horizontalCenter
294+ }
295+ width: units.gu(5)
296+ height: width
297+
298+ name: "up"
299+ color: theme.palette.normal.activity
300+ }
301+}
302
303=== added file 'plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml'
304--- plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml 1970-01-01 00:00:00 +0000
305+++ plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml 2016-06-20 13:58:28 +0000
306@@ -0,0 +1,133 @@
307+/*
308+ * Copyright 2016 Canonical Ltd.
309+ *
310+ * This program is free software; you can redistribute it and/or modify
311+ * it under the terms of the GNU Lesser General Public License as published by
312+ * the Free Software Foundation; version 3.
313+ *
314+ * This program is distributed in the hope that it will be useful,
315+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
316+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
317+ * GNU Lesser General Public License for more details.
318+ *
319+ * You should have received a copy of the GNU Lesser General Public License
320+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
321+ *
322+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
323+ */
324+
325+import QtQuick 2.4
326+import Ubuntu.Components 1.3
327+import Ubuntu.Components.Popups 1.3
328+import Ubuntu.Components.Themes.Ambiance 1.3
329+
330+Page {
331+ id: root
332+ property string name
333+ property string templateId
334+
335+ signal requestDeletion(string templateId)
336+ signal requestRename(string templateId, string name)
337+
338+ function deletionFailed() {
339+ PopupUtils.open(deletionFailed);
340+ state = "";
341+ }
342+
343+ header: PageHeader {
344+ objectName: "templateHeader"
345+ title: nameInput.text.length > 0 ? nameInput.text : name
346+ flickable: flickable
347+ }
348+
349+ states: [
350+ State {
351+ name: "deleting"
352+ PropertyChanges {
353+ target: nameInput
354+ enabled: false
355+ }
356+ PropertyChanges {
357+ target: deleteButton
358+ enabled: false
359+ }
360+ }
361+ ]
362+
363+ Flickable {
364+ id: flickable
365+ anchors {
366+ fill: parent
367+ topMargin: units.gu(2)
368+ }
369+ boundsBehavior: (contentHeight > root.height) ?
370+ Flickable.DragAndOvershootBounds :
371+ Flickable.StopAtBounds
372+ contentHeight: contentItem.childrenRect.height
373+
374+ Column {
375+ spacing: units.gu(2)
376+ anchors {
377+ left: parent.left
378+ right: parent.right
379+ margins: units.gu(3)
380+ }
381+
382+ Label {
383+ id: nameLabel
384+ anchors.left: parent.left
385+ anchors.right: parent.right
386+ text: i18n.dtr("ubuntu-settings-components", "Fingerprint Name")
387+ font.weight: Font.Light
388+ }
389+
390+ TextField {
391+ id: nameInput
392+ objectName: "nameInput"
393+ anchors.left: parent.left
394+ anchors.right: parent.right
395+ inputMethodHints: Qt.ImhNoPredictiveText
396+ style: TextFieldStyle {}
397+ text: name
398+ onTextChanged: {
399+ if (text)
400+ requestRename(templateId, text)
401+ }
402+ onAccepted: {
403+ if (text) {
404+ requestRename(templateId, text);
405+ pageStack.pop();
406+ }
407+ }
408+ }
409+
410+ Button {
411+ id: deleteButton
412+ objectName: "templateDelete"
413+ text: i18n.dtr("ubuntu-settings-components", "Delete Fingerprint")
414+ onClicked: {
415+ root.state = "deleting";
416+ requestDeletion(templateId)
417+ }
418+ width: parent.width
419+ }
420+ }
421+ }
422+
423+ Component {
424+ id: deletionFailed
425+
426+ Dialog {
427+ id: deletionFailedDialog
428+ objectName: "fingerprintDeletionFailedDialog"
429+ text: i18n.dtr("ubuntu-settings-components",
430+ "Sorry, the fingerprint could not be deleted.")
431+
432+ Button {
433+ objectName: "fingerprintDeleteionFailedOk"
434+ onClicked: PopupUtils.close(deletionFailedDialog)
435+ text: i18n.dtr("ubuntu-settings-components", "OK")
436+ }
437+ }
438+ }
439+}
440
441=== added file 'plugins/Ubuntu/Settings/Fingerprint/FingerprintVisual.qml'
442--- plugins/Ubuntu/Settings/Fingerprint/FingerprintVisual.qml 1970-01-01 00:00:00 +0000
443+++ plugins/Ubuntu/Settings/Fingerprint/FingerprintVisual.qml 2016-06-20 13:58:28 +0000
444@@ -0,0 +1,72 @@
445+/*
446+ * Copyright 2016 Canonical Ltd.
447+ *
448+ * This program is free software; you can redistribute it and/or modify
449+ * it under the terms of the GNU Lesser General Public License as published by
450+ * the Free Software Foundation; version 3.
451+ *
452+ * This program is distributed in the hope that it will be useful,
453+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
454+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
455+ * GNU Lesser General Public License for more details.
456+ *
457+ * You should have received a copy of the GNU Lesser General Public License
458+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
459+ *
460+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
461+ * Florian Boucault <florian.boucault@canonical.com>
462+ */
463+
464+import QtQuick 2.4
465+import Ubuntu.Settings.Fingerprint 0.1
466+
467+SegmentedImage {
468+ id: segmentedImage
469+
470+ property var masks: []
471+
472+ // http://stackoverflow.com/a/1830844/538866
473+ function isNumeric (n) {
474+ return !isNaN(parseFloat(n)) && isFinite(n);
475+ }
476+
477+ function getMasksToEnroll () {
478+ var outMasks = [];
479+ if (masks && masks.length) {
480+ masks.forEach(function (mask, i) {
481+ // Format is "<source>/[x1,y1,w1,h1],…,[xn,yn,wn,hn]"
482+ // If any value is non-numeric, we drop the mask.
483+ if (!isNumeric(mask.x) || !isNumeric(mask.y) || !isNumeric(mask.width)
484+ || !isNumeric(mask.height))
485+ return;
486+
487+ // Translate the box so as to mirror the mask
488+ mask.x = (1 - (mask.x + mask.width));
489+
490+ outMasks.push(mask);
491+ });
492+ }
493+ return outMasks;
494+ }
495+
496+ onMasksChanged: segmentedImage.enrollMasks(getMasksToEnroll())
497+
498+ textureSource: "qrc:/assets/fingerprint_segmented.png"
499+ boxesSource: "qrc:/assets/fingerprint_boxes.json"
500+
501+ Repeater {
502+ model: segmentedImage.masks
503+
504+ Rectangle {
505+ visible: UbuntuSettingsFingerprint.debug
506+ color: "red"
507+ opacity: 0.25
508+ x: modelData.x * segmentedImage.implicitWidth
509+ y: modelData.y * segmentedImage.implicitHeight
510+ width: modelData.width * segmentedImage.implicitWidth
511+ height: modelData.height * segmentedImage.implicitHeight
512+
513+ Component.onCompleted: console.log('Scanner mask (x, y, w, h):', x, y, width, height)
514+ }
515+ }
516+}
517
518=== added file 'plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml'
519--- plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml 1970-01-01 00:00:00 +0000
520+++ plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml 2016-06-20 13:58:28 +0000
521@@ -0,0 +1,439 @@
522+/*
523+ * Copyright 2016 Canonical Ltd.
524+ *
525+ * This program is free software; you can redistribute it and/or modify
526+ * it under the terms of the GNU Lesser General Public License as published by
527+ * the Free Software Foundation; version 3.
528+ *
529+ * This program is distributed in the hope that it will be useful,
530+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
531+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
532+ * GNU Lesser General Public License for more details.
533+ *
534+ * You should have received a copy of the GNU Lesser General Public License
535+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
536+ *
537+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
538+ */
539+
540+import QtQuick 2.4
541+import QtQuick.Layouts 1.1
542+import Biometryd 0.0
543+import GSettings 1.0
544+import Ubuntu.Components 1.3
545+import Ubuntu.Components.Popups 1.3
546+import Ubuntu.Settings.Fingerprint 0.1
547+
548+Page {
549+ id: root
550+ objectName: "fingerprintPage"
551+
552+ header: PageHeader {
553+ title: i18n.dtr("ubuntu-settings-components", "Fingerprint ID")
554+ flickable: content
555+ }
556+
557+ property var _ts: Biometryd.defaultDevice.templateStore
558+ property var _enrollmentOperation: null
559+ property var _clearanceOperation: null
560+ property var _removalOperation: null
561+ property var _listOperation: null
562+ property var _setupPage: null
563+ property var _fpInstancePage: null
564+ property var _settings: sysSettings
565+
566+ property Dialog _diag: null
567+ property bool passcodeSet: false
568+
569+ function enroll () {
570+ _enrollmentOperation = _ts.enroll(user);
571+ _enrollmentOperation.start(enrollmentObserver);
572+ }
573+
574+ function cancel () {
575+ if (_enrollmentOperation)
576+ _enrollmentOperation.cancel();
577+ }
578+
579+ function clear() {
580+ _clearanceOperation = _ts.clear(user);
581+ _clearanceOperation.start(clearanceObserver);
582+ }
583+
584+ function removeTemplate(templateId) {
585+ var names = sysSettings.fingerprintNames;
586+ delete names[templateId];
587+ sysSettings.fingerprintNames = names;
588+ }
589+
590+ function renameTemplate(templateId, newName) {
591+ var names = sysSettings.fingerprintNames;
592+ names[templateId] = newName;
593+ sysSettings.fingerprintNames = names;
594+ }
595+
596+ function addTemplate(templateId, name) {
597+ var names = sysSettings.fingerprintNames;
598+ names[templateId] = name;
599+ sysSettings.fingerprintNames = names;
600+ }
601+
602+ function createTemplateName() {
603+ var map = sysSettings.fingerprintNames;
604+ var currentNames = [];
605+ var newName;
606+ for (var k in map) {
607+ if (map.hasOwnProperty(k))
608+ currentNames.push(map[k]);
609+ }
610+
611+ var i = 0;
612+ do {
613+ newName = i18n.dtr("ubuntu-settings-components",
614+ "Finger %1").arg(++i); // Start at 1
615+ } while (currentNames.indexOf(newName) >= 0);
616+ return newName;
617+ }
618+
619+ // Assign names to unnamed fingerprints. This exist because we can't
620+ // guarantee that all fingerprints get names (i.e. enrollment can complete
621+ // after System Settings closes).
622+ function assignNames(templateIds) {
623+ var names = sysSettings.fingerprintNames;
624+ for (var i = 0; i < templateIds.length; i++) {
625+ if ( !(templateIds[i] in names) || !names[templateIds[i]])
626+ names[templateIds[i]] = createTemplateName();
627+ sysSettings.fingerprintNames = names;
628+ }
629+ }
630+
631+ signal requestPasscode()
632+
633+ Component.onCompleted: {
634+ // Start a list operation immediately.
635+ if (Biometryd.available) {
636+ _listOperation = _ts.list(user);
637+ _listOperation.start(listObserver);
638+ }
639+ }
640+
641+ Component.onDestruction: {
642+ if (_enrollmentOperation)
643+ _enrollmentOperation.cancel();
644+
645+ if (_clearanceOperation)
646+ _clearanceOperation.cancel();
647+
648+ if (_removalOperation)
649+ _removalOperation.cancel();
650+
651+ if (_listOperation)
652+ _listOperation.cancel();
653+ }
654+
655+ states: [
656+ State {
657+ name: "noPasscode"
658+ PropertyChanges {
659+ target: setupPasscode
660+ visible: true
661+ }
662+ PropertyChanges {
663+ target: setupFingerprint
664+ enabled: false
665+ }
666+ PropertyChanges {
667+ target: fingerprintsList
668+ enabled: false
669+ }
670+ when: !passcodeSet
671+ },
672+ State {
673+ name: "noScanner"
674+ PropertyChanges {
675+ target: setupFingerprint
676+ enabled: false
677+ }
678+ PropertyChanges {
679+ target: fingerprintsList
680+ visible: false
681+ }
682+ when: !Biometryd.available
683+ }
684+ ]
685+
686+ Flickable {
687+ id: content
688+ anchors.fill: parent
689+ boundsBehavior: (contentHeight > root.height) ?
690+ Flickable.DragAndOvershootBounds :
691+ Flickable.StopAtBounds
692+ contentHeight: contentItem.childrenRect.height
693+
694+ Column {
695+ anchors { left: parent.left; right: parent.right }
696+
697+ Column {
698+ id: setupPasscode
699+ anchors { left: parent.left; right: parent.right }
700+ visible: false
701+
702+ ListItem {
703+ height: setPcodeLayout.height + (divider.visible ? divider.height : 0)
704+ ListItemLayout {
705+ id: setPcodeLayout
706+ title.text: i18n.dtr(
707+ "ubuntu-settings-components",
708+ "Passcode required"
709+ )
710+ subtitle.text: i18n.dtr(
711+ "ubuntu-settings-components",
712+ "You must set a passcode to use fingerprint ID"
713+ )
714+ Button {
715+ objectName: "fingerprintSetPasscodeButton"
716+ onClicked: root.requestPasscode()
717+ text: i18n.dtr(
718+ "ubuntu-settings-components",
719+ "Set Passcode…"
720+ )
721+ }
722+ }
723+ }
724+ }
725+
726+ Column {
727+ id: fingerprints
728+ anchors { left: parent.left; right: parent.right }
729+
730+ Repeater {
731+ id: fingerprintsList
732+ property bool enabled: true
733+ objectName: "fingerprintsList"
734+ model: {
735+ var map = sysSettings.fingerprintNames;
736+ var m = [];
737+ for (var k in map) {
738+ if (map.hasOwnProperty(k)) {
739+ m.push({
740+ templateId: k,
741+ name: map[k]
742+ });
743+ }
744+ }
745+ m.sort(function (a, b) {
746+ if (a.name < b.name) return -1;
747+ if (a.name > b.name) return 1;
748+ if (a.name == b.name) return 0;
749+ });
750+ return m;
751+ }
752+
753+ ListItem {
754+ height: fpLayout.height + (divider.visible ? divider.height : 0)
755+ onClicked: _fpInstancePage = pageStack.push(
756+ Qt.resolvedUrl("Fingerprint.qml"), {
757+ name: modelData.name,
758+ templateId: modelData.templateId
759+ }
760+ )
761+ enabled: fingerprintsList.enabled
762+
763+ ListItemLayout {
764+ id: fpLayout
765+ objectName: "fingerprintInstance-" + index
766+ title.text: modelData.name
767+
768+ ProgressionSlot {}
769+ }
770+ }
771+ }
772+ }
773+
774+ Column {
775+ id: setupFingerprint
776+
777+ anchors { left: parent.left; right: parent.right }
778+ objectName: "fingerprintSetupEntry"
779+ property bool enabled: true
780+ spacing: units.gu(2)
781+
782+ ListItem {
783+ height: addFpLayout.height + (divider.visible ? divider.height : 0)
784+ onClicked: {
785+ _setupPage = pageStack.push(Qt.resolvedUrl("Setup.qml"));
786+ root.enroll();
787+ }
788+ enabled: parent.enabled
789+
790+ ListItemLayout {
791+ id: addFpLayout
792+ objectName: "fingerprintAddListItemLayout"
793+ title.text: i18n.dtr(
794+ "ubuntu-settings-components",
795+ "Add fingerprint"
796+ )
797+
798+ ProgressionSlot {}
799+ }
800+ }
801+
802+ Button {
803+ anchors.horizontalCenter: parent.horizontalCenter
804+ enabled: fingerprintsList.model.length > 0
805+ objectName: "fingerprintRemoveAllButton"
806+ onClicked: _diag = PopupUtils.open(removeAllAlert)
807+ text: i18n.dtr("ubuntu-settings-components",
808+ "Remove All…")
809+ }
810+ }
811+ }
812+ }
813+
814+ Component {
815+ id: removeAllAlert
816+
817+ Dialog {
818+ id: removeAllAlertDialog
819+
820+ objectName: "fingerprintRemoveAllDialog"
821+ text: i18n.dtr(
822+ "ubuntu-settings-components",
823+ "Are you sure you want to forget all stored fingerprints?"
824+ )
825+
826+ RowLayout {
827+ anchors { left: parent.left; right: parent.right }
828+ spacing: units.gu(2)
829+
830+ Button {
831+ onClicked: PopupUtils.close(removeAllAlertDialog)
832+ text: i18n.dtr("ubuntu-settings-components", "Cancel")
833+ Layout.fillWidth: true
834+ }
835+
836+ Button {
837+ objectName: "fingerprintRemoveAllConfirmationButton"
838+ onClicked: root.clear()
839+ text: i18n.dtr("ubuntu-settings-components", "Remove")
840+ Layout.fillWidth: true
841+ }
842+ }
843+ }
844+ }
845+
846+ Component {
847+ id: fingerprintReaderBroken
848+
849+ Dialog {
850+ id: fingerprintReaderBrokenDialog
851+ objectName: "fingerprintReaderBrokenDialog"
852+ text: i18n.dtr("ubuntu-settings-components",
853+ "Sorry, the reader doesn’t seem to be working.")
854+
855+ Button {
856+ objectName: "fingerprintReaderBrokenDialogOK"
857+ onClicked: PopupUtils.close(fingerprintReaderBrokenDialog)
858+ text: i18n.dtr("ubuntu-settings-components", "OK")
859+ }
860+ }
861+ }
862+
863+ Connections {
864+ target: _setupPage
865+ onEnroll: root.enroll()
866+ onCancel: root.cancel()
867+ }
868+
869+ Connections {
870+ target: _fpInstancePage
871+
872+ onRequestDeletion: {
873+ _removalOperation = _ts.remove(user, templateId);
874+ _removalOperation.start(removalObserver);
875+ }
876+ onRequestRename: renameTemplate(templateId, name)
877+ }
878+
879+ Observer {
880+ id: enrollmentObserver
881+ objectName: "enrollmentObserver"
882+ onFailed: {
883+ if (_setupPage)
884+ _setupPage.enrollmentFailed(reason);
885+ _enrollmentOperation = null;
886+ console.error("Enrollment failed", reason);
887+ }
888+ onCanceled: _enrollmentOperation = null
889+ onProgressed: _setupPage.enrollmentProgressed(percent, details)
890+ onSucceeded: {
891+ if (!(result in sysSettings.fingerprintNames))
892+ root.addTemplate(result, root.createTemplateName());
893+ if (_setupPage)
894+ _setupPage.enrollmentCompleted();
895+ _enrollmentOperation = null;
896+ }
897+ }
898+
899+ Observer {
900+ id: clearanceObserver
901+ objectName: "clearanceObserver"
902+ onFailed: {
903+ _clearanceOperation = null;
904+ if (_diag) PopupUtils.close(_diag);
905+ _diag = PopupUtils.open(fingerprintReaderBroken);
906+ console.error("Biometry clearance failed:", reason);
907+ }
908+ onCanceled: _clearanceOperation = null
909+ onSucceeded: {
910+ _clearanceOperation = null;
911+ if (_diag) PopupUtils.close(_diag);
912+ sysSettings.fingerprintNames = {};
913+ }
914+ }
915+
916+ Observer {
917+ id: removalObserver
918+ objectName: "removalObserver"
919+ onFailed: {
920+ _removalOperation = null;
921+ if (_fpInstancePage)
922+ _fpInstancePage.deletionFailed()
923+ console.error("Biometryd template deletion failed:", reason);
924+ }
925+ onCanceled: _removalOperation = null
926+ onSucceeded: {
927+ _removalOperation = null;
928+ if (pageStack.currentPage === _fpInstancePage)
929+ pageStack.pop();
930+ root.removeTemplate(result);
931+ }
932+ }
933+
934+ Observer {
935+ id: listObserver
936+ objectName: "listObserver"
937+ onFailed: {
938+ _listOperation = null;
939+ if (_diag) PopupUtils.close(_diag);
940+ _diag = PopupUtils.open(fingerprintReaderBroken);
941+ console.error("Biometryd list failed:", reason);
942+ }
943+ onCanceled: _listOperation = null
944+ onSucceeded: {
945+ _listOperation = null;
946+ root.assignNames(result);
947+ }
948+ }
949+
950+ User {
951+ id: user
952+ uid: UbuntuSettingsFingerprint.uid
953+ }
954+
955+ GSettings {
956+ id: sysSettings
957+ objectName: "systemSettings"
958+ schema.id: "com.ubuntu.touch.system"
959+ }
960+}
961
962=== added file 'plugins/Ubuntu/Settings/Fingerprint/SegmentBoundingBoxes.qml'
963--- plugins/Ubuntu/Settings/Fingerprint/SegmentBoundingBoxes.qml 1970-01-01 00:00:00 +0000
964+++ plugins/Ubuntu/Settings/Fingerprint/SegmentBoundingBoxes.qml 2016-06-20 13:58:28 +0000
965@@ -0,0 +1,81 @@
966+/*
967+ * Copyright 2016 Canonical Ltd.
968+ *
969+ * This program is free software; you can redistribute it and/or modify
970+ * it under the terms of the GNU Lesser General Public License as published by
971+ * the Free Software Foundation; version 3.
972+ *
973+ * This program is distributed in the hope that it will be useful,
974+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
975+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
976+ * GNU Lesser General Public License for more details.
977+ *
978+ * You should have received a copy of the GNU Lesser General Public License
979+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
980+ *
981+ * Authored by Florian Boucault <florian.boucault@canonical.com>
982+ */
983+
984+import QtQuick 2.4
985+
986+QtObject {
987+ id: segmentBoundingBoxes
988+
989+ property string source
990+ onSourceChanged: parseBoundingBoxes(source)
991+
992+ property var boundingBoxes: []
993+ property real width
994+ property real height
995+ property int count: boundingBoxes.length
996+
997+ // The API cannot be used reliably before this signal has been emitted.
998+ signal ready()
999+
1000+ function parseBoundingBoxes(source) {
1001+ var xhr = new XMLHttpRequest;
1002+ xhr.open("GET", source);
1003+ xhr.onreadystatechange = function() {
1004+ if (xhr.readyState == XMLHttpRequest.DONE) {
1005+ var b = [];
1006+ var json = JSON.parse(xhr.responseText);
1007+ boundingBoxes = json["boxes"];
1008+ width = json["width"];
1009+ height = json["height"];
1010+ ready();
1011+ }
1012+ }
1013+ xhr.send();
1014+ }
1015+
1016+ function intersects(box1, box2) {
1017+ // TODO: optimize
1018+ var x11 = box1[0];
1019+ var y11 = box1[1];
1020+ var x12 = box1[0] + box1[2];
1021+ var y12 = box1[1] + box1[3];
1022+ var x21 = box2[0];
1023+ var y21 = box2[1];
1024+ var x22 = box2[0] + box2[2];
1025+ var y22 = box2[1] + box2[3];
1026+ var x_overlap = Math.max(0, Math.min(x12,x22) - Math.max(x11,x21));
1027+ var y_overlap = Math.max(0, Math.min(y12,y22) - Math.max(y11,y21));
1028+ return (x_overlap / Math.min(box1[2], box2[2]) > 0.25
1029+ && y_overlap / Math.min(box1[3], box2[3]) > 0.25);
1030+ }
1031+
1032+ function computeIntersections(hitBox) {
1033+ var absoluteHitBox = [hitBox[0] * width, hitBox[1] * height,
1034+ hitBox[2] * width, hitBox[3] * height];
1035+
1036+ var intersections = [];
1037+ for (var i in boundingBoxes) {
1038+ var boundingBox = boundingBoxes[i];
1039+ if (intersects(absoluteHitBox, boundingBox)) {
1040+ intersections.push(i);
1041+ }
1042+ }
1043+
1044+ return intersections;
1045+ }
1046+}
1047
1048=== added file 'plugins/Ubuntu/Settings/Fingerprint/SegmentRenderer.qml'
1049--- plugins/Ubuntu/Settings/Fingerprint/SegmentRenderer.qml 1970-01-01 00:00:00 +0000
1050+++ plugins/Ubuntu/Settings/Fingerprint/SegmentRenderer.qml 2016-06-20 13:58:28 +0000
1051@@ -0,0 +1,95 @@
1052+/*
1053+ * Copyright 2016 Canonical Ltd.
1054+ *
1055+ * This program is free software; you can redistribute it and/or modify
1056+ * it under the terms of the GNU Lesser General Public License as published by
1057+ * the Free Software Foundation; version 3.
1058+ *
1059+ * This program is distributed in the hope that it will be useful,
1060+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1061+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1062+ * GNU Lesser General Public License for more details.
1063+ *
1064+ * You should have received a copy of the GNU Lesser General Public License
1065+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1066+ *
1067+ * Authored by Florian Boucault <florian.boucault@canonical.com>
1068+ */
1069+
1070+import QtQuick 2.4
1071+import Ubuntu.Components 1.3
1072+
1073+ShaderEffect {
1074+ id: segmentRenderer
1075+
1076+ implicitWidth: texture.width
1077+ implicitHeight: texture.height
1078+
1079+ function animate(segments) {
1080+ for (var i in segments) {
1081+ var progressPixel = progressTexture.children[segments[i]];
1082+ if (progressPixel.progress == 0.0) {
1083+ progressPixel.animation.start();
1084+ }
1085+ }
1086+ }
1087+
1088+ property string source
1089+ property int segmentsCount
1090+ property color backgroundColor: theme.palette.normal.base
1091+ property color fillColor: theme.palette.normal.activity
1092+ property Image texture: Image {
1093+ source: segmentRenderer.source
1094+ }
1095+ property var progressTexture: progressTexture
1096+ property int progressTextureSize: progressTexture.size
1097+
1098+ fragmentShader: "
1099+ varying mediump vec2 qt_TexCoord0;
1100+ uniform lowp float qt_Opacity;
1101+ uniform lowp vec4 backgroundColor;
1102+ uniform lowp vec4 fillColor;
1103+ uniform lowp sampler2D texture;
1104+ uniform lowp sampler2D progressTexture;
1105+ uniform lowp int progressTextureSize;
1106+
1107+ void main() {
1108+ lowp vec4 p = texture2D(texture, qt_TexCoord0);
1109+ lowp float segment = p.r * 255.0;
1110+ lowp vec4 segmentProgress = step(0.9, segment) * texture2D(progressTexture, vec2((segment - 1.0 + 0.5) / float(progressTextureSize), 0.5));
1111+ lowp vec4 color = mix(fillColor, backgroundColor, step(segmentProgress.r, p.g));
1112+ gl_FragColor = vec4(color.rgb, 1.0) * p.b * qt_Opacity;
1113+ }
1114+ "
1115+
1116+ // TODO: not the most efficient; could be replaced with an image provider
1117+ Row {
1118+ id: progressTexture
1119+
1120+ property int size: 128
1121+ layer.enabled: true
1122+ layer.sourceRect: Qt.rect(0, 0, size, 1)
1123+ layer.textureSize: Qt.size(size, 1)
1124+ layer.wrapMode: ShaderEffectSource.ClampToEdge
1125+ visible: false
1126+
1127+ Repeater {
1128+ model: segmentRenderer.segmentsCount
1129+ Rectangle {
1130+ id: progressPixel
1131+ width: 1
1132+ height: 1
1133+ color: Qt.rgba(progress, progress, progress, 1.0)
1134+ property real progress
1135+ property NumberAnimation animation: NumberAnimation {
1136+ target: progressPixel
1137+ property: "progress"
1138+ from: 0.0
1139+ to: 1.0
1140+ duration: UbuntuAnimation.SleepyDuration
1141+ easing: UbuntuAnimation.StandardEasing
1142+ }
1143+ }
1144+ }
1145+ }
1146+}
1147
1148=== added file 'plugins/Ubuntu/Settings/Fingerprint/SegmentedImage.qml'
1149--- plugins/Ubuntu/Settings/Fingerprint/SegmentedImage.qml 1970-01-01 00:00:00 +0000
1150+++ plugins/Ubuntu/Settings/Fingerprint/SegmentedImage.qml 2016-06-20 13:58:28 +0000
1151@@ -0,0 +1,52 @@
1152+/*
1153+ * Copyright 2016 Canonical Ltd.
1154+ *
1155+ * This program is free software; you can redistribute it and/or modify
1156+ * it under the terms of the GNU Lesser General Public License as published by
1157+ * the Free Software Foundation; version 3.
1158+ *
1159+ * This program is distributed in the hope that it will be useful,
1160+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1161+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1162+ * GNU Lesser General Public License for more details.
1163+ *
1164+ * You should have received a copy of the GNU Lesser General Public License
1165+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1166+ *
1167+ * Authored by Florian Boucault <florian.boucault@canonical.com>
1168+ */
1169+
1170+import QtQuick 2.4
1171+
1172+Item {
1173+ id: segImg
1174+ property alias textureSource: segmentRenderer.source
1175+ property alias boxesSource: segmentBoundingBoxes.source
1176+
1177+ implicitWidth: segmentRenderer.implicitWidth
1178+ implicitHeight: segmentRenderer.implicitHeight
1179+
1180+ // Ready to enroll.
1181+ signal ready()
1182+
1183+ function enrollMasks(masks) {
1184+ if (masks && masks.length) {
1185+ var segments = [];
1186+ masks.forEach(function (mask, i) {
1187+ var hitBox = [mask.x, mask.y, mask.width, mask.height];
1188+ segments = segments.concat(segmentBoundingBoxes.computeIntersections(hitBox));
1189+ });
1190+ segmentRenderer.animate(segments);
1191+ }
1192+ }
1193+
1194+ SegmentRenderer {
1195+ id: segmentRenderer
1196+ segmentsCount: segmentBoundingBoxes.count
1197+ }
1198+
1199+ SegmentBoundingBoxes {
1200+ id: segmentBoundingBoxes
1201+ onReady: segImg.ready()
1202+ }
1203+}
1204
1205=== added file 'plugins/Ubuntu/Settings/Fingerprint/Setup.qml'
1206--- plugins/Ubuntu/Settings/Fingerprint/Setup.qml 1970-01-01 00:00:00 +0000
1207+++ plugins/Ubuntu/Settings/Fingerprint/Setup.qml 2016-06-20 13:58:28 +0000
1208@@ -0,0 +1,387 @@
1209+/*
1210+ * Copyright 2016 Canonical Ltd.
1211+ *
1212+ * This program is free software; you can redistribute it and/or modify
1213+ * it under the terms of the GNU Lesser General Public License as published by
1214+ * the Free Software Foundation; version 3.
1215+ *
1216+ * This program is distributed in the hope that it will be useful,
1217+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1218+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1219+ * GNU Lesser General Public License for more details.
1220+ *
1221+ * You should have received a copy of the GNU Lesser General Public License
1222+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1223+ *
1224+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
1225+ */
1226+
1227+import Biometryd 0.0
1228+import QtQuick 2.4
1229+import QtQuick.Layouts 1.1
1230+import Ubuntu.Components 1.3
1231+import Ubuntu.Settings.Fingerprint 0.1
1232+
1233+Page {
1234+ id: root
1235+
1236+ objectName: "fingerprintSetupPage"
1237+
1238+ signal enroll()
1239+ signal cancel()
1240+
1241+ function enrollmentFailed(error) {
1242+ root.state = "failed";
1243+ }
1244+
1245+ function enrollmentCompleted() {
1246+ root.state = "done";
1247+ }
1248+
1249+ function enrollmentProgressed(progress, hints) {
1250+ root.state = "reading";
1251+ imageDefault.masks = hints[FingerprintReader.masks];
1252+ progressLabel.progress = 100 * progress;
1253+ directionContainer.direction = hints[FingerprintReader.suggestedNextDirection] || FingerprintReader.NotAvailable;
1254+ }
1255+
1256+ states: [
1257+ State {
1258+ name: ""
1259+ StateChangeScript {
1260+ script: statusLabel.setText(statusLabel.initialText)
1261+ }
1262+ },
1263+ State {
1264+ name: "reading"
1265+ StateChangeScript {
1266+ script: statusLabel.setText(
1267+ i18n.dtr("ubuntu-settings-components",
1268+ "Swipe your finger repeatedly over the reader.")
1269+ )
1270+ }
1271+ PropertyChanges {
1272+ target: imageDefault
1273+ opacity: 1
1274+ }
1275+ PropertyChanges {
1276+ target: progressLabel
1277+ opacity: 1
1278+ }
1279+ },
1280+ State {
1281+ name: "longer"
1282+ StateChangeScript {
1283+ script: statusLabel.setText(
1284+ i18n.dtr("ubuntu-settings-components",
1285+ "Keep your finger on the reader for longer.")
1286+ )
1287+ }
1288+ },
1289+ State {
1290+ name: "failed"
1291+ PropertyChanges {
1292+ target: imageDefault
1293+ opacity: 0
1294+ }
1295+ PropertyChanges {
1296+ target: imageFailed
1297+ opacity: 1
1298+ }
1299+ PropertyChanges {
1300+ target: cancelButton
1301+ text: i18n.dtr("ubuntu-settings-components", "Back");
1302+ }
1303+ PropertyChanges {
1304+ target: doneButton
1305+ visible: false
1306+ }
1307+ StateChangeScript {
1308+ script: statusLabel.setText(
1309+ i18n.dtr("ubuntu-settings-components",
1310+ "Sorry, the reader doesn’t seem to be working."),
1311+ true // No animation
1312+ )
1313+ }
1314+ StateChangeScript {
1315+ script: imageFailed.start()
1316+ }
1317+ PropertyChanges {
1318+ target: directionContainer
1319+ opacity: 0
1320+ }
1321+ },
1322+ State {
1323+ name: "done"
1324+ PropertyChanges {
1325+ target: imageDefault
1326+ opacity: 0
1327+ }
1328+ PropertyChanges {
1329+ target: imageDone
1330+ opacity: 1
1331+ }
1332+ PropertyChanges {
1333+ target: cancelButton
1334+ visible: false
1335+ }
1336+ StateChangeScript {
1337+ script: statusLabel.setText(
1338+ i18n.dtr("ubuntu-settings-components", "All done!"),
1339+ true // No animation
1340+ )
1341+ }
1342+ PropertyChanges {
1343+ target: doneButton
1344+ enabled: true
1345+ text: i18n.dtr("ubuntu-settings-components", "OK")
1346+ }
1347+ StateChangeScript {
1348+ script: imageDone.start()
1349+ }
1350+ PropertyChanges {
1351+ target: directionContainer
1352+ opacity: 0
1353+ }
1354+ }
1355+ ]
1356+
1357+ header: PageHeader {
1358+ visible: false
1359+ }
1360+
1361+ Item {
1362+ anchors.fill: parent
1363+
1364+ Item {
1365+ id: fingerprintBox
1366+ anchors.centerIn: parent
1367+ width: units.gu(26)
1368+ height: units.gu(29)
1369+
1370+ Item {
1371+ id: imageContainer
1372+ anchors.centerIn: parent
1373+ width: imageDefault.implicitWidth
1374+ height: imageDefault.implicitHeight
1375+
1376+ // Default image.
1377+ FingerprintVisual {
1378+ id: imageDefault
1379+ objectName: "fingerprintDefaultVisual"
1380+ anchors.centerIn: parent
1381+
1382+ Behavior on opacity { UbuntuNumberAnimation {
1383+ duration: UbuntuAnimation.SlowDuration
1384+ easing: UbuntuAnimation.StandardEasing
1385+ }}
1386+ }
1387+
1388+ // Failed image.
1389+ CircularSegment {
1390+ id: imageFailed
1391+ objectName: "fingerprintFailedVisual"
1392+ opacity: 0
1393+ color: "#ED3146"
1394+ width: directionContainer.width - units.dp(3)
1395+
1396+ anchors.centerIn: parent
1397+
1398+ function start () {
1399+ failAngstopAnim.start();
1400+ failThichAnim.start();
1401+ }
1402+
1403+ NumberAnimation on angleStop {
1404+ id: failAngstopAnim
1405+ running: false
1406+ from: 0
1407+ to: 360
1408+ duration: UbuntuAnimation.SlowDuration
1409+ easing: UbuntuAnimation.StandardEasing
1410+ }
1411+
1412+ NumberAnimation on thickness {
1413+ id: failThichAnim
1414+ running: false
1415+ from: 0
1416+ to: units.dp(3)
1417+ duration: UbuntuAnimation.SlowDuration
1418+ easing: UbuntuAnimation.StandardEasing
1419+ }
1420+
1421+ Icon {
1422+ name: "close"
1423+ color: "#ED3146"
1424+ width: units.gu(18)
1425+ anchors.centerIn: parent
1426+ }
1427+
1428+ Behavior on opacity { UbuntuNumberAnimation {
1429+ duration: UbuntuAnimation.SlowDuration
1430+ easing: UbuntuAnimation.StandardEasing
1431+ }}
1432+ }
1433+
1434+ // Done image.
1435+ CircularSegment {
1436+ id: imageDone
1437+ objectName: "fingerprintDoneVisual"
1438+ opacity: 0
1439+ width: directionContainer.width - units.dp(3)
1440+
1441+ anchors.centerIn: parent
1442+
1443+ function start () {
1444+ angstopAnim.start();
1445+ thickAnim.start();
1446+ }
1447+
1448+ NumberAnimation on angleStop {
1449+ id: angstopAnim
1450+ running: false
1451+ from: 0
1452+ to: 360
1453+ duration: UbuntuAnimation.SlowDuration
1454+ easing: UbuntuAnimation.StandardEasing
1455+ }
1456+
1457+ NumberAnimation on thickness {
1458+ id: thickAnim
1459+ running: false
1460+ from: 0
1461+ to: units.dp(3)
1462+ duration: UbuntuAnimation.SlowDuration
1463+ easing: UbuntuAnimation.StandardEasing
1464+ }
1465+
1466+ Icon {
1467+ name: "tick"
1468+ color: "#3EB34F"
1469+ width: units.gu(18)
1470+ anchors.centerIn: parent
1471+ }
1472+
1473+ Behavior on opacity { UbuntuNumberAnimation {
1474+ duration: UbuntuAnimation.SlowDuration
1475+ easing: UbuntuAnimation.StandardEasing
1476+ }}
1477+ }
1478+
1479+ DirectionVisual {
1480+ id: directionContainer
1481+ objectName: "fingerprintDirectionVisual"
1482+ anchors.centerIn: parent
1483+
1484+ width: Math.sqrt(
1485+ imageContainer.width*imageContainer.width
1486+ + imageContainer.height*imageContainer.height
1487+ )
1488+ height: width
1489+ }
1490+ }
1491+ }
1492+
1493+ StatusLabel {
1494+ id: statusLabel
1495+ anchors {
1496+ left: parent.left
1497+ leftMargin: units.gu(2.9)
1498+ right: parent.right
1499+ rightMargin: units.gu(2.9)
1500+ top: parent.top
1501+ topMargin: units.gu(5)
1502+ }
1503+ initialText: i18n.dtr("ubuntu-settings-components",
1504+ "Swipe your finger over the reader.")
1505+ objectName: "fingerprintStatusLabel"
1506+ }
1507+
1508+
1509+ Label {
1510+ id: progressLabel
1511+ objectName: "fingerprintProgressLabel"
1512+ property int progress: 0
1513+ anchors {
1514+ top: fingerprintBox.bottom
1515+ topMargin: units.gu(1.5)
1516+ horizontalCenter: parent.horizontalCenter
1517+ }
1518+ text: i18n.dtr("ubuntu-settings-components", "%1%").arg((progress).toFixed());
1519+ opacity: 0
1520+ horizontalAlignment: Text.AlignHCenter
1521+ fontSize: "large"
1522+ color: theme.palette.normal.backgroundTertiaryText
1523+
1524+ Behavior on opacity { UbuntuNumberAnimation {} }
1525+ Behavior on progress {
1526+ NumberAnimation {
1527+ duration: UbuntuAnimation.SlowDuration
1528+ easing: UbuntuAnimation.StandardEasing
1529+ }
1530+ }
1531+ }
1532+
1533+ Rectangle {
1534+ id: actions
1535+
1536+ anchors {
1537+ left: parent.left
1538+ right: parent.right
1539+ bottom: parent.bottom
1540+ }
1541+
1542+ // Color and height values are copied from the Wizard.
1543+ color: "#f5f5f5"
1544+ height: units.gu(5)
1545+
1546+ AbstractButton {
1547+ id: cancelButton
1548+ property alias text: cancelButtonText.text
1549+ objectName: "fingerprintSetupCancelButton"
1550+ anchors {
1551+ left: parent.left
1552+ leftMargin: units.gu(3)
1553+ verticalCenter: parent.verticalCenter
1554+ }
1555+ height: parent.height
1556+ width: units.gu(10)
1557+ onClicked: {
1558+ root.cancel();
1559+ pageStack.pop();
1560+ }
1561+
1562+ Label {
1563+ id: cancelButtonText
1564+ anchors.verticalCenter: parent.verticalCenter
1565+ text: i18n.dtr("ubuntu-settings-components", "Cancel")
1566+ }
1567+ }
1568+
1569+ AbstractButton {
1570+ id: doneButton
1571+ property alias text: doneButtonText.text
1572+ objectName: "fingerprintSetupDoneButton"
1573+ anchors {
1574+ right: parent.right
1575+ rightMargin: units.gu(3)
1576+ verticalCenter: parent.verticalCenter
1577+ }
1578+ enabled: false
1579+ height: parent.height
1580+ width: units.gu(10)
1581+ onClicked: pageStack.pop()
1582+
1583+ Label {
1584+ id: doneButtonText
1585+ anchors {
1586+ verticalCenter: parent.verticalCenter
1587+ right: parent.right
1588+ }
1589+ font.bold: parent.enabled
1590+ text: i18n.dtr("ubuntu-settings-components", "Next")
1591+ }
1592+ }
1593+ }
1594+ }
1595+}
1596
1597=== added file 'plugins/Ubuntu/Settings/Fingerprint/StatusLabel.qml'
1598--- plugins/Ubuntu/Settings/Fingerprint/StatusLabel.qml 1970-01-01 00:00:00 +0000
1599+++ plugins/Ubuntu/Settings/Fingerprint/StatusLabel.qml 2016-06-20 13:58:28 +0000
1600@@ -0,0 +1,84 @@
1601+/*
1602+ * Copyright 2016 Canonical Ltd.
1603+ *
1604+ * This program is free software; you can redistribute it and/or modify
1605+ * it under the terms of the GNU Lesser General Public License as published by
1606+ * the Free Software Foundation; version 3.
1607+ *
1608+ * This program is distributed in the hope that it will be useful,
1609+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1610+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1611+ * GNU Lesser General Public License for more details.
1612+ *
1613+ * You should have received a copy of the GNU Lesser General Public License
1614+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1615+ *
1616+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
1617+ */
1618+
1619+import QtQuick 2.4
1620+import Ubuntu.Components 1.3
1621+
1622+Item {
1623+ id: root
1624+
1625+ property string initialText
1626+ property int origX: 0
1627+ readonly property alias text: label.text
1628+
1629+ signal slideStarted()
1630+ signal slideCompleted()
1631+
1632+ Component.onCompleted: origX = label.x
1633+
1634+ function setText(text, noAnimation) {
1635+ if (noAnimation === true) {
1636+ label.text = text;
1637+ return;
1638+ }
1639+
1640+ function outStoppedHandler () {
1641+ label.text = text;
1642+ label.x = units.gu(50)
1643+ inAnim.start();
1644+ outAnim.stopped.disconnect(outStoppedHandler);
1645+ }
1646+ outAnim.stopped.connect(outStoppedHandler);
1647+ outAnim.start();
1648+ }
1649+
1650+ Label {
1651+ id: label
1652+
1653+ font.pixelSize: units.gu(3.3)
1654+ horizontalAlignment: Text.AlignLeft
1655+ height: units.gu(4)
1656+ text: initialText
1657+ width: parent.width
1658+ wrapMode: Text.WordWrap
1659+ }
1660+
1661+ NumberAnimation {
1662+ id: outAnim
1663+
1664+ alwaysRunToEnd: true
1665+ duration: UbuntuAnimation.FastDuration
1666+ easing: UbuntuAnimation.StandardEasing
1667+ onStarted: root.slideStarted()
1668+ property: "x"
1669+ target: label
1670+ to: -units.gu(50)
1671+ }
1672+
1673+ NumberAnimation {
1674+ id: inAnim
1675+
1676+ alwaysRunToEnd: true
1677+ duration: UbuntuAnimation.FastDuration
1678+ easing: UbuntuAnimation.StandardEasing
1679+ onStopped: root.slideCompleted()
1680+ property: "x"
1681+ target: label
1682+ to: root.origX
1683+ }
1684+}
1685
1686=== added directory 'plugins/Ubuntu/Settings/Fingerprint/assets'
1687=== added file 'plugins/Ubuntu/Settings/Fingerprint/assets.qrc'
1688--- plugins/Ubuntu/Settings/Fingerprint/assets.qrc 1970-01-01 00:00:00 +0000
1689+++ plugins/Ubuntu/Settings/Fingerprint/assets.qrc 2016-06-20 13:58:28 +0000
1690@@ -0,0 +1,11 @@
1691+<!DOCTYPE RCC><RCC version="1.0">
1692+<qresource>
1693+ <file>assets/shape-up@27.png</file>
1694+ <file>assets/shape-up@27.sci</file>
1695+ <file>assets/shape-down@27.png</file>
1696+ <file>assets/shape-down@27.sci</file>
1697+
1698+ <file>assets/fingerprint_segmented@27.png</file>
1699+ <file>assets/fingerprint_boxes.json</file>
1700+</qresource>
1701+</RCC>
1702
1703=== added file 'plugins/Ubuntu/Settings/Fingerprint/assets/fingerprint_boxes.json'
1704--- plugins/Ubuntu/Settings/Fingerprint/assets/fingerprint_boxes.json 1970-01-01 00:00:00 +0000
1705+++ plugins/Ubuntu/Settings/Fingerprint/assets/fingerprint_boxes.json 2016-06-20 13:58:28 +0000
1706@@ -0,0 +1,1 @@
1707+{"width": 451, "boxes": [[291, 515, 104, 50], [269, 510, 96, 34], [227, 506, 62, 16], [198, 505, 72, 60], [144, 498, 46, 67], [200, 467, 133, 32], [214, 449, 87, 28], [67, 432, 25, 104], [396, 420, 31, 89], [177, 395, 22, 103], [133, 390, 15, 96], [266, 375, 8, 31], [1, 356, 7, 42], [336, 355, 27, 114], [221, 350, 95, 105], [243, 323, 17, 106], [155, 317, 68, 248], [110, 317, 43, 243], [22, 314, 12, 155], [199, 310, 13, 127], [302, 296, 83, 223], [276, 295, 20, 136], [311, 275, 30, 189], [177, 266, 8, 114], [88, 263, 34, 287], [221, 249, 9, 86], [441, 238, 9, 169], [110, 231, 9, 70], [44, 226, 16, 280], [310, 225, 8, 181], [199, 223, 53, 86], [370, 217, 37, 288], [249, 208, 25, 153], [177, 201, 61, 49], [281, 195, 15, 85], [133, 183, 16, 196], [177, 178, 96, 29], [155, 167, 35, 134], [345, 166, 18, 173], [200, 156, 81, 31], [1, 149, 17, 192], [386, 145, 18, 60], [305, 142, 36, 118], [66, 139, 26, 277], [149, 134, 168, 77], [111, 132, 45, 85], [88, 130, 36, 120], [350, 118, 35, 162], [165, 111, 134, 28], [262, 92, 85, 64], [414, 91, 35, 133], [129, 89, 119, 36], [22, 88, 42, 211], [92, 67, 256, 62], [47, 64, 75, 149], [349, 47, 80, 360], [132, 44, 257, 90], [13, 41, 56, 95], [66, 22, 273, 60], [198, 1, 215, 76], [74, 1, 109, 39]], "height": 566}
1708
1709=== added file 'plugins/Ubuntu/Settings/Fingerprint/assets/fingerprint_segmented@27.png'
1710Binary files plugins/Ubuntu/Settings/Fingerprint/assets/fingerprint_segmented@27.png 1970-01-01 00:00:00 +0000 and plugins/Ubuntu/Settings/Fingerprint/assets/fingerprint_segmented@27.png 2016-06-20 13:58:28 +0000 differ
1711=== added file 'plugins/Ubuntu/Settings/Fingerprint/assets/shape-down@27.png'
1712Binary files plugins/Ubuntu/Settings/Fingerprint/assets/shape-down@27.png 1970-01-01 00:00:00 +0000 and plugins/Ubuntu/Settings/Fingerprint/assets/shape-down@27.png 2016-06-20 13:58:28 +0000 differ
1713=== added file 'plugins/Ubuntu/Settings/Fingerprint/assets/shape-down@27.sci'
1714--- plugins/Ubuntu/Settings/Fingerprint/assets/shape-down@27.sci 1970-01-01 00:00:00 +0000
1715+++ plugins/Ubuntu/Settings/Fingerprint/assets/shape-down@27.sci 2016-06-20 13:58:28 +0000
1716@@ -0,0 +1,7 @@
1717+border.top: 222
1718+border.right: 222
1719+border.bottom: 222
1720+border.left: 222
1721+horizontalTileMode: Round
1722+verticalTileMode: Round
1723+source: "shape-down@27.png"
1724
1725=== added file 'plugins/Ubuntu/Settings/Fingerprint/assets/shape-up@27.png'
1726Binary files plugins/Ubuntu/Settings/Fingerprint/assets/shape-up@27.png 1970-01-01 00:00:00 +0000 and plugins/Ubuntu/Settings/Fingerprint/assets/shape-up@27.png 2016-06-20 13:58:28 +0000 differ
1727=== added file 'plugins/Ubuntu/Settings/Fingerprint/assets/shape-up@27.sci'
1728--- plugins/Ubuntu/Settings/Fingerprint/assets/shape-up@27.sci 1970-01-01 00:00:00 +0000
1729+++ plugins/Ubuntu/Settings/Fingerprint/assets/shape-up@27.sci 2016-06-20 13:58:28 +0000
1730@@ -0,0 +1,7 @@
1731+border.top: 260
1732+border.right: 260
1733+border.bottom: 260
1734+border.left: 260
1735+horizontalTileMode: Round
1736+verticalTileMode: Round
1737+source: "shape-up@27.png"
1738
1739=== added file 'plugins/Ubuntu/Settings/Fingerprint/plugin.cpp'
1740--- plugins/Ubuntu/Settings/Fingerprint/plugin.cpp 1970-01-01 00:00:00 +0000
1741+++ plugins/Ubuntu/Settings/Fingerprint/plugin.cpp 2016-06-20 13:58:28 +0000
1742@@ -0,0 +1,35 @@
1743+/*
1744+ * Copyright (C) 2016 Canonical, Ltd.
1745+ *
1746+ * This program is free software; you can redistribute it and/or modify
1747+ * it under the terms of the GNU Lesser General Public License as published by
1748+ * the Free Software Foundation; version 3.
1749+ *
1750+ * This program is distributed in the hope that it will be useful,
1751+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1752+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1753+ * GNU Lesser General Public License for more details.
1754+ *
1755+ * You should have received a copy of the GNU Lesser General Public License
1756+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1757+ */
1758+
1759+#include "plugin.h"
1760+#include "ubuntusettingsfingerprint.h"
1761+
1762+#include <QtQml/qqml.h>
1763+
1764+static QObject* fp_singletonprovider(QQmlEngine *engine, QJSEngine *scriptEngine)
1765+{
1766+ Q_UNUSED(engine)
1767+ Q_UNUSED(scriptEngine)
1768+
1769+ return new UbuntuSettingsFingerprint;
1770+}
1771+
1772+void UbuntuSettingsFingerprintPlugin::registerTypes(const char *uri)
1773+{
1774+ qmlRegisterSingletonType<UbuntuSettingsFingerprint>(
1775+ uri, 0, 1, "UbuntuSettingsFingerprint", fp_singletonprovider
1776+ );
1777+}
1778
1779=== added file 'plugins/Ubuntu/Settings/Fingerprint/plugin.h'
1780--- plugins/Ubuntu/Settings/Fingerprint/plugin.h 1970-01-01 00:00:00 +0000
1781+++ plugins/Ubuntu/Settings/Fingerprint/plugin.h 2016-06-20 13:58:28 +0000
1782@@ -0,0 +1,30 @@
1783+/*
1784+ * Copyright (C) 2016 Canonical, Ltd.
1785+ *
1786+ * This program is free software; you can redistribute it and/or modify
1787+ * it under the terms of the GNU Lesser General Public License as published by
1788+ * the Free Software Foundation; version 3.
1789+ *
1790+ * This program is distributed in the hope that it will be useful,
1791+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1792+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1793+ * GNU Lesser General Public License for more details.
1794+ *
1795+ * You should have received a copy of the GNU Lesser General Public License
1796+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1797+ */
1798+
1799+#ifndef UBUNTUSETTINGSFINGERPRINT_PLUGIN_H
1800+#define UBUNTUSETTINGSFINGERPRINT_PLUGIN_H
1801+
1802+#include <QtQml/QQmlExtensionPlugin>
1803+
1804+class UbuntuSettingsFingerprintPlugin : public QQmlExtensionPlugin
1805+{
1806+ Q_OBJECT
1807+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
1808+public:
1809+ void registerTypes(const char *uri);
1810+};
1811+
1812+#endif // UBUNTUSETTINGSFINGERPRINT_PLUGIN_H
1813
1814=== added file 'plugins/Ubuntu/Settings/Fingerprint/qmldir'
1815--- plugins/Ubuntu/Settings/Fingerprint/qmldir 1970-01-01 00:00:00 +0000
1816+++ plugins/Ubuntu/Settings/Fingerprint/qmldir 2016-06-20 13:58:28 +0000
1817@@ -0,0 +1,7 @@
1818+module Ubuntu.Settings.Fingerprint
1819+plugin UbuntuSettingsFingerprintQml
1820+
1821+Fingerprint 0.1 Fingerprint.qml
1822+Fingerprints 0.1 Fingerprints.qml
1823+FingerprintVisual 0.1 FingerprintVisual.qml
1824+Setup 0.1 Setup.qml
1825
1826=== added file 'plugins/Ubuntu/Settings/Fingerprint/ubuntusettingsfingerprint.cpp'
1827--- plugins/Ubuntu/Settings/Fingerprint/ubuntusettingsfingerprint.cpp 1970-01-01 00:00:00 +0000
1828+++ plugins/Ubuntu/Settings/Fingerprint/ubuntusettingsfingerprint.cpp 2016-06-20 13:58:28 +0000
1829@@ -0,0 +1,39 @@
1830+/*
1831+ * Copyright (C) 2016 Canonical, Ltd.
1832+ *
1833+ * This program is free software; you can redistribute it and/or modify
1834+ * it under the terms of the GNU Lesser General Public License as published by
1835+ * the Free Software Foundation; version 3.
1836+ *
1837+ * This program is distributed in the hope that it will be useful,
1838+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1839+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1840+ * GNU Lesser General Public License for more details.
1841+ *
1842+ * You should have received a copy of the GNU Lesser General Public License
1843+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1844+ *
1845+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
1846+ */
1847+#include <unistd.h>
1848+#include <sys/types.h>
1849+#include <QProcessEnvironment>
1850+
1851+#include "ubuntusettingsfingerprint.h"
1852+
1853+UbuntuSettingsFingerprint::UbuntuSettingsFingerprint(QObject* parent)
1854+ : QObject(parent)
1855+{
1856+}
1857+
1858+qlonglong UbuntuSettingsFingerprint::uid() const
1859+{
1860+ return qlonglong(getuid());
1861+}
1862+
1863+bool UbuntuSettingsFingerprint::debug() const
1864+{
1865+ return QProcessEnvironment::systemEnvironment().contains(
1866+ QLatin1String("USC_FINGERPRINT_DEBUG")
1867+ );
1868+}
1869
1870=== added file 'plugins/Ubuntu/Settings/Fingerprint/ubuntusettingsfingerprint.h'
1871--- plugins/Ubuntu/Settings/Fingerprint/ubuntusettingsfingerprint.h 1970-01-01 00:00:00 +0000
1872+++ plugins/Ubuntu/Settings/Fingerprint/ubuntusettingsfingerprint.h 2016-06-20 13:58:28 +0000
1873@@ -0,0 +1,37 @@
1874+/*
1875+ * Copyright (C) 2016 Canonical, Ltd.
1876+ *
1877+ * This program is free software; you can redistribute it and/or modify
1878+ * it under the terms of the GNU Lesser General Public License as published by
1879+ * the Free Software Foundation; version 3.
1880+ *
1881+ * This program is distributed in the hope that it will be useful,
1882+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1883+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1884+ * GNU Lesser General Public License for more details.
1885+ *
1886+ * You should have received a copy of the GNU Lesser General Public License
1887+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1888+ *
1889+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
1890+ */
1891+
1892+#ifndef UBUNTUSETTINGSFINGERPRINT_H
1893+#define UBUNTUSETTINGSFINGERPRINT_H
1894+
1895+#include <QObject>
1896+
1897+class UbuntuSettingsFingerprint : public QObject
1898+{
1899+ Q_OBJECT
1900+public:
1901+ explicit UbuntuSettingsFingerprint(QObject* parent = 0);
1902+
1903+ Q_PROPERTY(qlonglong uid READ uid CONSTANT)
1904+ Q_PROPERTY(bool debug READ debug CONSTANT)
1905+
1906+ qlonglong uid() const;
1907+ bool debug() const;
1908+};
1909+
1910+#endif // UBUNTUSETTINGSFINGERPRINT_H
1911
1912=== added directory 'plugins/Ubuntu/Settings/Fingerprint/utils'
1913=== added file 'plugins/Ubuntu/Settings/Fingerprint/utils/segment.py'
1914--- plugins/Ubuntu/Settings/Fingerprint/utils/segment.py 1970-01-01 00:00:00 +0000
1915+++ plugins/Ubuntu/Settings/Fingerprint/utils/segment.py 2016-06-20 13:58:28 +0000
1916@@ -0,0 +1,84 @@
1917+#!/usr/bin/python2
1918+"""
1919+ * Copyright 2016 Canonical Ltd.
1920+ *
1921+ * This program is free software; you can redistribute it and/or modify
1922+ * it under the terms of the GNU Lesser General Public License as published by
1923+ * the Free Software Foundation; version 3.
1924+ *
1925+ * This program is distributed in the hope that it will be useful,
1926+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1927+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1928+ * GNU Lesser General Public License for more details.
1929+ *
1930+ * You should have received a copy of the GNU Lesser General Public License
1931+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1932+ *
1933+ * Authored by Florian Boucault <florian.boucault@canonical.com>
1934+ */
1935+"""
1936+
1937+import os.path
1938+import argparse
1939+import json
1940+import cv2
1941+
1942+parser = argparse.ArgumentParser(
1943+ description='Generates segmented version of img and extracts bbs.'
1944+)
1945+parser.add_argument('input_image', type=str,
1946+ help='path to the image to segment')
1947+args = parser.parse_args()
1948+
1949+input_image = os.path.abspath(args.input_image)
1950+print("Segmenting %s..." % input_image)
1951+filename, _ = os.path.splitext(os.path.basename(input_image))
1952+split = filename.split('@')
1953+if len(split) != 1:
1954+ output_image = "%s_segmented@%s.png" % (split[0], split[1])
1955+ output_boxes = "%s_boxes.json" % split[0]
1956+else:
1957+ output_image = "%s_segmented.png" % filename
1958+ output_boxes = "%s_boxes.json" % filename
1959+
1960+img = cv2.imread(input_image, -1)
1961+img_boxes = img.copy()
1962+gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
1963+ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
1964+contours, hierarchy = cv2.findContours(
1965+ thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE
1966+)
1967+
1968+print("Detected %d segments." % len(contours))
1969+
1970+bounding_boxes = []
1971+for index, contour in enumerate(contours):
1972+ x, y, w, h = cv2.boundingRect(contour)
1973+ bounding_boxes.append((x, y, w, h))
1974+# print(x, y, w, h)
1975+ cv2.rectangle(img_boxes,
1976+ (x, y),
1977+ (x + w, y + h),
1978+ (255, 20, 20, 255), 1)
1979+ cv2.drawContours(thresh, contours, index, (index + 1),
1980+ cv2.cv.CV_FILLED)
1981+ cv2.drawContours(thresh, contours, index, (index + 1), 2)
1982+
1983+b, g, r, a = cv2.split(img)
1984+img = cv2.merge([a, g, thresh])
1985+
1986+cv2.imwrite(output_image, img)
1987+print("Written segmented version of '%s' to '%s'" % (
1988+ args.input_image, output_image)
1989+)
1990+
1991+description = {"width": img.shape[1],
1992+ "height": img.shape[0],
1993+ "boxes": bounding_boxes}
1994+with open(output_boxes, 'w') as outfile:
1995+ json.dump(description, outfile)
1996+print("Written bounding boxes to '%s'" % output_boxes)
1997+
1998+cv2.imshow('image', img_boxes)
1999+cv2.waitKey(0)
2000+cv2.destroyAllWindows()
2001
2002=== modified file 'po/ubuntu-settings-components.pot'
2003--- po/ubuntu-settings-components.pot 2016-05-19 17:52:21 +0000
2004+++ po/ubuntu-settings-components.pot 2016-06-20 13:58:28 +0000
2005@@ -8,7 +8,7 @@
2006 msgstr ""
2007 "Project-Id-Version: ubuntu-settings-components\n"
2008 "Report-Msgid-Bugs-To: \n"
2009-"POT-Creation-Date: 2016-04-25 15:44+0200\n"
2010+"POT-Creation-Date: 2016-06-20 15:57+0200\n"
2011 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
2012 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
2013 "Language-Team: LANGUAGE <LL@li.org>\n"
2014@@ -21,6 +21,105 @@
2015 msgid "Quick reply with:"
2016 msgstr ""
2017
2018+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml:80
2019+msgid "Fingerprint Name"
2020+msgstr ""
2021+
2022+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml:107
2023+msgid "Delete Fingerprint"
2024+msgstr ""
2025+
2026+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml:124
2027+msgid "Sorry, the fingerprint could not be deleted."
2028+msgstr ""
2029+
2030+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml:129
2031+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:337
2032+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:137
2033+#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:148
2034+msgid "OK"
2035+msgstr ""
2036+
2037+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:32
2038+msgid "Fingerprint ID"
2039+msgstr ""
2040+
2041+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:93
2042+#, qt-format
2043+msgid "Finger %1"
2044+msgstr ""
2045+
2046+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:187
2047+msgid "Passcode required"
2048+msgstr ""
2049+
2050+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:191
2051+msgid "You must set a passcode to use fingerprint ID"
2052+msgstr ""
2053+
2054+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:198
2055+msgid "Set Passcode…"
2056+msgstr ""
2057+
2058+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:274
2059+msgid "Add fingerprint"
2060+msgstr ""
2061+
2062+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:287
2063+msgid "Remove All…"
2064+msgstr ""
2065+
2066+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:302
2067+msgid "Are you sure you want to forget all stored fingerprints?"
2068+msgstr ""
2069+
2070+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:311
2071+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:357
2072+#: plugins/Ubuntu/Settings/Vpn/DialogFile.qml:161
2073+#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:135
2074+#: plugins/Ubuntu/Settings/Vpn/VpnPreviewDialog.qml:104
2075+msgid "Cancel"
2076+msgstr ""
2077+
2078+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:318
2079+#: plugins/Ubuntu/Settings/Vpn/VpnPreviewDialog.qml:84
2080+msgid "Remove"
2081+msgstr ""
2082+
2083+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:332
2084+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:102
2085+msgid "Sorry, the reader doesn’t seem to be working."
2086+msgstr ""
2087+
2088+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:60
2089+msgid "Swipe your finger repeatedly over the reader."
2090+msgstr ""
2091+
2092+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:77
2093+msgid "Keep your finger on the reader for longer."
2094+msgstr ""
2095+
2096+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:93
2097+msgid "Back"
2098+msgstr ""
2099+
2100+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:130
2101+msgid "All done!"
2102+msgstr ""
2103+
2104+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:296
2105+msgid "Swipe your finger over the reader."
2106+msgstr ""
2107+
2108+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:310
2109+#, qt-format
2110+msgid "%1%"
2111+msgstr ""
2112+
2113+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:382
2114+msgid "Next"
2115+msgstr ""
2116+
2117 #: plugins/Ubuntu/Settings/Menus/CalendarMenu.qml:57
2118 #, qt-format
2119 msgctxt "%1=month name, %2=4-digit year"
2120@@ -48,12 +147,6 @@
2121 msgid "Message"
2122 msgstr ""
2123
2124-#: plugins/Ubuntu/Settings/Vpn/DialogFile.qml:161
2125-#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:134
2126-#: plugins/Ubuntu/Settings/Vpn/VpnPreviewDialog.qml:104
2127-msgid "Cancel"
2128-msgstr ""
2129-
2130 #: plugins/Ubuntu/Settings/Vpn/DialogFile.qml:170
2131 msgid "Accept"
2132 msgstr ""
2133@@ -358,14 +451,10 @@
2134 msgid "Your Wi-Fi/mobile provider can track your use of any other services. "
2135 msgstr ""
2136
2137-#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:26
2138+#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:25
2139 msgid "Set up VPN"
2140 msgstr ""
2141
2142-#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:147
2143-msgid "OK"
2144-msgstr ""
2145-
2146 #: plugins/Ubuntu/Settings/Vpn/VpnList.qml:62
2147 msgid "Delete configuration"
2148 msgstr ""
2149@@ -380,10 +469,6 @@
2150 msgid "VPN"
2151 msgstr ""
2152
2153-#: plugins/Ubuntu/Settings/Vpn/VpnPreviewDialog.qml:84
2154-msgid "Remove"
2155-msgstr ""
2156-
2157 #: plugins/Ubuntu/Settings/Vpn/VpnPreviewDialog.qml:96
2158 msgid "Change"
2159 msgstr ""
2160
2161=== modified file 'tests/qmltests/CMakeLists.txt'
2162--- tests/qmltests/CMakeLists.txt 2016-03-09 14:04:14 +0000
2163+++ tests/qmltests/CMakeLists.txt 2016-06-20 13:58:28 +0000
2164@@ -1,6 +1,8 @@
2165 # add_qml_test macro
2166 include(QmlTest)
2167
2168+add_subdirectory(mocks)
2169+
2170 set(qmltest_DEFAULT_TARGETS qmluitests)
2171 set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
2172 set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
2173@@ -40,3 +42,8 @@
2174 add_qml_test(Vpn VpnPptpEditor)
2175 add_qml_test(Vpn VpnPreviewDialogCertificateChecks)
2176 add_qml_test(Vpn VpnPreviewDialog ENVIRONMENT NO_SSL_CERTIFICATE_CHECK=1)
2177+
2178+add_qml_test(Fingerprint Fingerprints IMPORT_PATHS ${CMAKE_CURRENT_BINARY_DIR}/mocks)
2179+add_qml_test(Fingerprint FingerprintNames IMPORT_PATHS ${CMAKE_CURRENT_BINARY_DIR}/mocks)
2180+add_qml_test(Fingerprint FingerprintSetup IMPORT_PATHS ${CMAKE_CURRENT_BINARY_DIR}/mocks)
2181+add_qml_test(Fingerprint FingerprintVisual)
2182
2183=== added directory 'tests/qmltests/Fingerprint'
2184=== added file 'tests/qmltests/Fingerprint/tst_FingerprintNames.qml'
2185--- tests/qmltests/Fingerprint/tst_FingerprintNames.qml 1970-01-01 00:00:00 +0000
2186+++ tests/qmltests/Fingerprint/tst_FingerprintNames.qml 2016-06-20 13:58:28 +0000
2187@@ -0,0 +1,364 @@
2188+/*
2189+ * Copyright 2016 Canonical Ltd.
2190+ *
2191+ * This program is free software; you can redistribute it and/or modify
2192+ * it under the terms of the GNU Lesser General Public License as published by
2193+ * the Free Software Foundation; version 3.
2194+ *
2195+ * This program is distributed in the hope that it will be useful,
2196+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2197+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2198+ * GNU Lesser General Public License for more details.
2199+ *
2200+ * You should have received a copy of the GNU Lesser General Public License
2201+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2202+ *
2203+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
2204+ */
2205+
2206+import QtQuick 2.4
2207+import QtTest 1.0
2208+import Ubuntu.Test 0.1
2209+import Ubuntu.Settings.Fingerprint 0.1
2210+import Ubuntu.Components 1.3
2211+import Biometryd 0.0
2212+import GSettings 1.0
2213+
2214+Item {
2215+ id: testRoot
2216+ width: units.gu(50)
2217+ height: units.gu(90)
2218+
2219+ PageStack {
2220+ id: pageStack
2221+ }
2222+
2223+ Component {
2224+ id: fingerprintsComponent
2225+
2226+ Fingerprints {
2227+ anchors.fill: parent
2228+ visible: false
2229+ }
2230+ }
2231+
2232+ Component {
2233+ id: fingerprintComponent
2234+
2235+ Fingerprint {
2236+ anchors.fill: parent
2237+ visible: false
2238+ }
2239+ }
2240+
2241+ Component {
2242+ id: gsettingsComponent
2243+
2244+ GSettings {
2245+ schema.id: "com.ubuntu.touch.system"
2246+ }
2247+ }
2248+
2249+ UbuntuTestCase {
2250+ name: "TestOverview"
2251+ when: windowShown
2252+
2253+ property var pageInstance: null
2254+ property var gsettingsInstance: null
2255+
2256+ function getTemplateEntry(i) {
2257+ var id = "fingerprintInstance-" + i;
2258+ return findChild(pageInstance, id);
2259+ }
2260+
2261+ function getListObserver() {
2262+ return findInvisibleChild(pageInstance, "listObserver");
2263+ }
2264+
2265+ function getRemovalObserver() {
2266+ return findInvisibleChild(pageInstance, "removalObserver");
2267+ }
2268+
2269+ function getClearanceObserver() {
2270+ return findInvisibleChild(pageInstance, "clearanceObserver");
2271+ }
2272+
2273+ function getEnrollmentObserver() {
2274+ return findInvisibleChild(pageInstance, "enrollmentObserver");
2275+ }
2276+
2277+ function initTestCase() {
2278+ Biometryd.setAvailable(true);
2279+ }
2280+
2281+ function init() {
2282+ gsettingsInstance = gsettingsComponent.createObject(testRoot);
2283+ pageInstance = fingerprintsComponent.createObject(testRoot, {
2284+ _settings: gsettingsInstance,
2285+ passcodeSet: true
2286+ });
2287+ pageStack.push(pageInstance);
2288+ }
2289+
2290+ function test_listSort() {
2291+ GSettingsController.setFingerprintNames({
2292+ "first": "A finger",
2293+ "second": "Big finger",
2294+ "last": "Zmall finger",
2295+ });
2296+ compare(getTemplateEntry(0).title.text, "A finger");
2297+ compare(getTemplateEntry(1).title.text, "Big finger");
2298+ compare(getTemplateEntry(2).title.text, "Zmall finger");
2299+ }
2300+
2301+ function test_remoteRemoval() {
2302+ GSettingsController.setFingerprintNames({
2303+ "tmplId": "name"
2304+ });
2305+ verify(getTemplateEntry(0));
2306+
2307+ GSettingsController.setFingerprintNames({});
2308+ verify(!getTemplateEntry(0));
2309+ }
2310+
2311+ function test_remoteAddition() {
2312+ GSettingsController.setFingerprintNames({
2313+ "tmplId": "name"
2314+ });
2315+ verify(getTemplateEntry(0));
2316+
2317+ GSettingsController.setFingerprintNames({
2318+ "tmplId": "name",
2319+ "tmplId2": "name2"
2320+ });
2321+ verify(getTemplateEntry(0));
2322+ verify(getTemplateEntry(1));
2323+ }
2324+
2325+ function test_remoteRename() {
2326+ GSettingsController.setFingerprintNames({
2327+ "tmplId": "My finger",
2328+ });
2329+ compare(getTemplateEntry(0).title.text, "My finger");
2330+ GSettingsController.setFingerprintNames({
2331+ "tmplId": "Your finger",
2332+ });
2333+ compare(getTemplateEntry(0).title.text, "Your finger");
2334+ }
2335+
2336+ function test_localRemoval() {
2337+ GSettingsController.setFingerprintNames({
2338+ "tmplId": "name"
2339+ });
2340+ verify(getTemplateEntry(0));
2341+ pageInstance.removeTemplate("tmplId");
2342+ verify(!getTemplateEntry(0));
2343+ }
2344+
2345+ function test_localAddition() {
2346+ pageInstance.addTemplate("tmplId", "My finger");
2347+ verify(getTemplateEntry(0));
2348+ compare(getTemplateEntry(0).title.text, "My finger");
2349+ }
2350+
2351+ function test_localRename() {
2352+ GSettingsController.setFingerprintNames({
2353+ "tmplId": "My finger"
2354+ });
2355+ pageInstance.renameTemplate("tmplId", "Your finger");
2356+ verify(getTemplateEntry(0));
2357+ compare(getTemplateEntry(0).title.text, "Your finger");
2358+ }
2359+
2360+ function test_createTemplateName() {
2361+ GSettingsController.setFingerprintNames({
2362+ "tmplId": i18n.dtr("ubuntu-settings-components", "Finger %1").arg(1)
2363+ });
2364+ compare(pageInstance.createTemplateName(), i18n.dtr("ubuntu-settings-components", "Finger %1").arg(2));
2365+ pageInstance.renameTemplate("tmplId", i18n.dtr("ubuntu-settings-components", "Finger %1").arg(2));
2366+ compare(pageInstance.createTemplateName(), i18n.dtr("ubuntu-settings-components", "Finger %1").arg(1));
2367+ }
2368+
2369+ function test_assignNames() {
2370+ var templateIds = ["tmplId0", "tmplId1", "tmplId2"];
2371+
2372+ // This name shouldn't be overwritten
2373+ GSettingsController.setFingerprintNames({
2374+ "tmplId1": "My finger"
2375+ });
2376+
2377+ getListObserver().mockList(templateIds, "");
2378+
2379+ verify(getTemplateEntry(0));
2380+ compare(getTemplateEntry(0).title.text, i18n.dtr("ubuntu-settings-components", "Finger %1").arg(1));
2381+
2382+ verify(getTemplateEntry(1));
2383+ compare(getTemplateEntry(1).title.text, i18n.dtr("ubuntu-settings-components", "Finger %1").arg(2));
2384+
2385+ verify(getTemplateEntry(2));
2386+ compare(getTemplateEntry(2).title.text, "My finger");
2387+ }
2388+
2389+ function test_serviceRemoval() {
2390+ GSettingsController.setFingerprintNames({
2391+ "tmplId": "A finger"
2392+ });
2393+ getRemovalObserver().mockRemoval("tmplId", "");
2394+ verify(!getTemplateEntry(0));
2395+ compare(GSettingsController.fingerprintNames(), {});
2396+ }
2397+
2398+ function test_serviceEnrollment() {
2399+ GSettingsController.setFingerprintNames({
2400+ "tmplId1": "Existing finger"
2401+ });
2402+ getEnrollmentObserver().mockEnroll("tmplId2", "");
2403+
2404+ verify(getTemplateEntry(0));
2405+ compare(getTemplateEntry(0).title.text, "Existing finger");
2406+
2407+ verify(getTemplateEntry(1));
2408+ compare(getTemplateEntry(1).title.text, i18n.dtr("ubuntu-settings-components", "Finger %1").arg(1));
2409+ }
2410+
2411+ function test_serviceEnrollmentFirstRun() {
2412+ var targetName = i18n.dtr("ubuntu-settings-components", "Finger %1").arg(1);
2413+
2414+ // A test where the template id is 0.
2415+ getEnrollmentObserver().mockEnroll(0, "");
2416+
2417+ verify(getTemplateEntry(0));
2418+ compare(getTemplateEntry(0).title.text, targetName);
2419+ }
2420+
2421+ function test_serviceEnrollmentReusesId() {
2422+ // Test a case where enrollment processes re-uses the template id
2423+ // Hopefully this will never happen, but it currently does in testing,
2424+ // so test it.
2425+ var targetName = i18n.dtr("ubuntu-settings-components", "Finger %1").arg(1);
2426+
2427+ getEnrollmentObserver().mockEnroll(0, "");
2428+ verify(getTemplateEntry(0));
2429+ compare(getTemplateEntry(0).title.text, targetName);
2430+
2431+ // Re-enroll same id, make sure it doesn't change the name
2432+ getEnrollmentObserver().mockEnroll(0, "");
2433+ verify(getTemplateEntry(0));
2434+ compare(getTemplateEntry(0).title.text, targetName);
2435+
2436+ }
2437+
2438+ function test_serviceClearance() {
2439+ GSettingsController.setFingerprintNames({
2440+ "tmplId1": "A finger",
2441+ "tmplId2": "My finger"
2442+ });
2443+ getClearanceObserver().mockClearance("");
2444+
2445+ verify(!getTemplateEntry(0));
2446+ compare(GSettingsController.fingerprintNames(), {});
2447+ }
2448+
2449+ function cleanup() {
2450+ pageStack.pop();
2451+ GSettingsController.setFingerprintNames({});
2452+ gsettingsInstance.destroy();
2453+ gsettingsInstance = null;
2454+ pageInstance.destroy();
2455+ pageInstance = null;
2456+ }
2457+ }
2458+
2459+ SignalSpy {
2460+ id: requestDeletionSpy
2461+ signalName: "requestDeletion"
2462+ }
2463+
2464+ SignalSpy {
2465+ id: requestRenameSpy
2466+ signalName: "requestRename"
2467+ }
2468+
2469+ UbuntuTestCase {
2470+ name: "TestTemplate"
2471+ when: windowShown
2472+
2473+ property var templateInstance: null
2474+
2475+ function getDeleteButton() {
2476+ return findChild(templateInstance, "templateDelete");
2477+ }
2478+
2479+ function getHeader() {
2480+ return findChild(templateInstance, "templateHeader");
2481+ }
2482+
2483+ function getNameInput() {
2484+ return findChild(templateInstance, "nameInput");
2485+ }
2486+
2487+ function getFailedDialog() {
2488+ return findChild(testRoot, "fingerprintDeletionFailedDialog");
2489+ }
2490+
2491+ function getFailedDialogOk() {
2492+ return findChild(testRoot, "fingerprintDeleteionFailedOk");
2493+ }
2494+
2495+ function init() {
2496+ templateInstance = fingerprintComponent.createObject(testRoot);
2497+ pageStack.push(templateInstance);
2498+ requestRenameSpy.target = templateInstance;
2499+ requestDeletionSpy.target = templateInstance;
2500+ }
2501+
2502+ function cleanup() {
2503+ requestRenameSpy.clear();
2504+ requestDeletionSpy.clear();
2505+ pageStack.pop();
2506+ templateInstance.destroy();
2507+ templateInstance = null;
2508+ }
2509+
2510+ function test_name() {
2511+ templateInstance.name = "My finger";
2512+ compare(getHeader().title, "My finger");
2513+ compare(getNameInput().text, "My finger");
2514+ }
2515+
2516+ function test_requestDeletion() {
2517+ templateInstance.templateId = "tmplId";
2518+ var button = getDeleteButton();
2519+ mouseClick(button, button.width / 2, button.height / 2);
2520+ requestDeletionSpy.wait();
2521+ compare(requestDeletionSpy.count, 1);
2522+ compare(requestDeletionSpy.signalArguments[0][0], "tmplId");
2523+ }
2524+
2525+ function test_requestRename() {
2526+ templateInstance.templateId = "tmplId";
2527+ templateInstance.name = "My finger";
2528+ requestRenameSpy.clear();
2529+
2530+ getNameInput().text = "Your finger";
2531+ requestRenameSpy.wait();
2532+ compare(requestRenameSpy.count, 1);
2533+ compare(requestRenameSpy.signalArguments[0][0], "tmplId");
2534+ compare(requestRenameSpy.signalArguments[0][1], "Your finger");
2535+ }
2536+
2537+ function test_deletionFailed() {
2538+ templateInstance.deletionFailed();
2539+ tryCompareFunction(function () {
2540+ return !!getFailedDialog();
2541+ }, true);
2542+
2543+ var button = getFailedDialogOk();
2544+ mouseClick(button, button.width / 2, button.height / 2);
2545+
2546+ tryCompareFunction(function () {
2547+ return !!getFailedDialog();
2548+ }, false);
2549+ }
2550+ }
2551+}
2552
2553=== added file 'tests/qmltests/Fingerprint/tst_FingerprintSetup.qml'
2554--- tests/qmltests/Fingerprint/tst_FingerprintSetup.qml 1970-01-01 00:00:00 +0000
2555+++ tests/qmltests/Fingerprint/tst_FingerprintSetup.qml 2016-06-20 13:58:28 +0000
2556@@ -0,0 +1,236 @@
2557+/*
2558+ * Copyright 2016 Canonical Ltd.
2559+ *
2560+ * This program is free software; you can redistribute it and/or modify
2561+ * it under the terms of the GNU Lesser General Public License as published by
2562+ * the Free Software Foundation; version 3.
2563+ *
2564+ * This program is distributed in the hope that it will be useful,
2565+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2566+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2567+ * GNU Lesser General Public License for more details.
2568+ *
2569+ * You should have received a copy of the GNU Lesser General Public License
2570+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2571+ *
2572+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
2573+ */
2574+
2575+import QtQuick 2.4
2576+import QtTest 1.0
2577+import Ubuntu.Components 1.3
2578+import Ubuntu.Settings.Fingerprint 0.1
2579+import Ubuntu.Test 0.1
2580+import Biometryd 0.0
2581+
2582+Item {
2583+ id: testRoot
2584+ width: units.gu(50)
2585+ height: units.gu(90)
2586+
2587+ Component {
2588+ id: setupComponent
2589+
2590+ Setup {
2591+ anchors.fill: parent
2592+ visible: false
2593+ }
2594+ }
2595+
2596+ PageStack {
2597+ id: pageStack
2598+ }
2599+
2600+ SignalSpy {
2601+ id: statusLabelSpy
2602+ signalName: "slideCompleted"
2603+ }
2604+
2605+ SignalSpy {
2606+ id: enrollmentObserverProgressedSpy
2607+ signalName: "progressed"
2608+ }
2609+
2610+ SignalSpy {
2611+ id: enrollmentObserverSucceededSpy
2612+ signalName: "succeeded"
2613+ }
2614+
2615+ SignalSpy {
2616+ id: enrollmentObserverFailedSpy
2617+ signalName: "failed"
2618+ }
2619+
2620+ UbuntuTestCase {
2621+ name: "SetupUI"
2622+ when: windowShown
2623+
2624+ property var setupInstance: null
2625+
2626+ function init() {
2627+ Biometryd.setAvailable(true);
2628+ setupInstance = setupComponent.createObject(testRoot);
2629+ pageStack.push(setupInstance);
2630+
2631+ statusLabelSpy.target = getStatusLabel();
2632+ }
2633+
2634+ function cleanup() {
2635+ statusLabelSpy.clear();
2636+
2637+ pageStack.pop();
2638+ setupInstance.destroy();
2639+ setupInstance = null
2640+ }
2641+
2642+ function getStatusLabel() {
2643+ return findChild(setupInstance, "fingerprintStatusLabel");
2644+ }
2645+
2646+ function getFailedVisual() {
2647+ return findChild(setupInstance, "fingerprintFailedVisual");
2648+ }
2649+
2650+ function getDefaultVisual() {
2651+ return findChild(setupInstance, "fingerprintDefaultVisual");
2652+ }
2653+
2654+ function getDoneVisual() {
2655+ return findChild(setupInstance, "fingerprintDoneVisual");
2656+ }
2657+
2658+ function getProgressLabel() {
2659+ return findChild(setupInstance, "fingerprintProgressLabel");
2660+ }
2661+
2662+ function test_initialState() {
2663+ var targetText = i18n.dtr("ubuntu-settings-components", "Swipe your finger over the reader.");
2664+ compare(getStatusLabel().text, targetText);
2665+
2666+ tryCompare(getDefaultVisual(), "opacity", 1);
2667+ tryCompare(getFailedVisual(), "opacity", 0);
2668+ tryCompare(getDoneVisual(), "opacity", 0);
2669+ }
2670+
2671+ function test_startedState() {
2672+ var targetText = i18n.dtr("ubuntu-settings-components", "Swipe your finger repeatedly over the reader.");
2673+ setupInstance.enrollmentProgressed(0.5, {});
2674+ statusLabelSpy.wait();
2675+ compare(getStatusLabel().text, targetText);
2676+
2677+ tryCompare(getDefaultVisual(), "opacity", 1);
2678+ tryCompare(getFailedVisual(), "opacity", 0);
2679+ tryCompare(getDoneVisual(), "opacity", 0);
2680+ }
2681+
2682+ function test_failedStatus() {
2683+ var targetText = i18n.dtr("ubuntu-settings-components", "Sorry, the reader doesn’t seem to be working.");
2684+ setupInstance.enrollmentFailed("test failure");
2685+ compare(getStatusLabel().text, targetText);
2686+
2687+ tryCompare(getDefaultVisual(), "opacity", 0);
2688+ tryCompare(getFailedVisual(), "opacity", 1);
2689+ tryCompare(getDoneVisual(), "opacity", 0);
2690+ }
2691+
2692+ function test_successfulState() {
2693+ var targetText = i18n.dtr("ubuntu-settings-components", "All done!");
2694+
2695+ setupInstance.enrollmentCompleted();
2696+ compare(getStatusLabel().text, targetText);
2697+
2698+ tryCompare(getDefaultVisual(), "opacity", 0);
2699+ tryCompare(getFailedVisual(), "opacity", 0);
2700+ tryCompare(getDoneVisual(), "opacity", 1);
2701+
2702+ var button = findChild(pageStack, "fingerprintSetupDoneButton");
2703+ compare(button.enabled, true, "button was disabled when done");
2704+ }
2705+
2706+ function test_notDone() {
2707+ var button = findChild(pageStack, "fingerprintSetupDoneButton");
2708+ compare(button.enabled, false, "button was enabled initially");
2709+ }
2710+
2711+ function test_statusLabel() {
2712+ getStatusLabel().setText("foo");
2713+ statusLabelSpy.wait();
2714+ compare(getStatusLabel().text, "foo");
2715+ }
2716+
2717+ function test_direction_data() {
2718+ return [
2719+ { tag: "empty", visual: { visible: false, rotation: 0 }},
2720+ { tag: "not available", dir: FingerprintReader.NotAvailable, visual: { visible: false, rotation: 0 }},
2721+ { tag: "SouthWest", dir: FingerprintReader.SouthWest, visual: { visible: true, rotation: 225 }},
2722+ { tag: "South", dir: FingerprintReader.South, visual: { visible: true, rotation: 180 }},
2723+ { tag: "SouthEast", dir: FingerprintReader.SouthEast, visual: { visible: true, rotation: 135 }},
2724+ { tag: "NorthWest", dir: FingerprintReader.NorthWest, visual: { visible: true, rotation: 315 }},
2725+ { tag: "North", dir: FingerprintReader.North, visual: { visible: true, rotation: 0 }},
2726+ { tag: "NorthEast", dir: FingerprintReader.NorthEast, visual: { visible: true, rotation: 45 }},
2727+ { tag: "East", dir: FingerprintReader.East, visual: { visible: true, rotation: 90 }},
2728+ { tag: "West", dir: FingerprintReader.West, visual: { visible: true, rotation: 270 }}
2729+ ]
2730+ }
2731+
2732+ function test_direction(data) {
2733+ var vis = findChild(setupInstance, "fingerprintDirectionVisual");
2734+ var hints = {};
2735+ hints[FingerprintReader.suggestedNextDirection] = data.dir;
2736+
2737+ setupInstance.enrollmentProgressed(0.5, hints);
2738+
2739+ tryCompare(vis, "opacity", data.visual.visible ? 1 : 0)
2740+ compare(vis.opacity, data.visual.visible ? 1 : 0);
2741+ compare(vis.rotation, data.visual.rotation);
2742+ }
2743+
2744+ function test_progressHidden() {
2745+ var pl = getProgressLabel();
2746+ compare(pl.opacity, 0);
2747+ }
2748+
2749+ function test_progressVisible() {
2750+ var pl = getProgressLabel();
2751+ setupInstance.enrollmentProgressed(0.5, {});
2752+ tryCompare(pl, "opacity", 1);
2753+ tryCompare(pl, "text", i18n.dtr("ubuntu-settings-components", "%1%").arg(50));
2754+ }
2755+
2756+ function test_progressReadable() {
2757+ setupInstance.enrollmentProgressed(0.6666666667, {});
2758+ tryCompare(getProgressLabel(), "text", i18n.dtr("ubuntu-settings-components", "%1%").arg(66));
2759+ }
2760+
2761+ // This is a visual test where we can confirm that the arrow
2762+ // rotates using the orthodromic distance.
2763+ function test_directions() {
2764+ var hints = {};
2765+
2766+ hints[FingerprintReader.suggestedNextDirection] = FingerprintReader.North;
2767+ setupInstance.enrollmentProgressed(0.6666666667, hints);
2768+ wait(200)
2769+ hints[FingerprintReader.suggestedNextDirection] = FingerprintReader.East;
2770+ setupInstance.enrollmentProgressed(0.6666666667, hints);
2771+ wait(200)
2772+ hints[FingerprintReader.suggestedNextDirection] = FingerprintReader.South;
2773+ setupInstance.enrollmentProgressed(0.6666666667, hints);
2774+ wait(200)
2775+ hints[FingerprintReader.suggestedNextDirection] = FingerprintReader.West;
2776+ setupInstance.enrollmentProgressed(0.6666666667, hints);
2777+ wait(200)
2778+ hints[FingerprintReader.suggestedNextDirection] = FingerprintReader.SouthEast;
2779+ setupInstance.enrollmentProgressed(0.6666666667, hints);
2780+ wait(200)
2781+ hints[FingerprintReader.suggestedNextDirection] = FingerprintReader.NorthEast;
2782+ setupInstance.enrollmentProgressed(0.6666666667, hints);
2783+ wait(200)
2784+ hints[FingerprintReader.suggestedNextDirection] = FingerprintReader.NorthWest;
2785+ setupInstance.enrollmentProgressed(0.6666666667, hints);
2786+ wait(200)
2787+ hints[FingerprintReader.suggestedNextDirection] = FingerprintReader.NorthEast;
2788+ setupInstance.enrollmentProgressed(0.6666666667, hints);
2789+ wait(200)
2790+ }
2791+ }
2792+}
2793
2794=== added file 'tests/qmltests/Fingerprint/tst_FingerprintVisual.qml'
2795--- tests/qmltests/Fingerprint/tst_FingerprintVisual.qml 1970-01-01 00:00:00 +0000
2796+++ tests/qmltests/Fingerprint/tst_FingerprintVisual.qml 2016-06-20 13:58:28 +0000
2797@@ -0,0 +1,132 @@
2798+/*
2799+ * Copyright 2016 Canonical Ltd.
2800+ *
2801+ * This program is free software; you can redistribute it and/or modify
2802+ * it under the terms of the GNU Lesser General Public License as published by
2803+ * the Free Software Foundation; version 3.
2804+ *
2805+ * This program is distributed in the hope that it will be useful,
2806+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2807+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2808+ * GNU Lesser General Public License for more details.
2809+ *
2810+ * You should have received a copy of the GNU Lesser General Public License
2811+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2812+ *
2813+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
2814+ */
2815+
2816+import QtQuick 2.4
2817+import QtTest 1.0
2818+import Ubuntu.Components 1.3
2819+import Ubuntu.Settings.Fingerprint 0.1
2820+import Ubuntu.Test 0.1
2821+
2822+Item {
2823+ id: testRoot
2824+ width: units.gu(50)
2825+ height: units.gu(90)
2826+
2827+ SignalSpy {
2828+ id: visualReadySpy
2829+ signalName: "ready"
2830+ }
2831+
2832+ Component {
2833+ id: fingerprintVisualComp
2834+
2835+ FingerprintVisual {
2836+ id: vis
2837+ objectName: "fingerprintVisual"
2838+ width: 400
2839+ height: width * 1.227
2840+ }
2841+ }
2842+
2843+
2844+ UbuntuTestCase {
2845+ name: "FingerprintVisual"
2846+ when: windowShown
2847+
2848+ function init() {
2849+ visualReadySpy.target = fingerprintVisualComp.createObject(testRoot);
2850+ visualReadySpy.wait()
2851+ }
2852+
2853+ function cleanup() {
2854+ findChild(testRoot, "fingerprintVisual").destroy();
2855+ }
2856+
2857+ function test_masks_data() {
2858+ return [
2859+ { masks: null, targetMasks: [], tag: "null" },
2860+ { masks: [], targetMasks: [], tag: "no masks" },
2861+ {
2862+ masks: [{x: 0, y: 0, width: 0, height: 0 }],
2863+ targetMasks: [{x: 0, y: 0, width: 0, height: 0}],
2864+ tag: "0"
2865+ },
2866+ {
2867+ masks: [
2868+ {x: null, y: "-a", width: "0x1", height: true },
2869+ {},
2870+ ],
2871+ targetMasks: [],
2872+ tag: "bad values"
2873+ },
2874+
2875+ // Masks for manual, visual checks.
2876+ {
2877+ masks: [
2878+ {x: 0, y: 0, width: 0.5, height: 0.5 }
2879+ ],
2880+ visualCheck: true,
2881+ tag: "top right corner"
2882+ },
2883+ {
2884+ masks: [
2885+ {x: 0.5, y: 0, width: 0.5, height: 0.5 }
2886+ ],
2887+ visualCheck: true,
2888+ tag: "top left corner"
2889+ },
2890+ {
2891+ masks: [
2892+ {x: 0, y: 0.5, width: 0.5, height: 0.5 }
2893+ ],
2894+ visualCheck: true,
2895+ tag: "bottom right corner"
2896+ },
2897+ {
2898+ masks: [
2899+ {x: 0.5, y: 0.5, width: 0.5, height: 0.5 }
2900+ ],
2901+ visualCheck: true,
2902+ tag: "bottom left corner"
2903+ },
2904+ {
2905+ masks: [
2906+ {x: 0, y: 0, width: 0.5, height: 0.5 },
2907+ {x: 0.5, y: 0, width: 0.5, height: 0.5 },
2908+ {x: 0, y: 0.5, width: 0.5, height: 0.5 },
2909+ {x: 0.5, y: 0.5, width: 0.5, height: 0.5 }
2910+ ],
2911+ visualCheck: true,
2912+ tag: "all corners"
2913+ }
2914+ ]
2915+ }
2916+
2917+ function test_masks (data) {
2918+ var vis = findChild(testRoot, "fingerprintVisual");
2919+ vis.masks = data.masks;
2920+ if (data.visualCheck) {
2921+ wait(1000);
2922+ } else {
2923+ var actualMasks = vis.getMasksToEnroll();
2924+ var targetMasks = data.targetMasks;
2925+ compare(actualMasks.length, targetMasks.length);
2926+ }
2927+ }
2928+ }
2929+}
2930
2931=== added file 'tests/qmltests/Fingerprint/tst_Fingerprints.qml'
2932--- tests/qmltests/Fingerprint/tst_Fingerprints.qml 1970-01-01 00:00:00 +0000
2933+++ tests/qmltests/Fingerprint/tst_Fingerprints.qml 2016-06-20 13:58:28 +0000
2934@@ -0,0 +1,230 @@
2935+/*
2936+ * Copyright 2016 Canonical Ltd.
2937+ *
2938+ * This program is free software; you can redistribute it and/or modify
2939+ * it under the terms of the GNU Lesser General Public License as published by
2940+ * the Free Software Foundation; version 3.
2941+ *
2942+ * This program is distributed in the hope that it will be useful,
2943+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2944+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2945+ * GNU Lesser General Public License for more details.
2946+ *
2947+ * You should have received a copy of the GNU Lesser General Public License
2948+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2949+ *
2950+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
2951+ */
2952+
2953+import QtQuick 2.4
2954+import QtTest 1.0
2955+import Ubuntu.Test 0.1
2956+import Ubuntu.Settings.Fingerprint 0.1
2957+import Biometryd 0.0
2958+import GSettings 1.0
2959+
2960+Item {
2961+ id: testRoot
2962+ width: units.gu(50)
2963+ height: units.gu(90)
2964+
2965+ Component {
2966+ id: fingerprintsComponent
2967+
2968+ Fingerprints {
2969+ anchors.fill: parent
2970+ }
2971+ }
2972+
2973+ SignalSpy {
2974+ id: spy
2975+ }
2976+
2977+ UbuntuTestCase {
2978+ name: "FingerprintPanel"
2979+ when: windowShown
2980+
2981+ property var fingerprintsInstance: null
2982+
2983+ function init() {
2984+ Biometryd.setAvailable(true);
2985+ fingerprintsInstance = fingerprintsComponent.createObject(testRoot);
2986+ }
2987+
2988+ function cleanup() {
2989+ spy.clear();
2990+ spy.target = null;
2991+ spy.signalName = "";
2992+ fingerprintsInstance.destroy();
2993+ GSettingsController.setFingerprintNames({});
2994+ }
2995+
2996+ function getClearanceObserver() {
2997+ return findInvisibleChild(fingerprintsInstance, "clearanceObserver");
2998+ }
2999+
3000+ function getListObserver() {
3001+ return findInvisibleChild(fingerprintsInstance, "listObserver");
3002+ }
3003+
3004+ function getEnrollmentObserver() {
3005+ return findInvisibleChild(fingerprintsInstance, "enrollmentObserver");
3006+ }
3007+
3008+ function getRemovalObserver() {
3009+ return findInvisibleChild(fingerprintsInstance, "removalObserver");
3010+ }
3011+
3012+ function getBrokenDialog() {
3013+ return findChild(testRoot, "fingerprintReaderBrokenDialog");
3014+ }
3015+
3016+ function getBrokenDialogOk() {
3017+ return findChild(testRoot, "fingerprintReaderBrokenDialogOK");
3018+ }
3019+
3020+ function getAddFingerprintItem() {
3021+ return findChild(fingerprintsInstance, "fingerprintAddListItemLayout");
3022+ }
3023+
3024+ function getRemoveAllButton() {
3025+ return findChild(fingerprintsInstance, "fingerprintRemoveAllButton");
3026+ }
3027+
3028+ function getFingerprintsList() {
3029+ return findChild(fingerprintsInstance, "fingerprintsList");
3030+ }
3031+
3032+ function getSetupEntry() {
3033+ return findChild(fingerprintsInstance, "fingerprintSetupEntry");
3034+ }
3035+
3036+ function test_failures_data() {
3037+ return [
3038+ { tag: "clearance", observer: getClearanceObserver, mock: "mockClearance", mockArgs: ["failed"] },
3039+ { tag: "list", observer: getListObserver, mock: "mockList", mockArgs: [[], "failed"] }
3040+ ]
3041+ }
3042+
3043+ function test_failures(data) {
3044+ var obs = data.observer();
3045+ spy.signalName = "failed";
3046+ spy.target = obs;
3047+ obs[data.mock].apply(null, data.mockArgs);
3048+ spy.wait();
3049+ var errorDiag = getBrokenDialog();
3050+ var ok = getBrokenDialogOk();
3051+ mouseClick(ok, ok.width / 2, ok.height / 2);
3052+
3053+ // Halt testing until dialog has been destroyed.
3054+ tryCompareFunction(function() {
3055+ return getBrokenDialog();
3056+ }, null);
3057+ }
3058+
3059+ function test_noPasscode() {
3060+ fingerprintsInstance.passcodeSet = false;
3061+ compare(fingerprintsInstance.state, "noPasscode");
3062+
3063+ var setButton = findChild(fingerprintsInstance, "fingerprintSetPasscodeButton");
3064+ compare(setButton.visible, true);
3065+
3066+ var setupEntry = getSetupEntry();
3067+ compare(setupEntry.enabled, false);
3068+
3069+ var fingerprintsList = getFingerprintsList();
3070+ compare(fingerprintsList.enabled, false);
3071+ }
3072+
3073+ function test_noScanner() {
3074+ fingerprintsInstance.passcodeSet = true;
3075+ Biometryd.setAvailable(false);
3076+ compare(fingerprintsInstance.state, "noScanner");
3077+
3078+ var addItem = getAddFingerprintItem();
3079+ compare(addItem.enabled, false);
3080+
3081+ var removeButton = getRemoveAllButton();
3082+ compare(removeButton.enabled, false);
3083+
3084+ var fingerprintsList = getFingerprintsList();
3085+ compare(fingerprintsList.visible, false);
3086+ }
3087+
3088+ function test_passcode() {
3089+ fingerprintsInstance.passcodeSet = true;
3090+ compare(fingerprintsInstance.state, "");
3091+ var setButton = findChild(fingerprintsInstance, "fingerprintSetPasscodeButton");
3092+ compare(setButton.visible, false);
3093+ var setupEntry = getSetupEntry();
3094+ compare(setupEntry.enabled, true);
3095+ }
3096+
3097+ function test_changePasscode() {
3098+ fingerprintsInstance.passcodeSet = false;
3099+ var setButton = findChild(fingerprintsInstance, "fingerprintSetPasscodeButton");
3100+
3101+ spy.signalName = "requestPasscode"
3102+ spy.target = fingerprintsInstance;
3103+ mouseClick(setButton, setButton.width / 2, setButton.height / 2);
3104+ spy.wait();
3105+
3106+ compare(spy.count, 1);
3107+ }
3108+
3109+ function test_setup() {
3110+ fingerprintsInstance.passcodeSet = false;
3111+ var add = getAddFingerprintItem();
3112+ var remove = getRemoveAllButton();
3113+ compare(add.enabled, false);
3114+ compare(remove.enabled, false);
3115+ }
3116+
3117+ function test_noRemove() {
3118+ fingerprintsInstance.passcodeSet = true;
3119+ GSettingsController.setFingerprintNames({});
3120+ var remove = getRemoveAllButton();
3121+ compare(remove.enabled, false);
3122+ }
3123+
3124+ function test_remove() {
3125+ fingerprintsInstance.passcodeSet = true;
3126+ GSettingsController.setFingerprintNames({"tmplId": "A Finger"});
3127+
3128+ var remove = getRemoveAllButton();
3129+ mouseClick(remove, remove.width / 2, remove.height / 2);
3130+ var diag = findChild(testRoot, "fingerprintRemoveAllDialog");
3131+ var confirm = findChild(diag, "fingerprintRemoveAllConfirmationButton");
3132+ compare(confirm.visible, true);
3133+ mouseClick(confirm, confirm.width / 2, confirm.height / 2);
3134+
3135+ var obs = getClearanceObserver();
3136+ spy.signalName = "succeeded";
3137+ spy.target = obs;
3138+ obs.mockClearance("");
3139+ spy.wait();
3140+ compare(spy.count, 1);
3141+
3142+ // Wait for dialog destruction (which is required for other tests)
3143+ // to function.
3144+ tryCompareFunction(function() {
3145+ return findChild(testRoot, "fingerprintRemoveAllDialog");
3146+ }, null);
3147+ }
3148+
3149+ function test_enrollmentSucceeded() {
3150+ var obs = getEnrollmentObserver();
3151+ var targetFingerprintName = i18n.dtr("ubuntu-settings-components", "Finger %1").arg(1);
3152+ spy.signalName = "succeeded";
3153+ spy.target = obs;
3154+ obs.mockEnroll("tmplId", "");
3155+ spy.wait();
3156+ compare(spy.count, 1);
3157+ compare(spy.signalArguments[0][0], "tmplId");
3158+
3159+ tryCompareFunction(function() {
3160+ return GSettingsController.fingerprintNames()["tmplId"];
3161+ }, targetFingerprintName);
3162+ }
3163+ }
3164+}
3165
3166=== added directory 'tests/qmltests/mocks'
3167=== added directory 'tests/qmltests/mocks/Biometryd'
3168=== added file 'tests/qmltests/mocks/Biometryd/CMakeLists.txt'
3169--- tests/qmltests/mocks/Biometryd/CMakeLists.txt 1970-01-01 00:00:00 +0000
3170+++ tests/qmltests/mocks/Biometryd/CMakeLists.txt 2016-06-20 13:58:28 +0000
3171@@ -0,0 +1,20 @@
3172+include_directories(
3173+ ${CMAKE_CURRENT_BINARY_DIR}
3174+)
3175+
3176+set(MOCK_BIOMETRYD_SOURCES
3177+ plugin.cpp
3178+ MockDevice.cpp
3179+ MockFingerprintReader.cpp
3180+ MockObserver.cpp
3181+ MockOperation.cpp
3182+ MockService.cpp
3183+ MockTemplateStore.cpp
3184+ MockUser.cpp
3185+)
3186+
3187+add_library(MockBiometryd MODULE ${MOCK_BIOMETRYD_SOURCES})
3188+
3189+qt5_use_modules(MockBiometryd Qml Quick Core)
3190+
3191+add_usc_mock(Biometryd 0.0 Biometryd TARGETS MockBiometryd)
3192
3193=== added file 'tests/qmltests/mocks/Biometryd/MockDevice.cpp'
3194--- tests/qmltests/mocks/Biometryd/MockDevice.cpp 1970-01-01 00:00:00 +0000
3195+++ tests/qmltests/mocks/Biometryd/MockDevice.cpp 2016-06-20 13:58:28 +0000
3196@@ -0,0 +1,30 @@
3197+/*
3198+ * Copyright (C) 2016 Canonical, Ltd.
3199+ *
3200+ * This program is free software; you can redistribute it and/or modify
3201+ * it under the terms of the GNU General Public License as published by
3202+ * the Free Software Foundation; version 3.
3203+ *
3204+ * This program is distributed in the hope that it will be useful,
3205+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3206+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3207+ * GNU General Public License for more details.
3208+ *
3209+ * You should have received a copy of the GNU General Public License
3210+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3211+ */
3212+
3213+#include "MockDevice.h"
3214+
3215+MockDevice::MockDevice(QObject *parent)
3216+ : QObject(parent)
3217+ , m_ts(new MockTemplateStore(this))
3218+{
3219+}
3220+
3221+MockTemplateStore* MockDevice::templateStore()
3222+{
3223+ return m_ts;
3224+}
3225+
3226+#include "MockDevice.moc"
3227
3228=== added file 'tests/qmltests/mocks/Biometryd/MockDevice.h'
3229--- tests/qmltests/mocks/Biometryd/MockDevice.h 1970-01-01 00:00:00 +0000
3230+++ tests/qmltests/mocks/Biometryd/MockDevice.h 2016-06-20 13:58:28 +0000
3231@@ -0,0 +1,38 @@
3232+/*
3233+ * Copyright (C) 2016 Canonical, Ltd.
3234+ *
3235+ * This program is free software; you can redistribute it and/or modify
3236+ * it under the terms of the GNU General Public License as published by
3237+ * the Free Software Foundation; version 3.
3238+ *
3239+ * This program is distributed in the hope that it will be useful,
3240+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3241+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3242+ * GNU General Public License for more details.
3243+ *
3244+ * You should have received a copy of the GNU General Public License
3245+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3246+ */
3247+
3248+#ifndef MOCK_DEVICE_H
3249+#define MOCK_DEVICE_H
3250+
3251+#include <QObject>
3252+#include "MockTemplateStore.h"
3253+
3254+class MockDevice : public QObject
3255+{
3256+ Q_OBJECT
3257+ Q_DISABLE_COPY(MockDevice)
3258+
3259+public:
3260+ explicit MockDevice(QObject *parent = 0);
3261+ Q_PROPERTY(MockTemplateStore* templateStore READ templateStore CONSTANT)
3262+
3263+ MockTemplateStore* templateStore();
3264+
3265+private:
3266+ MockTemplateStore* m_ts;
3267+};
3268+
3269+#endif // MOCK_DEVICE_H
3270
3271=== added file 'tests/qmltests/mocks/Biometryd/MockFingerprintReader.cpp'
3272--- tests/qmltests/mocks/Biometryd/MockFingerprintReader.cpp 1970-01-01 00:00:00 +0000
3273+++ tests/qmltests/mocks/Biometryd/MockFingerprintReader.cpp 2016-06-20 13:58:28 +0000
3274@@ -0,0 +1,49 @@
3275+/*
3276+ * Copyright (C) 2016 Canonical, Ltd.
3277+ *
3278+ * This program is free software; you can redistribute it and/or modify
3279+ * it under the terms of the GNU General Public License as published by
3280+ * the Free Software Foundation; version 3.
3281+ *
3282+ * This program is distributed in the hope that it will be useful,
3283+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3284+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3285+ * GNU General Public License for more details.
3286+ *
3287+ * You should have received a copy of the GNU General Public License
3288+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3289+ */
3290+
3291+#include "MockFingerprintReader.h"
3292+
3293+MockFingerprintReader::MockFingerprintReader(QObject *parent)
3294+ : QObject(parent)
3295+{
3296+}
3297+
3298+QString MockFingerprintReader::isFingerPresent() const
3299+{
3300+ return "isFingerPresent";
3301+}
3302+
3303+QString MockFingerprintReader::hasMainClusterIdentified() const
3304+{
3305+ return "hasMainClusterIdentified";
3306+}
3307+
3308+QString MockFingerprintReader::suggestedNextDirection() const
3309+{
3310+ return "suggestedNextDirection";
3311+}
3312+
3313+QString MockFingerprintReader::estimatedFingerSize() const
3314+{
3315+ return "estimatedFingerSize";
3316+}
3317+
3318+QString MockFingerprintReader::masks() const
3319+{
3320+ return "masks";
3321+}
3322+
3323+#include "MockFingerprintReader.moc"
3324
3325=== added file 'tests/qmltests/mocks/Biometryd/MockFingerprintReader.h'
3326--- tests/qmltests/mocks/Biometryd/MockFingerprintReader.h 1970-01-01 00:00:00 +0000
3327+++ tests/qmltests/mocks/Biometryd/MockFingerprintReader.h 2016-06-20 13:58:28 +0000
3328@@ -0,0 +1,65 @@
3329+/*
3330+ * Copyright (C) 2016 Canonical, Ltd.
3331+ *
3332+ * This program is free software; you can redistribute it and/or modify
3333+ * it under the terms of the GNU General Public License as published by
3334+ * the Free Software Foundation; version 3.
3335+ *
3336+ * This program is distributed in the hope that it will be useful,
3337+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3338+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3339+ * GNU General Public License for more details.
3340+ *
3341+ * You should have received a copy of the GNU General Public License
3342+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3343+ */
3344+
3345+#ifndef MOCK_FINGERPRINTREADER_H
3346+#define MOCK_FINGERPRINTREADER_H
3347+
3348+#include <QObject>
3349+#include <QString>
3350+#include <QVariant>
3351+#include <QList>
3352+#include <QRect>
3353+
3354+class MockFingerprintReader : public QObject
3355+
3356+{
3357+ Q_OBJECT
3358+ Q_DISABLE_COPY(MockFingerprintReader)
3359+ Q_ENUMS(Direction)
3360+ Q_PROPERTY(QString isFingerPresent READ isFingerPresent)
3361+ Q_PROPERTY(QString hasMainClusterIdentified READ hasMainClusterIdentified)
3362+ Q_PROPERTY(QString suggestedNextDirection READ suggestedNextDirection)
3363+ Q_PROPERTY(QString masks READ masks)
3364+
3365+public:
3366+ explicit MockFingerprintReader(QObject *parent = 0);
3367+
3368+ enum class Direction
3369+ {
3370+ NotAvailable,
3371+ SouthWest,
3372+ South,
3373+ SouthEast,
3374+ NorthWest,
3375+ North,
3376+ NorthEast,
3377+ East,
3378+ West
3379+ };
3380+
3381+ Q_INVOKABLE QString isFingerPresent() const;
3382+ Q_INVOKABLE QString hasMainClusterIdentified() const;
3383+ Q_INVOKABLE QString suggestedNextDirection() const;
3384+ Q_INVOKABLE QString estimatedFingerSize() const;
3385+ Q_INVOKABLE QString masks() const;
3386+
3387+
3388+Q_SIGNALS:
3389+ void succeeded(const QVariant &result);
3390+ void failed(const QString &reason);
3391+};
3392+
3393+#endif // MOCK_FINGERPRINTREADER_H
3394
3395=== added file 'tests/qmltests/mocks/Biometryd/MockObserver.cpp'
3396--- tests/qmltests/mocks/Biometryd/MockObserver.cpp 1970-01-01 00:00:00 +0000
3397+++ tests/qmltests/mocks/Biometryd/MockObserver.cpp 2016-06-20 13:58:28 +0000
3398@@ -0,0 +1,88 @@
3399+/*
3400+ * Copyright (C) 2016 Canonical, Ltd.
3401+ *
3402+ * This program is free software; you can redistribute it and/or modify
3403+ * it under the terms of the GNU General Public License as published by
3404+ * the Free Software Foundation; version 3.
3405+ *
3406+ * This program is distributed in the hope that it will be useful,
3407+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3408+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3409+ * GNU General Public License for more details.
3410+ *
3411+ * You should have received a copy of the GNU General Public License
3412+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3413+ */
3414+
3415+#include "MockObserver.h"
3416+
3417+class Result : public QObject
3418+{
3419+ Q_OBJECT
3420+ Q_PROPERTY(unsigned int uid READ uid CONSTANT)
3421+
3422+public:
3423+ explicit Result(unsigned int uid, QObject *parent = 0)
3424+ : QObject(parent), m_uid(uid)
3425+ {}
3426+
3427+ unsigned int uid() const { return m_uid; }
3428+
3429+private:
3430+ unsigned int m_uid;
3431+};
3432+
3433+MockObserver::MockObserver(QObject *parent)
3434+ : QObject(parent)
3435+{
3436+}
3437+
3438+void MockObserver::mockSize(int size, const QString &error)
3439+{
3440+ if (error.isEmpty())
3441+ Q_EMIT succeeded(QVariant::fromValue(size));
3442+ else
3443+ Q_EMIT failed(error);
3444+}
3445+
3446+void MockObserver::mockEnroll(const QString &templateId, const QString &error)
3447+{
3448+ if (error.isEmpty())
3449+ Q_EMIT succeeded(templateId);
3450+ else
3451+ Q_EMIT failed(error);
3452+}
3453+
3454+void MockObserver::mockEnrollProgress(double percent,
3455+ const QVariantMap& details)
3456+{
3457+ Q_EMIT progressed(percent, details);
3458+}
3459+
3460+void MockObserver::mockClearance(const QString &error)
3461+{
3462+ if (error.isEmpty())
3463+ Q_EMIT succeeded(QVariant());
3464+ else
3465+ Q_EMIT failed(error);
3466+}
3467+
3468+void MockObserver::mockRemoval(const QString &templateId,
3469+ const QString &error)
3470+{
3471+ if (error.isEmpty())
3472+ Q_EMIT succeeded(templateId);
3473+ else
3474+ Q_EMIT failed(error);
3475+}
3476+
3477+void MockObserver::mockList(const QStringList &templateIds,
3478+ const QString &error)
3479+{
3480+ if (error.isEmpty())
3481+ Q_EMIT succeeded(templateIds);
3482+ else
3483+ Q_EMIT failed(error);
3484+}
3485+
3486+#include "MockObserver.moc"
3487
3488=== added file 'tests/qmltests/mocks/Biometryd/MockObserver.h'
3489--- tests/qmltests/mocks/Biometryd/MockObserver.h 1970-01-01 00:00:00 +0000
3490+++ tests/qmltests/mocks/Biometryd/MockObserver.h 2016-06-20 13:58:28 +0000
3491@@ -0,0 +1,52 @@
3492+/*
3493+ * Copyright (C) 2016 Canonical, Ltd.
3494+ *
3495+ * This program is free software; you can redistribute it and/or modify
3496+ * it under the terms of the GNU General Public License as published by
3497+ * the Free Software Foundation; version 3.
3498+ *
3499+ * This program is distributed in the hope that it will be useful,
3500+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3501+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3502+ * GNU General Public License for more details.
3503+ *
3504+ * You should have received a copy of the GNU General Public License
3505+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3506+ */
3507+
3508+#ifndef MOCK_OBSERVER_H
3509+#define MOCK_OBSERVER_H
3510+
3511+#include <QObject>
3512+#include <QString>
3513+#include <QVariant>
3514+
3515+class MockObserver : public QObject
3516+{
3517+ Q_OBJECT
3518+ Q_DISABLE_COPY(MockObserver)
3519+
3520+public:
3521+ explicit MockObserver(QObject *parent = 0);
3522+
3523+ Q_INVOKABLE void mockSize(int size, const QString &error); // only in mock
3524+ Q_INVOKABLE void mockEnroll(const QString &templateId,
3525+ const QString &error); // only in mock
3526+ Q_INVOKABLE void mockEnrollProgress(double percent,
3527+ const QVariantMap& details); // only in mock
3528+ Q_INVOKABLE void mockClearance(const QString &error); // only in mock
3529+ Q_INVOKABLE void mockRemoval(const QString &templateId,
3530+ const QString &error); // only in mock
3531+ Q_INVOKABLE void mockList(const QStringList &templateIds,
3532+ const QString &error); // only in mock
3533+
3534+
3535+Q_SIGNALS:
3536+ void progressed(double percent, const QVariantMap& details);
3537+ void succeeded(const QVariant &result);
3538+ void failed(const QString &reason);
3539+ void canceled(const QString& reason);
3540+ void started();
3541+};
3542+
3543+#endif // MOCK_OBSERVER_H
3544
3545=== added file 'tests/qmltests/mocks/Biometryd/MockOperation.cpp'
3546--- tests/qmltests/mocks/Biometryd/MockOperation.cpp 1970-01-01 00:00:00 +0000
3547+++ tests/qmltests/mocks/Biometryd/MockOperation.cpp 2016-06-20 13:58:28 +0000
3548@@ -0,0 +1,34 @@
3549+/*
3550+ * Copyright (C) 2016 Canonical, Ltd.
3551+ *
3552+ * This program is free software; you can redistribute it and/or modify
3553+ * it under the terms of the GNU General Public License as published by
3554+ * the Free Software Foundation; version 3.
3555+ *
3556+ * This program is distributed in the hope that it will be useful,
3557+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3558+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3559+ * GNU General Public License for more details.
3560+ *
3561+ * You should have received a copy of the GNU General Public License
3562+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3563+ */
3564+
3565+#include "MockOperation.h"
3566+
3567+MockOperation::MockOperation(QObject *parent) : QObject(parent)
3568+{
3569+}
3570+
3571+bool MockOperation::start(MockObserver *observer)
3572+{
3573+ Q_UNUSED(observer);
3574+ return true;
3575+}
3576+
3577+bool MockOperation::cancel()
3578+{
3579+ return true;
3580+}
3581+
3582+#include "MockOperation.moc"
3583
3584=== added file 'tests/qmltests/mocks/Biometryd/MockOperation.h'
3585--- tests/qmltests/mocks/Biometryd/MockOperation.h 1970-01-01 00:00:00 +0000
3586+++ tests/qmltests/mocks/Biometryd/MockOperation.h 2016-06-20 13:58:28 +0000
3587@@ -0,0 +1,36 @@
3588+/*
3589+ * Copyright (C) 2016 Canonical, Ltd.
3590+ *
3591+ * This program is free software; you can redistribute it and/or modify
3592+ * it under the terms of the GNU General Public License as published by
3593+ * the Free Software Foundation; version 3.
3594+ *
3595+ * This program is distributed in the hope that it will be useful,
3596+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3597+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3598+ * GNU General Public License for more details.
3599+ *
3600+ * You should have received a copy of the GNU General Public License
3601+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3602+ */
3603+
3604+#ifndef MOCK_OPERATION_H
3605+#define MOCK_OPERATION_H
3606+
3607+#include <QObject>
3608+
3609+class MockObserver;
3610+
3611+class MockOperation : public QObject
3612+{
3613+ Q_OBJECT
3614+ Q_DISABLE_COPY(MockOperation)
3615+
3616+public:
3617+ explicit MockOperation(QObject *parent = 0);
3618+
3619+ Q_INVOKABLE bool start(MockObserver* observer);
3620+ Q_INVOKABLE bool cancel();
3621+};
3622+
3623+#endif // MOCK_OPERATION_H
3624
3625=== added file 'tests/qmltests/mocks/Biometryd/MockService.cpp'
3626--- tests/qmltests/mocks/Biometryd/MockService.cpp 1970-01-01 00:00:00 +0000
3627+++ tests/qmltests/mocks/Biometryd/MockService.cpp 2016-06-20 13:58:28 +0000
3628@@ -0,0 +1,42 @@
3629+/*
3630+ * Copyright (C) 2016 Canonical, Ltd.
3631+ *
3632+ * This program is free software; you can redistribute it and/or modify
3633+ * it under the terms of the GNU General Public License as published by
3634+ * the Free Software Foundation; version 3.
3635+ *
3636+ * This program is distributed in the hope that it will be useful,
3637+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3638+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3639+ * GNU General Public License for more details.
3640+ *
3641+ * You should have received a copy of the GNU General Public License
3642+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3643+ */
3644+
3645+#include "MockService.h"
3646+
3647+MockService::MockService(QObject *parent)
3648+ : QObject(parent)
3649+ , m_device(new MockDevice(this))
3650+ , m_available(false)
3651+{
3652+}
3653+
3654+MockDevice* MockService::defaultDevice()
3655+{
3656+ return m_device;
3657+}
3658+
3659+bool MockService::isAvailable() const
3660+{
3661+ return m_available;
3662+}
3663+
3664+void MockService::setAvailable(const bool available)
3665+{
3666+ m_available = available;
3667+ Q_EMIT (availableChanged(available));
3668+}
3669+
3670+#include "MockService.moc"
3671
3672=== added file 'tests/qmltests/mocks/Biometryd/MockService.h'
3673--- tests/qmltests/mocks/Biometryd/MockService.h 1970-01-01 00:00:00 +0000
3674+++ tests/qmltests/mocks/Biometryd/MockService.h 2016-06-20 13:58:28 +0000
3675@@ -0,0 +1,46 @@
3676+/*
3677+ * Copyright (C) 2016 Canonical, Ltd.
3678+ *
3679+ * This program is free software; you can redistribute it and/or modify
3680+ * it under the terms of the GNU General Public License as published by
3681+ * the Free Software Foundation; version 3.
3682+ *
3683+ * This program is distributed in the hope that it will be useful,
3684+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3685+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3686+ * GNU General Public License for more details.
3687+ *
3688+ * You should have received a copy of the GNU General Public License
3689+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3690+ */
3691+
3692+#ifndef MOCK_SERVICE_H
3693+#define MOCK_SERVICE_H
3694+
3695+#include <QObject>
3696+
3697+#include "MockDevice.h"
3698+
3699+class MockService : public QObject
3700+{
3701+ Q_OBJECT
3702+ Q_DISABLE_COPY(MockService)
3703+
3704+public:
3705+ explicit MockService(QObject *parent = 0);
3706+ Q_PROPERTY(MockDevice* defaultDevice READ defaultDevice CONSTANT)
3707+ Q_PROPERTY(bool available READ isAvailable NOTIFY availableChanged)
3708+
3709+ MockDevice* defaultDevice();
3710+ bool isAvailable() const;
3711+ Q_INVOKABLE void setAvailable(const bool available); // mock only
3712+
3713+Q_SIGNALS:
3714+ void availableChanged(bool);
3715+
3716+private:
3717+ MockDevice* m_device;
3718+ bool m_available;
3719+};
3720+
3721+#endif // MOCK_SERVICE_H
3722
3723=== added file 'tests/qmltests/mocks/Biometryd/MockTemplateStore.cpp'
3724--- tests/qmltests/mocks/Biometryd/MockTemplateStore.cpp 1970-01-01 00:00:00 +0000
3725+++ tests/qmltests/mocks/Biometryd/MockTemplateStore.cpp 2016-06-20 13:58:28 +0000
3726@@ -0,0 +1,56 @@
3727+/*
3728+ * Copyright (C) 2016 Canonical, Ltd.
3729+ *
3730+ * This program is free software; you can redistribute it and/or modify
3731+ * it under the terms of the GNU General Public License as published by
3732+ * the Free Software Foundation; version 3.
3733+ *
3734+ * This program is distributed in the hope that it will be useful,
3735+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3736+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3737+ * GNU General Public License for more details.
3738+ *
3739+ * You should have received a copy of the GNU General Public License
3740+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3741+ */
3742+
3743+#include "MockTemplateStore.h"
3744+
3745+MockTemplateStore::MockTemplateStore(QObject *parent)
3746+{
3747+ Q_UNUSED(parent);
3748+}
3749+
3750+MockSizeQuery* MockTemplateStore::size(MockUser* user)
3751+{
3752+ Q_UNUSED(user);
3753+ return new MockSizeQuery(this);
3754+}
3755+
3756+MockEnrollment* MockTemplateStore::enroll(MockUser* user)
3757+{
3758+ Q_UNUSED(user);
3759+ return new MockEnrollment(this);
3760+}
3761+
3762+MockClearance* MockTemplateStore::clear(MockUser* user)
3763+{
3764+ Q_UNUSED(user);
3765+ return new MockClearance(this);
3766+}
3767+
3768+MockRemoval* MockTemplateStore::remove(MockUser* user,
3769+ const QString &templateId)
3770+{
3771+ Q_UNUSED(user);
3772+ Q_UNUSED(templateId);
3773+ return new MockRemoval(this);
3774+}
3775+
3776+MockList* MockTemplateStore::list(MockUser* user)
3777+{
3778+ Q_UNUSED(user);
3779+ return new MockList(this);
3780+}
3781+
3782+#include "MockTemplateStore.moc"
3783
3784=== added file 'tests/qmltests/mocks/Biometryd/MockTemplateStore.h'
3785--- tests/qmltests/mocks/Biometryd/MockTemplateStore.h 1970-01-01 00:00:00 +0000
3786+++ tests/qmltests/mocks/Biometryd/MockTemplateStore.h 2016-06-20 13:58:28 +0000
3787@@ -0,0 +1,86 @@
3788+/*
3789+ * Copyright (C) 2016 Canonical, Ltd.
3790+ *
3791+ * This program is free software; you can redistribute it and/or modify
3792+ * it under the terms of the GNU General Public License as published by
3793+ * the Free Software Foundation; version 3.
3794+ *
3795+ * This program is distributed in the hope that it will be useful,
3796+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3797+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3798+ * GNU General Public License for more details.
3799+ *
3800+ * You should have received a copy of the GNU General Public License
3801+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3802+ */
3803+
3804+#ifndef MOCK_TEMPLATESTORE_H
3805+#define MOCK_TEMPLATESTORE_H
3806+
3807+#include <QObject>
3808+#include "MockOperation.h"
3809+
3810+class MockUser;
3811+
3812+class MockSizeQuery : public MockOperation
3813+{
3814+ Q_OBJECT
3815+public:
3816+ MockSizeQuery(QObject *parent) : MockOperation(parent)
3817+ {
3818+ }
3819+};
3820+
3821+class MockEnrollment : public MockOperation
3822+{
3823+ Q_OBJECT
3824+public:
3825+ MockEnrollment(QObject *parent) : MockOperation(parent)
3826+ {
3827+ }
3828+};
3829+
3830+class MockClearance : public MockOperation
3831+{
3832+ Q_OBJECT
3833+public:
3834+ MockClearance(QObject *parent) : MockOperation(parent)
3835+ {
3836+ }
3837+};
3838+
3839+class MockRemoval : public MockOperation
3840+{
3841+ Q_OBJECT
3842+public:
3843+ MockRemoval(QObject *parent) : MockOperation(parent)
3844+ {
3845+ }
3846+};
3847+
3848+class MockList : public MockOperation
3849+{
3850+ Q_OBJECT
3851+public:
3852+ MockList(QObject *parent) : MockOperation(parent)
3853+ {
3854+ }
3855+};
3856+
3857+class MockTemplateStore : public QObject
3858+{
3859+ Q_OBJECT
3860+ Q_DISABLE_COPY(MockTemplateStore)
3861+
3862+public:
3863+ explicit MockTemplateStore(QObject *parent = 0);
3864+
3865+ Q_INVOKABLE MockSizeQuery* size(MockUser* user);
3866+ Q_INVOKABLE MockEnrollment* enroll(MockUser* user);
3867+ Q_INVOKABLE MockClearance* clear(MockUser* user);
3868+ Q_INVOKABLE MockRemoval* remove(MockUser* user,
3869+ const QString &templateId);
3870+ Q_INVOKABLE MockList* list(MockUser* user);
3871+};
3872+
3873+#endif // MOCK_TEMPLATESTORE_H
3874
3875=== added file 'tests/qmltests/mocks/Biometryd/MockUser.cpp'
3876--- tests/qmltests/mocks/Biometryd/MockUser.cpp 1970-01-01 00:00:00 +0000
3877+++ tests/qmltests/mocks/Biometryd/MockUser.cpp 2016-06-20 13:58:28 +0000
3878@@ -0,0 +1,33 @@
3879+/*
3880+ * Copyright (C) 2016 Canonical, Ltd.
3881+ *
3882+ * This program is free software; you can redistribute it and/or modify
3883+ * it under the terms of the GNU General Public License as published by
3884+ * the Free Software Foundation; version 3.
3885+ *
3886+ * This program is distributed in the hope that it will be useful,
3887+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3888+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3889+ * GNU General Public License for more details.
3890+ *
3891+ * You should have received a copy of the GNU General Public License
3892+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3893+ */
3894+
3895+#include "MockUser.h"
3896+
3897+MockUser::MockUser(QObject *parent) : QObject(parent)
3898+{
3899+}
3900+
3901+int MockUser::uid() const
3902+{
3903+ return m_uid;
3904+}
3905+
3906+void MockUser::setUid(const int &uid)
3907+{
3908+ m_uid = uid;
3909+}
3910+
3911+#include "MockUser.moc"
3912
3913=== added file 'tests/qmltests/mocks/Biometryd/MockUser.h'
3914--- tests/qmltests/mocks/Biometryd/MockUser.h 1970-01-01 00:00:00 +0000
3915+++ tests/qmltests/mocks/Biometryd/MockUser.h 2016-06-20 13:58:28 +0000
3916@@ -0,0 +1,38 @@
3917+/*
3918+ * Copyright (C) 2016 Canonical, Ltd.
3919+ *
3920+ * This program is free software; you can redistribute it and/or modify
3921+ * it under the terms of the GNU General Public License as published by
3922+ * the Free Software Foundation; version 3.
3923+ *
3924+ * This program is distributed in the hope that it will be useful,
3925+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3926+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3927+ * GNU General Public License for more details.
3928+ *
3929+ * You should have received a copy of the GNU General Public License
3930+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3931+ */
3932+
3933+#ifndef MOCK_USER_H
3934+#define MOCK_USER_H
3935+
3936+#include <QObject>
3937+
3938+class MockUser : public QObject
3939+{
3940+ Q_OBJECT
3941+ Q_DISABLE_COPY(MockUser)
3942+
3943+public:
3944+ explicit MockUser(QObject *parent = 0);
3945+ Q_PROPERTY(int uid READ uid WRITE setUid)
3946+
3947+ int uid() const;
3948+ void setUid(const int &uid);
3949+
3950+private:
3951+ int m_uid = 0;
3952+};
3953+
3954+#endif // MOCK_USER_H
3955
3956=== added file 'tests/qmltests/mocks/Biometryd/plugin.cpp'
3957--- tests/qmltests/mocks/Biometryd/plugin.cpp 1970-01-01 00:00:00 +0000
3958+++ tests/qmltests/mocks/Biometryd/plugin.cpp 2016-06-20 13:58:28 +0000
3959@@ -0,0 +1,60 @@
3960+/*
3961+ * Copyright (C) 2014 Canonical, Ltd.
3962+ *
3963+ * This program is free software; you can redistribute it and/or modify
3964+ * it under the terms of the GNU General Public License as published by
3965+ * the Free Software Foundation; version 3.
3966+ *
3967+ * This program is distributed in the hope that it will be useful,
3968+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3969+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3970+ * GNU General Public License for more details.
3971+ *
3972+ * You should have received a copy of the GNU General Public License
3973+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3974+ */
3975+
3976+#include "plugin.h"
3977+
3978+#include "MockDevice.h"
3979+#include "MockFingerprintReader.h"
3980+#include "MockObserver.h"
3981+#include "MockOperation.h"
3982+#include "MockService.h"
3983+#include "MockTemplateStore.h"
3984+#include "MockUser.h"
3985+
3986+#include <QtQml>
3987+
3988+void BackendPlugin::registerTypes(const char *uri)
3989+{
3990+ Q_ASSERT(uri == QLatin1String("Biometryd"));
3991+
3992+ qmlRegisterType<MockObserver>(uri, 0, 0, "Observer");
3993+ qmlRegisterType<MockUser>(uri, 0, 0, "User");
3994+
3995+ qmlRegisterUncreatableType<MockDevice>(uri, 0, 0, "Device", "Rely on Biometryd.instance");
3996+
3997+ qmlRegisterUncreatableType<MockOperation>(uri, 0, 0, "Operation", "Rely on Biometryd.instance");
3998+ qmlRegisterUncreatableType<MockSizeQuery>(uri, 0, 0, "SizeQuery", "Rely on Biometryd.instance");
3999+ qmlRegisterUncreatableType<MockEnrollment>(uri, 0, 0, "Enrollment", "Rely on Biometryd.instance");
4000+ qmlRegisterUncreatableType<MockClearance>(uri, 0, 0, "Clearance", "Rely on Biometryd.instance");
4001+ qmlRegisterUncreatableType<MockTemplateStore>(uri, 0, 0, "TemplateStore", "Rely on Biometryd.instance");
4002+ qmlRegisterUncreatableType<MockRemoval>(uri, 0, 0, "Removal", "Rely on Biometryd.instance");
4003+ qmlRegisterUncreatableType<MockList>(uri, 0, 0, "List", "Rely on Biometryd.instance");
4004+
4005+ qmlRegisterSingletonType<MockService>(
4006+ uri, 0, 0, "Biometryd",
4007+ [](QQmlEngine*, QJSEngine*) -> QObject*
4008+ {
4009+ return new MockService;
4010+ }
4011+ );
4012+ qmlRegisterSingletonType<MockFingerprintReader>(
4013+ uri, 0, 0, "FingerprintReader",
4014+ [](QQmlEngine*, QJSEngine*) -> QObject*
4015+ {
4016+ return new MockFingerprintReader;
4017+ }
4018+ );
4019+}
4020
4021=== added file 'tests/qmltests/mocks/Biometryd/plugin.h'
4022--- tests/qmltests/mocks/Biometryd/plugin.h 1970-01-01 00:00:00 +0000
4023+++ tests/qmltests/mocks/Biometryd/plugin.h 2016-06-20 13:58:28 +0000
4024@@ -0,0 +1,31 @@
4025+/*
4026+ * Copyright (C) 2016 Canonical, Ltd.
4027+ *
4028+ * This program is free software; you can redistribute it and/or modify
4029+ * it under the terms of the GNU General Public License as published by
4030+ * the Free Software Foundation; version 3.
4031+ *
4032+ * This program is distributed in the hope that it will be useful,
4033+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4034+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4035+ * GNU General Public License for more details.
4036+ *
4037+ * You should have received a copy of the GNU General Public License
4038+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4039+ */
4040+
4041+#ifndef MOCK_BIOMETRYD_PLUGIN_H
4042+#define MOCK_BIOMETRYD_PLUGIN_H
4043+
4044+#include <QQmlExtensionPlugin>
4045+
4046+class BackendPlugin : public QQmlExtensionPlugin
4047+{
4048+ Q_OBJECT
4049+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
4050+
4051+public:
4052+ void registerTypes(const char *uri) override;
4053+};
4054+
4055+#endif // MOCK_BIOMETRYD_PLUGIN_H
4056
4057=== added file 'tests/qmltests/mocks/Biometryd/qmldir'
4058--- tests/qmltests/mocks/Biometryd/qmldir 1970-01-01 00:00:00 +0000
4059+++ tests/qmltests/mocks/Biometryd/qmldir 2016-06-20 13:58:28 +0000
4060@@ -0,0 +1,2 @@
4061+module Biometryd
4062+plugin MockBiometryd
4063
4064=== added file 'tests/qmltests/mocks/CMakeLists.txt'
4065--- tests/qmltests/mocks/CMakeLists.txt 1970-01-01 00:00:00 +0000
4066+++ tests/qmltests/mocks/CMakeLists.txt 2016-06-20 13:58:28 +0000
4067@@ -0,0 +1,32 @@
4068+include(QmlPlugins)
4069+
4070+# Set up and optionally install a mock plugin for ubuntu-settings-components.
4071+#
4072+# add_usc_mock(plugin version path
4073+# [PREFIX string] # Install the plugin to the specified prefix under unity8 private plugin directory
4074+# [...] # See export_qmlfiles and export_qmlplugin documentation for more options
4075+# )
4076+
4077+macro(add_usc_mock PLUGIN VERSION PATH)
4078+ set(single PREFIX)
4079+ cmake_parse_arguments(MOCK "" "${single}" "" ${ARGN})
4080+
4081+ if(MOCK_PREFIX)
4082+ export_qmlfiles(${PLUGIN} ${PATH}
4083+ DESTINATION ${SHELL_INSTALL_QML}/${MOCK_PREFIX}
4084+ TARGET_PREFIX ${MOCK_PREFIX}-Mock
4085+ ${MOCK_UNPARSED_ARGUMENTS}
4086+ )
4087+ export_qmlplugin(${PLUGIN} ${VERSION} ${PATH}
4088+ DESTINATION ${SHELL_INSTALL_QML}/${MOCK_PREFIX}
4089+ TARGET_PREFIX ${MOCK_PREFIX}-Mock
4090+ ${MOCK_UNPARSED_ARGUMENTS}
4091+ )
4092+ else()
4093+ export_qmlfiles(${PLUGIN} ${PATH} TARGET_PREFIX Mock ${MOCK_UNPARSED_ARGUMENTS})
4094+ export_qmlplugin(${PLUGIN} ${VERSION} ${PATH} TARGET_PREFIX Mock ${MOCK_UNPARSED_ARGUMENTS})
4095+ endif()
4096+endmacro()
4097+
4098+add_subdirectory(Biometryd)
4099+add_subdirectory(GSettings.1.0)
4100
4101=== added directory 'tests/qmltests/mocks/GSettings.1.0'
4102=== added file 'tests/qmltests/mocks/GSettings.1.0/CMakeLists.txt'
4103--- tests/qmltests/mocks/GSettings.1.0/CMakeLists.txt 1970-01-01 00:00:00 +0000
4104+++ tests/qmltests/mocks/GSettings.1.0/CMakeLists.txt 2016-06-20 13:58:28 +0000
4105@@ -0,0 +1,20 @@
4106+include_directories(
4107+ ${CMAKE_CURRENT_BINARY_DIR}
4108+ ${Qt5Core_INCLUDE_DIRS}
4109+ ${Qt5Quick_INCLUDE_DIRS}
4110+)
4111+
4112+set(GSettingsQML_SOURCES
4113+ fake_gsettings.cpp
4114+ plugin.cpp
4115+)
4116+
4117+add_library(FakeGSettingsQml MODULE ${GSettingsQML_SOURCES})
4118+target_link_libraries(FakeGSettingsQml
4119+ ${Qt5Core_LIBRARIES}
4120+ ${Qt5Quick_LIBRARIES}
4121+)
4122+
4123+qt5_use_modules(FakeGSettingsQml Qml)
4124+
4125+add_usc_mock(GSettings 1.0 GSettings.1.0 TARGETS FakeGSettingsQml)
4126
4127=== added file 'tests/qmltests/mocks/GSettings.1.0/fake_gsettings.cpp'
4128--- tests/qmltests/mocks/GSettings.1.0/fake_gsettings.cpp 1970-01-01 00:00:00 +0000
4129+++ tests/qmltests/mocks/GSettings.1.0/fake_gsettings.cpp 2016-06-20 13:58:28 +0000
4130@@ -0,0 +1,124 @@
4131+/*
4132+ * Copyright 2013 Canonical Ltd.
4133+ *
4134+ * This program is free software; you can redistribute it and/or modify
4135+ * it under the terms of the GNU Lesser General Public License as published by
4136+ * the Free Software Foundation; version 3.
4137+ *
4138+ * This program is distributed in the hope that it will be useful,
4139+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4140+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4141+ * GNU Lesser General Public License for more details.
4142+ *
4143+ * You should have received a copy of the GNU Lesser General Public License
4144+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4145+ */
4146+
4147+#include "fake_gsettings.h"
4148+
4149+#include <QDebug>
4150+
4151+GSettingsControllerQml* GSettingsControllerQml::s_controllerInstance = 0;
4152+
4153+GSettingsControllerQml::GSettingsControllerQml()
4154+ : m_fingerprintNames()
4155+{
4156+}
4157+
4158+GSettingsControllerQml::~GSettingsControllerQml() {
4159+ s_controllerInstance = 0;
4160+}
4161+
4162+GSettingsControllerQml* GSettingsControllerQml::instance() {
4163+ if (!s_controllerInstance) {
4164+ s_controllerInstance = new GSettingsControllerQml();
4165+ }
4166+ return s_controllerInstance;
4167+}
4168+
4169+QVariantMap GSettingsControllerQml::fingerprintNames() const
4170+{
4171+ return m_fingerprintNames;
4172+}
4173+
4174+void GSettingsControllerQml::setFingerprintNames(QVariantMap map)
4175+{
4176+ if (map != m_fingerprintNames) {
4177+ m_fingerprintNames = map;
4178+ Q_EMIT fingerprintNamesChanged();
4179+ }
4180+}
4181+
4182+GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) {
4183+}
4184+
4185+QByteArray GSettingsSchemaQml::id() const {
4186+ return m_id;
4187+}
4188+
4189+void GSettingsSchemaQml::setId(const QByteArray &id) {
4190+ if (!m_id.isEmpty()) {
4191+ qWarning("GSettings.schema.id may only be set on construction");
4192+ return;
4193+ }
4194+
4195+ m_id = id;
4196+}
4197+
4198+QByteArray GSettingsSchemaQml::path() const {
4199+ return m_path;
4200+}
4201+
4202+void GSettingsSchemaQml::setPath(const QByteArray &path) {
4203+ if (!m_path.isEmpty()) {
4204+ qWarning("GSettings.schema.path may only be set on construction");
4205+ return;
4206+ }
4207+
4208+ m_path = path;
4209+}
4210+
4211+GSettingsQml::GSettingsQml(QObject *parent)
4212+ : QObject(parent),
4213+ m_valid(false)
4214+{
4215+ m_schema = new GSettingsSchemaQml(this);
4216+}
4217+
4218+void GSettingsQml::classBegin()
4219+{
4220+}
4221+
4222+void GSettingsQml::componentComplete()
4223+{
4224+ // Emulate what the real GSettings module does, and only return undefined
4225+ // values until we are completed loading.
4226+ m_valid = true;
4227+
4228+ // FIXME: We should make this dynamic, instead of hard-coding all possible
4229+ // properties in one object. We should create properties based on the schema.
4230+ connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::fingerprintNamesChanged,
4231+ this, &GSettingsQml::fingerprintNamesChanged);
4232+
4233+ Q_EMIT fingerprintNamesChanged();
4234+}
4235+
4236+GSettingsSchemaQml * GSettingsQml::schema() const {
4237+ return m_schema;
4238+}
4239+
4240+QVariantMap GSettingsQml::fingerprintNames() const
4241+{
4242+ if (m_valid && m_schema->id() == "com.ubuntu.touch.system") {
4243+ return GSettingsControllerQml::instance()->fingerprintNames();
4244+ } else {
4245+ return QVariantMap();
4246+ }
4247+}
4248+
4249+void GSettingsQml::setFingerprintNames(const QVariantMap &map)
4250+{
4251+ if (m_valid && m_schema->id() == "com.ubuntu.touch.system") {
4252+ GSettingsControllerQml::instance()->setFingerprintNames(map);
4253+ }
4254+}
4255
4256=== added file 'tests/qmltests/mocks/GSettings.1.0/fake_gsettings.h'
4257--- tests/qmltests/mocks/GSettings.1.0/fake_gsettings.h 1970-01-01 00:00:00 +0000
4258+++ tests/qmltests/mocks/GSettings.1.0/fake_gsettings.h 2016-06-20 13:58:28 +0000
4259@@ -0,0 +1,101 @@
4260+/*
4261+ * Copyright 2013 Canonical Ltd.
4262+ *
4263+ * This program is free software; you can redistribute it and/or modify
4264+ * it under the terms of the GNU Lesser General Public License as published by
4265+ * the Free Software Foundation; version 3.
4266+ *
4267+ * This program is distributed in the hope that it will be useful,
4268+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4269+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4270+ * GNU Lesser General Public License for more details.
4271+ *
4272+ * You should have received a copy of the GNU Lesser General Public License
4273+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4274+ */
4275+
4276+#ifndef FAKE_GSETTINGS_H
4277+#define FAKE_GSETTINGS_H
4278+
4279+#include <QList>
4280+#include <QObject>
4281+#include <QQmlParserStatus>
4282+#include <QStringList>
4283+#include <QVariant>
4284+
4285+class GSettingsSchemaQml: public QObject
4286+{
4287+ Q_OBJECT
4288+
4289+ Q_PROPERTY(QByteArray id READ id WRITE setId)
4290+public:
4291+ GSettingsSchemaQml(QObject *parent = nullptr);
4292+
4293+ QByteArray id() const;
4294+ void setId(const QByteArray &id);
4295+
4296+ QByteArray path() const;
4297+ void setPath(const QByteArray &path);
4298+
4299+private:
4300+ QByteArray m_id;
4301+ QByteArray m_path;
4302+};
4303+
4304+class GSettingsQml: public QObject, public QQmlParserStatus
4305+{
4306+ Q_OBJECT
4307+ Q_INTERFACES(QQmlParserStatus)
4308+
4309+ Q_PROPERTY(GSettingsSchemaQml* schema READ schema NOTIFY schemaChanged)
4310+ Q_PROPERTY(QVariantMap fingerprintNames
4311+ READ fingerprintNames
4312+ WRITE setFingerprintNames
4313+ NOTIFY fingerprintNamesChanged)
4314+
4315+public:
4316+ GSettingsQml(QObject *parent = nullptr);
4317+
4318+ void classBegin() override;
4319+ void componentComplete() override;
4320+
4321+ GSettingsSchemaQml * schema() const;
4322+
4323+ QVariantMap fingerprintNames() const;
4324+ void setFingerprintNames(const QVariantMap &map);
4325+
4326+Q_SIGNALS:
4327+ void fingerprintNamesChanged();
4328+ void schemaChanged();
4329+
4330+private:
4331+ GSettingsSchemaQml* m_schema;
4332+ bool m_valid;
4333+
4334+ friend class GSettingsSchemaQml;
4335+};
4336+
4337+class GSettingsControllerQml: public QObject
4338+{
4339+ Q_OBJECT
4340+
4341+public:
4342+ static GSettingsControllerQml* instance();
4343+ ~GSettingsControllerQml();
4344+
4345+ Q_INVOKABLE QVariantMap fingerprintNames() const;
4346+ Q_INVOKABLE void setFingerprintNames(QVariantMap map);
4347+
4348+Q_SIGNALS:
4349+ void fingerprintNamesChanged();
4350+
4351+private:
4352+ GSettingsControllerQml();
4353+
4354+ QVariantMap m_fingerprintNames;
4355+
4356+ static GSettingsControllerQml* s_controllerInstance;
4357+ QList<GSettingsQml *> m_registeredGSettings;
4358+};
4359+
4360+#endif // FAKE_GSETTINGS_H
4361
4362=== added file 'tests/qmltests/mocks/GSettings.1.0/plugin.cpp'
4363--- tests/qmltests/mocks/GSettings.1.0/plugin.cpp 1970-01-01 00:00:00 +0000
4364+++ tests/qmltests/mocks/GSettings.1.0/plugin.cpp 2016-06-20 13:58:28 +0000
4365@@ -0,0 +1,33 @@
4366+/*
4367+ * Copyright (C) 2013 Canonical, Ltd.
4368+ *
4369+ * This program is free software; you can redistribute it and/or modify
4370+ * it under the terms of the GNU General Public License as published by
4371+ * the Free Software Foundation; version 3.
4372+ *
4373+ * This program is distributed in the hope that it will be useful,
4374+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4375+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4376+ * GNU General Public License for more details.
4377+ *
4378+ * You should have received a copy of the GNU General Public License
4379+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4380+ */
4381+
4382+#include "plugin.h"
4383+#include "fake_gsettings.h"
4384+
4385+#include <QtQml/qqml.h>
4386+
4387+static QObject* controllerProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
4388+{
4389+ return GSettingsControllerQml::instance();
4390+}
4391+
4392+void FakeGSettingsQmlPlugin::registerTypes(const char *uri)
4393+{
4394+ qmlRegisterSingletonType<GSettingsControllerQml>(uri, 1, 0, "GSettingsController", controllerProvider);
4395+ qmlRegisterType<GSettingsQml>(uri, 1, 0, "GSettings");
4396+ qmlRegisterUncreatableType<GSettingsSchemaQml>(uri, 1, 0, "GSettingsSchema",
4397+ "GSettingsSchema can only be used inside of a GSettings component");
4398+}
4399
4400=== added file 'tests/qmltests/mocks/GSettings.1.0/plugin.h'
4401--- tests/qmltests/mocks/GSettings.1.0/plugin.h 1970-01-01 00:00:00 +0000
4402+++ tests/qmltests/mocks/GSettings.1.0/plugin.h 2016-06-20 13:58:28 +0000
4403@@ -0,0 +1,31 @@
4404+/*
4405+ * Copyright (C) 2013 Canonical, Ltd.
4406+ *
4407+ * This program is free software; you can redistribute it and/or modify
4408+ * it under the terms of the GNU General Public License as published by
4409+ * the Free Software Foundation; version 3.
4410+ *
4411+ * This program is distributed in the hope that it will be useful,
4412+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4413+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4414+ * GNU General Public License for more details.
4415+ *
4416+ * You should have received a copy of the GNU General Public License
4417+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4418+ */
4419+
4420+#ifndef PLUGIN_H
4421+#define PLUGIN_H
4422+
4423+#include <QtQml/QQmlExtensionPlugin>
4424+
4425+class FakeGSettingsQmlPlugin : public QQmlExtensionPlugin
4426+{
4427+ Q_OBJECT
4428+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
4429+
4430+public:
4431+ void registerTypes(const char *uri) override;
4432+};
4433+
4434+#endif // PLUGIN_H
4435
4436=== added file 'tests/qmltests/mocks/GSettings.1.0/qmldir'
4437--- tests/qmltests/mocks/GSettings.1.0/qmldir 1970-01-01 00:00:00 +0000
4438+++ tests/qmltests/mocks/GSettings.1.0/qmldir 2016-06-20 13:58:28 +0000
4439@@ -0,0 +1,2 @@
4440+module GSettings
4441+plugin FakeGSettingsQml

Subscribers

People subscribed via source and target branches