Unity 8
NotificationMenuItemFactory.qml
1 /*
2  * Copyright 2013 Canonical Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authors:
17  * Nick Dedekind <nick.dedekind@canonical.com>
18  */
19 
20 import QtQuick 2.4
21 import Ubuntu.Components 1.3
22 import QMenuModel 0.1
23 import "../Components"
24 
25 Loader {
26  id: menuFactory
27 
28  property QtObject menuModel: null
29  property QtObject menuData: null
30  property int menuIndex : -1
31  property int maxHeight
32  readonly property bool fullscreen: menuData.type === "com.canonical.snapdecision.pinlock"
33  property url background: ""
34 
35  signal accepted()
36 
37  property var _map: {
38  "com.canonical.snapdecision.textfield": textfield,
39  "com.canonical.snapdecision.pinlock" : pinLock,
40  }
41 
42  sourceComponent: {
43  if (menuData.type !== undefined) {
44  var component = _map[menuData.type];
45  if (component !== undefined) {
46  if (component === pinLock && shell.hasLockedApp) {
47  // In case we are in emergency mode, just skip this unlock.
48  // Happens with two locked SIMs but the user clicks
49  // Emergency Call on the first unlock dialog.
50  // TODO: if we ever allow showing the indicators in
51  // emergency mode, we'll need to differentiate between
52  // user-initiated ones which we *do* want to show and the
53  // dialogs that appear on boot, which we don't. But for
54  // now we can get away with skipping all such dialogs.
55  menuModel.activate(menuIndex, false);
56  return null;
57  }
58  return component;
59  }
60  }
61  }
62 
63  function getExtendedProperty(object, propertyName, defaultValue) {
64  if (object && object.hasOwnProperty(propertyName)) {
65  return object[propertyName];
66  }
67  return defaultValue;
68  }
69 
70  Component {
71  id: textfield
72 
73  Column {
74  spacing: units.gu(2)
75 
76  anchors {
77  left: parent.left
78  right: parent.right
79  margins: spacing
80  }
81 
82  Component.onCompleted: {
83  menuModel.loadExtendedAttributes(menuIndex, {"x-echo-mode-password": "bool"});
84  checkBox.checked = menuData.ext.xEchoModePassword ? false : true
85  checkBoxRow.visible = menuData.ext.xEchoModePassword
86  }
87 
88  Label {
89  text: menuData.label
90  color: notification.sdFontColor
91  }
92 
93  TextField {
94  id: textfield
95 
96  // TODO using Qt.ImhNoPredictiveText here until lp #1291575 is fixed for ubuntu-ui-toolkit
97  inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText
98  anchors {
99  left: parent.left
100  right: parent.right
101  }
102  echoMode: checkBox.checked ? TextInput.Normal : TextInput.Password
103  height: units.gu(5)
104  Component.onCompleted: {
105  forceActiveFocus();
106  }
107  onTextChanged: {
108  menuModel.changeState(menuIndex, text);
109  }
110  onAccepted: {
111  menuFactory.accepted()
112  }
113  }
114 
115  Row {
116  id: checkBoxRow
117 
118  spacing: units.gu(.5)
119 
120  CheckBox {
121  id: checkBox
122 
123  checked: false
124  activeFocusOnPress: false
125  }
126 
127  Label {
128  anchors.verticalCenter: checkBox.verticalCenter
129  text: i18n.tr("Show password")
130  color: notification.sdFontColor
131 
132  MouseArea {
133  anchors.fill: parent
134  onClicked: { checkBox.checked = !checkBox.checked }
135  }
136  }
137  }
138  }
139  }
140 
141  Component {
142  id: pinLock
143 
144  Lockscreen {
145  anchors {
146  left: parent.left
147  right: parent.right
148  }
149  height: menuFactory.maxHeight
150  infoText: notification.summary
151  errorText: errorAction.valid ? errorAction.state : ""
152  retryText: notification.body
153  background: menuFactory.background
154  darkenBackground: 0.4
155 
156  onEntered: {
157  menuModel.changeState(menuIndex, passphrase);
158  clear(false);
159  }
160 
161  onCancel: {
162  menuModel.activate(menuIndex, false);
163  }
164 
165  onEmergencyCall: {
166  shell.startLockedApp("dialer-app");
167  menuModel.activate(menuIndex, false);
168  }
169 
170  property var extendedData: menuData && menuData.ext || undefined
171 
172  property var pinMinMaxAction : UnityMenuAction {
173  model: menuModel
174  index: menuIndex
175  name: getExtendedProperty(extendedData, "xCanonicalPinMinMax", "")
176 
177  onStateChanged: {
178  var min = pinMinMaxAction.state[0];
179  var max = pinMinMaxAction.state[1];
180 
181  if (min === 0) min = -1;
182  if (max === 0) max = -1;
183 
184  minPinLength = min
185  maxPinLength = max
186  }
187  }
188 
189  property var popupAction: UnityMenuAction {
190  model: menuModel
191  index: menuIndex
192  name: getExtendedProperty(extendedData, "xCanonicalPinPopup", "")
193  onStateChanged: {
194  if (state !== "")
195  showInfoPopup("", state);
196  }
197  }
198  onInfoPopupConfirmed: {
199  popupAction.activate();
200  }
201 
202  Timer {
203  id: errorTimer
204  interval: 4000;
205  running: false;
206  repeat: false
207  onTriggered: {
208  errorAction.activate();
209  }
210  }
211  property var errorAction: UnityMenuAction {
212  model: menuModel
213  index: menuIndex
214  name: getExtendedProperty(extendedData, "xCanonicalPinError", "")
215  onStateChanged: {
216  errorText = state;
217  if (state !== "") {
218  clear(true);
219  errorTimer.running = true;
220  }
221  }
222  }
223 
224  function loadAttributes() {
225  if (!menuModel || menuIndex == -1) return;
226  menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-pin-min-max': 'string',
227  'x-canonical-pin-popup': 'string',
228  'x-canonical-pin-error': 'string'});
229  }
230  Component.onCompleted: {
231  loadAttributes();
232  }
233  }
234  }
235 }