Merge lp:~jonas-drange/ubuntu-settings-components/fingerprint into lp:~registry/ubuntu-settings-components/trunk

Proposed by Jonas G. Drange
Status: Work in progress
Proposed branch: lp:~jonas-drange/ubuntu-settings-components/fingerprint
Merge into: lp:~registry/ubuntu-settings-components/trunk
Diff against target: 4419 lines (+4053/-18)
55 files modified
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 (+440/-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 (+388/-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:~jonas-drange/ubuntu-settings-components/fingerprint
Reviewer Review Type Date Requested Status
Registry Administrators Pending
Review via email: mp+289292@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.
 * Did you perform an exploratory manual test run of your code change and any related functionality?
 TBD
 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
 N/A
 * If you changed the UI, has there been a design review?
 TBD
 * If you changed localized strings, has the POT file been updated?
 TBD

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

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

mature the example

112. By Jonas G. Drange

merge trunk

113. By Jonas G. Drange

comp page

114. By Jonas G. Drange

add fingerprint qml test

115. By Jonas G. Drange

add qml tests

116. By Jonas G. Drange

use predicted signals and methods from discussions with tvoss

117. By Jonas G. Drange

remove dangling function keyword

118. By Jonas G. Drange

PageHeader crashes, use title instead

119. By Jonas G. Drange

conform to spec

120. By Jonas G. Drange

doc, sort props

Revision history for this message
Jonas G. Drange (jonas-drange) :
121. By Jonas G. Drange

implement some of the qml binding features

122. By Jonas G. Drange

add mocking

123. By Jonas G. Drange

add mocked biometryd

124. By Jonas G. Drange

rewrite tests to use mocking

125. By Jonas G. Drange

working enrollment test

126. By Jonas G. Drange

make enrollment work once again, albeit with deprecated animations

127. By Jonas G. Drange

init provider

128. By Jonas G. Drange

use qrc to put the paths in the binary (compressed)

129. By Jonas G. Drange

undo test comment

130. By Jonas G. Drange

small fixes, make renderPath private

131. By Jonas G. Drange

remove debug stuff in fingerprint page

132. By Jonas G. Drange

remove debug stuff in fingerprint page

133. By Jonas G. Drange

add test for fingerprint visual

134. By Jonas G. Drange

fix a lot of details

135. By Jonas G. Drange

some comments

136. By Jonas G. Drange

new paths from design

137. By Jonas G. Drange

add svg dep

138. By Jonas G. Drange

move paths to assets instead, add everything to qrc to get it compressed.

139. By Jonas G. Drange

use png as drop shadows

140. By Jonas G. Drange

fix broken transparent pngs

141. By Jonas G. Drange

buttons per spec

142. By Jonas G. Drange

biometryd is a depend of the binary package

143. By Jonas G. Drange

sync with trunk

144. By Jonas G. Drange

remove spurious mockoperation

145. By Jonas G. Drange

reverse X axis

146. By Jonas G. Drange

animated enrollment

147. By Jonas G. Drange

clean up cancel logic, add available to mock and test it

148. By Jonas G. Drange

add circular segment, completing the done animation

149. By Jonas G. Drange

remove unused asset

150. By Jonas G. Drange

add direction visual

151. By Jonas G. Drange

add red translucent rectangle for each scanner mask

152. By Jonas G. Drange

drop svg dep

153. By Jonas G. Drange

update pot

154. By Jonas G. Drange

size op only on available

155. By Jonas G. Drange

fix some design issues

156. By Jonas G. Drange

have failed and success screens on same page

157. By Jonas G. Drange

first stab at smart rotation

158. By Jonas G. Drange

complete directionvisual

Revision history for this message
Jonas G. Drange (jonas-drange) :
159. By Jonas G. Drange

start working on name story

160. By Jonas G. Drange

first part of named templates

161. By Jonas G. Drange

refactor tests, and add the last piece of the naming

162. By Jonas G. Drange

update pot

Unmerged revisions

162. By Jonas G. Drange

update pot

161. By Jonas G. Drange

refactor tests, and add the last piece of the naming

160. By Jonas G. Drange

first part of named templates

159. By Jonas G. Drange

start working on name story

158. By Jonas G. Drange

complete directionvisual

157. By Jonas G. Drange

first stab at smart rotation

156. By Jonas G. Drange

have failed and success screens on same page

155. By Jonas G. Drange

fix some design issues

154. By Jonas G. Drange

size op only on available

153. By Jonas G. Drange

update pot

Preview Diff

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

Subscribers

People subscribed via source and target branches

to all changes: