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