Unity 8
NarrowView.qml
1 /*
2  * Copyright (C) 2015-2016 Canonical, Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 import QtQuick 2.4
18 import QtQuick.Window 2.2
19 import Ubuntu.Components 1.3
20 import Ubuntu.Telephony 0.1 as Telephony
21 import "../Components"
22 
23 FocusScope {
24  id: root
25 
26  property alias dragHandleLeftMargin: coverPage.dragHandleLeftMargin
27  property alias launcherOffset: coverPage.launcherOffset
28  property alias currentIndex: loginList.currentIndex
29  property alias delayMinutes: delayedLockscreen.delayMinutes
30  property alias backgroundTopMargin: coverPage.backgroundTopMargin
31  property url background
32  property bool hasCustomBackground
33  property bool locked
34  property alias alphanumeric: loginList.alphanumeric
35  property alias userModel: loginList.model
36  property alias infographicModel: coverPage.infographicModel
37  property string sessionToStart
38  property bool waiting
39  readonly property bool fullyShown: coverPage.showProgress === 1 || lockscreen.shown
40  readonly property bool required: coverPage.required || lockscreen.required
41  readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running
42 
43  // so that it can be replaced in tests with a mock object
44  property var inputMethod: Qt.inputMethod
45 
46  signal selected(int index)
47  signal responded(string response)
48  signal tease()
49  signal emergencyCall()
50 
51  function showMessage(html) {
52  loginList.showMessage(html);
53  }
54 
55  function showPrompt(text, isSecret, isDefaultPrompt) {
56  loginList.showPrompt(text, isSecret, isDefaultPrompt);
57  }
58 
59  function showLastChance() {
60  /* TODO: when we finish support for resetting device after too many
61  failed logins, we should re-add this popup.
62  var title = lockscreen.alphaNumeric ?
63  i18n.tr("Sorry, incorrect passphrase.") :
64  i18n.tr("Sorry, incorrect passcode.");
65  var text = i18n.tr("This will be your last attempt.") + " " +
66  (lockscreen.alphaNumeric ?
67  i18n.tr("If passphrase is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted.") :
68  i18n.tr("If passcode is entered incorrectly, your phone will conduct a factory reset and all personal data will be deleted."));
69  lockscreen.showInfoPopup(title, text);
70  */
71  }
72 
73  function hide() {
74  lockscreen.hide();
75  coverPage.hide();
76  }
77 
78  function notifyAuthenticationSucceeded(showFakePassword) {
79  if (showFakePassword) {
80  loginList.showFakePassword();
81  }
82  }
83 
84  function notifyAuthenticationFailed() {
85  loginList.showError();
86  }
87 
88  function showErrorMessage(msg) {
89  coverPage.showErrorMessage(msg);
90  }
91 
92  function reset(forceShow) {
93  loginList.reset();
94  if (forceShow) {
95  coverPage.show();
96  }
97  }
98 
99  function tryToUnlock(toTheRight) {
100  var coverChanged = coverPage.shown;
101  lockscreen.maybeShow();
102  if (toTheRight) {
103  coverPage.hideRight();
104  } else {
105  coverPage.hide();
106  }
107  return coverChanged;
108  }
109 
110  onLockedChanged: {
111  if (locked) {
112  lockscreen.maybeShow();
113  } else {
114  lockscreen.hide();
115  }
116  }
117 
118  Showable {
119  id: lockscreen
120  objectName: "lockscreen"
121  anchors.fill: parent
122  shown: false
123 
124  showAnimation: StandardAnimation { property: "opacity"; to: 1 }
125  hideAnimation: StandardAnimation { property: "opacity"; to: 0 }
126 
127  Wallpaper {
128  id: lockscreenBackground
129  objectName: "lockscreenBackground"
130  anchors {
131  fill: parent
132  topMargin: root.backgroundTopMargin
133  }
134  source: root.background
135  }
136 
137  // Darken background to match CoverPage
138  Rectangle {
139  objectName: "lockscreenShade"
140  anchors.fill: parent
141  color: "black"
142  opacity: root.hasCustomBackground ? 0.4 : 0
143  }
144 
145  LoginList {
146  id: loginList
147  objectName: "loginList"
148 
149  anchors {
150  horizontalCenter: parent.horizontalCenter
151  top: parent.top
152  bottom: parent.bottom
153  }
154  width: units.gu(40)
155  boxVerticalOffset: units.gu(14)
156  enabled: !coverPage.shown && visible
157  visible: !delayedLockscreen.visible
158 
159  locked: root.locked
160 
161  onSelected: if (enabled) root.selected(index)
162  onResponded: root.responded(response)
163  }
164 
165  DelayedLockscreen {
166  id: delayedLockscreen
167  objectName: "delayedLockscreen"
168  anchors.fill: parent
169  visible: delayMinutes > 0
170  alphaNumeric: loginList.alphanumeric
171  }
172 
173  function maybeShow() {
174  if (root.locked && !shown) {
175  showNow();
176  }
177  }
178  }
179 
180  Rectangle {
181  anchors.fill: parent
182  color: "black"
183  opacity: coverPage.showProgress * 0.8
184  }
185 
186  CoverPage {
187  id: coverPage
188  objectName: "coverPage"
189  height: parent.height
190  width: parent.width
191  background: root.background
192  hasCustomBackground: root.hasCustomBackground
193  draggable: !root.waiting
194  onTease: root.tease()
195  onClicked: hide()
196 
197  onShowProgressChanged: {
198  if (showProgress === 1) {
199  loginList.reset();
200  } else if (showProgress === 0) {
201  loginList.tryToUnlock();
202  }
203  }
204 
205  Clock {
206  anchors {
207  top: parent.top
208  topMargin: units.gu(2)
209  horizontalCenter: parent.horizontalCenter
210  }
211  }
212  }
213 
214  StyledItem {
215  id: bottomBar
216  visible: lockscreen.shown
217  height: units.gu(4)
218 
219  anchors.left: parent.left
220  anchors.right: parent.right
221  anchors.top: parent.bottom
222  anchors.topMargin: - height * (1 - coverPage.showProgress)
223  - (inputMethod && inputMethod.visible ?
224  inputMethod.keyboardRectangle.height : 0)
225 
226  Rectangle {
227  color: UbuntuColors.porcelain // matches OSK background
228  anchors.fill: parent
229  }
230 
231  Label {
232  text: i18n.tr("Cancel")
233  anchors.left: parent.left
234  anchors.leftMargin: units.gu(2)
235  anchors.top: parent.top
236  anchors.bottom: parent.bottom
237  verticalAlignment: Text.AlignVCenter
238  font.weight: Font.Light
239  fontSize: "small"
240  color: UbuntuColors.slate
241 
242  AbstractButton {
243  anchors.fill: parent
244  anchors.leftMargin: -units.gu(2)
245  anchors.rightMargin: -units.gu(2)
246  onClicked: coverPage.show()
247  }
248  }
249 
250  Label {
251  objectName: "emergencyCallLabel"
252  text: callManager.hasCalls ? i18n.tr("Return to Call") : i18n.tr("Emergency")
253  anchors.right: parent.right
254  anchors.rightMargin: units.gu(2)
255  anchors.top: parent.top
256  anchors.bottom: parent.bottom
257  verticalAlignment: Text.AlignVCenter
258  font.weight: Font.Light
259  fontSize: "small"
260  color: UbuntuColors.slate
261  // TODO: uncomment once bug 1616538 is fixed
262  // visible: telepathyHelper.ready && telepathyHelper.emergencyCallsAvailable
263  enabled: visible
264 
265  AbstractButton {
266  anchors.fill: parent
267  anchors.leftMargin: -units.gu(2)
268  anchors.rightMargin: -units.gu(2)
269  onClicked: root.emergencyCall()
270  }
271  }
272  }
273 
274  // FIXME: It's difficult to keep something tied closely to the OSK (bug
275  // 1616163). But as a hack to avoid the background peeking out,
276  // we add an extra Rectangle that just serves to hide the background
277  // during OSK animations.
278  Rectangle {
279  visible: bottomBar.visible
280  height: inputMethod && inputMethod.visible ?
281  inputMethod.keyboardRectangle.height : 0
282  anchors.bottom: parent.bottom
283  anchors.left: parent.left
284  anchors.right: parent.right
285  color: UbuntuColors.porcelain
286  }
287 }