GCC Code Coverage Report


Directory: ./
File: panels/wwan/cc-wwan-sim-lock-dialog.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 122 0.0%
Functions: 0 15 0.0%
Branches: 0 63 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* cc-wwan-network-dialog.c
3 *
4 * Copyright 2019,2022 Purism SPC
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author(s):
20 * Mohammed Sadiq <sadiq@sadiqpk.org>
21 *
22 * SPDX-License-Identifier: GPL-3.0-or-later
23 */
24
25 #undef G_LOG_DOMAIN
26 #define G_LOG_DOMAIN "cc-wwan-sim-lock-dialog"
27
28 #include <config.h>
29 #include <glib/gi18n.h>
30 #include <libmm-glib.h>
31
32 #include "cc-wwan-sim-lock-dialog.h"
33 #include "cc-wwan-resources.h"
34
35 /**
36 * @short_description: Dialog to manage SIM Locks like PIN
37 */
38
39 #define PIN_MINIMUM_LENGTH 4
40 #define PIN_MAXIMUM_LENGTH 8
41
42 struct _CcWwanSimLockDialog
43 {
44 GtkDialog parent_instance;
45
46 CcWwanDevice *device;
47
48 GtkButton *apply_button;
49 GtkStack *button_stack;
50 GtkGrid *lock_change_grid;
51 AdwSwitchRow *lock_row;
52 GtkEntry *new_pin_entry;
53 GtkButton *next_button;
54 GtkEntry *pin_confirm_entry;
55 GtkEntry *pin_entry;
56 GtkStack *pin_settings_stack;
57 };
58
59 G_DEFINE_TYPE (CcWwanSimLockDialog, cc_wwan_sim_lock_dialog, GTK_TYPE_DIALOG)
60
61
62 enum {
63 PROP_0,
64 PROP_DEVICE,
65 N_PROPS
66 };
67
68 static GParamSpec *properties[N_PROPS];
69
70 static void
71 cc_wwan_sim_lock_changed_cb (CcWwanSimLockDialog *self)
72 {
73 gboolean row_enabled, lock_enabled;
74
75 lock_enabled = cc_wwan_device_get_sim_lock (self->device);
76 row_enabled = adw_switch_row_get_active (self->lock_row);
77
78 gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), lock_enabled != row_enabled);
79 gtk_widget_set_visible (GTK_WIDGET (self->lock_change_grid), row_enabled && lock_enabled);
80 }
81
82 static void
83 cc_wwan_pin_next_clicked_cb (CcWwanSimLockDialog *self)
84 {
85 gtk_stack_set_visible_child_name (self->pin_settings_stack, "pin-entry");
86 gtk_editable_set_text (GTK_EDITABLE (self->pin_entry), "");
87
88 gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), FALSE);
89 gtk_stack_set_visible_child (self->button_stack,
90 GTK_WIDGET (self->apply_button));
91 }
92
93 static void
94 cc_wwan_pin_apply_clicked_cb (CcWwanSimLockDialog *self)
95 {
96 const gchar *pin, *new_pin;
97 gboolean row_enabled, lock_enabled;
98
99 gtk_widget_set_visible (GTK_WIDGET (self), FALSE);
100
101 lock_enabled = cc_wwan_device_get_sim_lock (self->device);
102 row_enabled = adw_switch_row_get_active (self->lock_row);
103 pin = gtk_editable_get_text (GTK_EDITABLE (self->pin_entry));
104 new_pin = gtk_editable_get_text (GTK_EDITABLE (self->new_pin_entry));
105
106 if (lock_enabled != row_enabled)
107 {
108 if (row_enabled)
109 cc_wwan_device_enable_pin (self->device, pin, NULL, NULL, NULL);
110 else
111 cc_wwan_device_disable_pin (self->device, pin, NULL, NULL, NULL);
112
113 return;
114 }
115
116 cc_wwan_device_change_pin (self->device, pin, new_pin, NULL, NULL, NULL);
117 }
118
119 static void
120 cc_wwan_pin_entry_text_inserted_cb (CcWwanSimLockDialog *self,
121 gchar *new_text,
122 gint new_text_length,
123 gpointer position,
124 GtkEditable *editable)
125 {
126 size_t digit_end;
127 size_t len;
128
129 if (!new_text || !*new_text)
130 return;
131
132 if (new_text_length == 1 && g_ascii_isdigit (*new_text))
133 return;
134
135 if (new_text_length == -1)
136 len = strlen (new_text);
137 else
138 len = new_text_length;
139
140 if (len == 1 && g_ascii_isdigit (*new_text))
141 return;
142
143 digit_end = strspn (new_text, "1234567890");
144
145 /* The maximum length possible for PIN is 8 */
146 if (len <= 8 && digit_end == len)
147 return;
148
149 g_signal_stop_emission_by_name (editable, "insert-text");
150 gtk_widget_error_bell (GTK_WIDGET (editable));
151 }
152
153 static void
154 cc_wwan_pin_entry_changed_cb (CcWwanSimLockDialog *self)
155 {
156 const gchar *new_pin, *confirm_pin;
157
158 new_pin = gtk_editable_get_text (GTK_EDITABLE (self->new_pin_entry));
159 confirm_pin = gtk_editable_get_text (GTK_EDITABLE (self->pin_confirm_entry));
160 gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), FALSE);
161
162 /* A PIN should have a minimum length of 4 */
163 if (!new_pin || !confirm_pin || strlen (new_pin) < 4)
164 return;
165
166 if (g_str_equal (new_pin, confirm_pin))
167 gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), TRUE);
168 }
169
170
171 static void
172 cc_wwan_pin_entered_cb (CcWwanSimLockDialog *self)
173 {
174 const gchar *pin;
175 gsize len;
176 gboolean enable_apply;
177
178 pin = gtk_editable_get_text (GTK_EDITABLE (self->pin_entry));
179
180 if (!pin || !*pin)
181 {
182 gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), FALSE);
183 return;
184 }
185
186 len = strlen (pin);
187 enable_apply = len >= PIN_MINIMUM_LENGTH && len <= PIN_MAXIMUM_LENGTH;
188
189 gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), enable_apply);
190 }
191
192 static void
193 cc_wwan_sim_lock_dialog_set_property (GObject *object,
194 guint prop_id,
195 const GValue *value,
196 GParamSpec *pspec)
197 {
198 CcWwanSimLockDialog *self = (CcWwanSimLockDialog *)object;
199
200 switch (prop_id)
201 {
202 case PROP_DEVICE:
203 self->device = g_value_dup_object (value);
204 break;
205
206 default:
207 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
208 }
209 }
210
211 static void
212 cc_wwan_sim_lock_dialog_show (GtkWidget *widget)
213 {
214 CcWwanSimLockDialog *self = (CcWwanSimLockDialog *)widget;
215 gboolean lock_enabled;
216
217 gtk_editable_set_text (GTK_EDITABLE (self->pin_entry), "");
218 gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), FALSE);
219 gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), FALSE);
220
221 lock_enabled = cc_wwan_device_get_sim_lock (self->device);
222 g_object_set (self->lock_row, "active", lock_enabled, NULL);
223 gtk_widget_set_visible (GTK_WIDGET (self->lock_change_grid), lock_enabled);
224
225 gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), FALSE);
226 gtk_stack_set_visible_child (self->button_stack,
227 GTK_WIDGET (self->next_button));
228 gtk_button_set_label (self->apply_button, _("_Set"));
229
230 gtk_stack_set_visible_child_name (self->pin_settings_stack, "pin-settings");
231
232 gtk_editable_set_text (GTK_EDITABLE (self->pin_entry), "");
233 gtk_editable_set_text (GTK_EDITABLE (self->new_pin_entry), "");
234 gtk_editable_set_text (GTK_EDITABLE (self->pin_confirm_entry), "");
235
236 GTK_WIDGET_CLASS (cc_wwan_sim_lock_dialog_parent_class)->show (widget);
237 }
238
239 static void
240 cc_wwan_sim_lock_dialog_dispose (GObject *object)
241 {
242 CcWwanSimLockDialog *self = (CcWwanSimLockDialog *)object;
243
244 g_clear_object (&self->device);
245
246 G_OBJECT_CLASS (cc_wwan_sim_lock_dialog_parent_class)->dispose (object);
247 }
248
249 static void
250 cc_wwan_sim_lock_dialog_class_init (CcWwanSimLockDialogClass *klass)
251 {
252 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
253 GObjectClass *object_class = G_OBJECT_CLASS (klass);
254
255 object_class->set_property = cc_wwan_sim_lock_dialog_set_property;
256 object_class->dispose = cc_wwan_sim_lock_dialog_dispose;
257
258 widget_class->show = cc_wwan_sim_lock_dialog_show;
259
260 properties[PROP_DEVICE] =
261 g_param_spec_object ("device",
262 "Device",
263 "The WWAN Device",
264 CC_TYPE_WWAN_DEVICE,
265 G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
266
267 g_object_class_install_properties (object_class, N_PROPS, properties);
268
269 gtk_widget_class_set_template_from_resource (widget_class,
270 "/org/gnome/control-center/wwan/cc-wwan-sim-lock-dialog.ui");
271
272 gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, apply_button);
273 gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, button_stack);
274 gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, lock_change_grid);
275 gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, lock_row);
276 gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, new_pin_entry);
277 gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, next_button);
278 gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, pin_confirm_entry);
279 gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, pin_entry);
280 gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, pin_settings_stack);
281
282 gtk_widget_class_bind_template_callback (widget_class, cc_wwan_sim_lock_changed_cb);
283 gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_next_clicked_cb);
284 gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_apply_clicked_cb);
285 gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_entry_text_inserted_cb);
286 gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_entry_changed_cb);
287 gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_entered_cb);
288 }
289
290 static void
291 cc_wwan_sim_lock_dialog_init (CcWwanSimLockDialog *self)
292 {
293 gtk_widget_init_template (GTK_WIDGET (self));
294 }
295
296 GtkWindow *
297 cc_wwan_sim_lock_dialog_new (GtkWindow *parent_window,
298 CcWwanDevice *device)
299 {
300 g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
301 g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL);
302
303 return GTK_WINDOW (g_object_new (CC_TYPE_WWAN_SIM_LOCK_DIALOG,
304 "transient-for", parent_window,
305 "use-header-bar", 1,
306 "device", device,
307 NULL));
308 }
309