GCC Code Coverage Report


Directory: ./
File: panels/wwan/cc-wwan-mode-dialog.c
Date: 2024-05-03 09:46:52
Exec Total Coverage
Lines: 0 118 0.0%
Functions: 0 22 0.0%
Branches: 0 70 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* cc-wwan-mode-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-network-mode-dialog"
27
28 #include <config.h>
29 #include <glib/gi18n.h>
30 #include <libmm-glib.h>
31
32 #include "cc-wwan-mode-dialog.h"
33 #include "cc-wwan-resources.h"
34
35 /**
36 * @short_description: WWAN network type selection dialog
37 */
38
39 #define CC_TYPE_WWAN_MODE_ROW (cc_wwan_mode_row_get_type())
40 G_DECLARE_FINAL_TYPE (CcWwanModeRow, cc_wwan_mode_row, CC, WWAN_MODE_ROW, GtkListBoxRow)
41
42 struct _CcWwanModeDialog
43 {
44 GtkDialog parent_instance;
45
46 CcWwanDevice *device;
47 GtkListBox *network_mode_list;
48 CcWwanModeRow *selected_row;
49
50 MMModemMode preferred;
51 MMModemMode allowed;
52 MMModemMode new_allowed;
53 MMModemMode new_preferred;
54 };
55
56 G_DEFINE_TYPE (CcWwanModeDialog, cc_wwan_mode_dialog, GTK_TYPE_DIALOG)
57
58
59 enum {
60 PROP_0,
61 PROP_DEVICE,
62 N_PROPS
63 };
64
65 static GParamSpec *properties[N_PROPS];
66
67 struct _CcWwanModeRow
68 {
69 GtkListBoxRow parent_instance;
70 GtkImage *ok_emblem;
71 MMModemMode allowed;
72 MMModemMode preferred;
73 };
74
75 G_DEFINE_TYPE (CcWwanModeRow, cc_wwan_mode_row, GTK_TYPE_LIST_BOX_ROW)
76
77 static void
78 cc_wwan_mode_row_class_init (CcWwanModeRowClass *klass)
79 {
80 }
81
82 static void
83 cc_wwan_mode_row_init (CcWwanModeRow *row)
84 {
85 }
86
87 static void
88 cc_wwan_mode_changed_cb (CcWwanModeDialog *self,
89 CcWwanModeRow *row)
90 {
91 g_assert (CC_IS_WWAN_MODE_DIALOG (self));
92 g_assert (CC_IS_WWAN_MODE_ROW (row));
93
94 if (row == self->selected_row)
95 return;
96
97 gtk_widget_set_visible (GTK_WIDGET (row->ok_emblem), TRUE);
98
99 if (self->selected_row)
100 gtk_widget_set_visible (GTK_WIDGET (self->selected_row->ok_emblem), FALSE);
101
102 self->selected_row = row;
103 }
104
105 static void
106 cc_wwan_mode_dialog_ok_clicked_cb (CcWwanModeDialog *self)
107 {
108 g_assert (CC_IS_WWAN_MODE_DIALOG (self));
109
110 if (self->selected_row)
111 {
112 cc_wwan_device_set_current_mode (self->device,
113 self->selected_row->allowed,
114 self->selected_row->preferred,
115 NULL, NULL, NULL);
116 }
117 else
118 {
119 g_return_if_reached ();
120 }
121
122 gtk_window_close (GTK_WINDOW (self));
123 }
124
125 static GtkWidget *
126 cc_wwan_mode_dialog_row_new (CcWwanModeDialog *self,
127 MMModemMode allowed,
128 MMModemMode preferred)
129 {
130 CcWwanModeRow *row;
131 GtkWidget *box, *label, *image;
132 g_autofree gchar *mode = NULL;
133
134 g_assert (CC_WWAN_MODE_DIALOG (self));
135
136 row = g_object_new (CC_TYPE_WWAN_MODE_ROW, NULL);
137 row->allowed = allowed;
138 row->preferred = preferred;
139
140 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
141 g_object_set (box,
142 "margin-top", 18,
143 "margin-bottom", 18,
144 "margin-start", 18,
145 "margin-end", 18,
146 NULL);
147 gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
148
149 mode = cc_wwan_device_get_string_from_mode (self->device, allowed, preferred);
150 label = gtk_label_new (mode);
151 gtk_widget_set_hexpand (label, TRUE);
152 gtk_widget_set_halign (label, GTK_ALIGN_START);
153 gtk_box_append (GTK_BOX (box), label);
154
155 /* image should be hidden by default */
156 image = gtk_image_new_from_icon_name ("emblem-ok-symbolic");
157 gtk_widget_set_visible (image, FALSE);
158 row->ok_emblem = GTK_IMAGE (image);
159 gtk_box_append (GTK_BOX (box), image);
160
161 return GTK_WIDGET (row);
162 }
163
164 static void
165 cc_wwan_mode_dialog_update (CcWwanModeDialog *self)
166 {
167 MMModemMode allowed;
168 MMModemMode modes[][2] = {
169 {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, MM_MODEM_MODE_5G},
170 {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, 0},
171 {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, MM_MODEM_MODE_5G},
172 {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, 0},
173 {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G},
174 {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, 0},
175 {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G},
176 {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, 0},
177 {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_3G},
178 {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, 0},
179 {MM_MODEM_MODE_5G, 0},
180 {MM_MODEM_MODE_4G, 0},
181 {MM_MODEM_MODE_3G, 0},
182 {MM_MODEM_MODE_2G, 0},
183 };
184 size_t i;
185
186 g_assert (CC_IS_WWAN_MODE_DIALOG (self));
187
188 if (!cc_wwan_device_get_supported_modes (self->device, &allowed, NULL))
189 {
190 g_warning ("No modes supported by modem");
191 return;
192 }
193
194 for (i = 0; i < G_N_ELEMENTS (modes); i++)
195 {
196 GtkWidget *row;
197
198 if ((modes[i][0] & allowed) != modes[i][0])
199 continue;
200
201 if (modes[i][1] && !(modes[i][1] & allowed))
202 continue;
203
204 row = cc_wwan_mode_dialog_row_new (self, modes[i][0], modes[i][1]);
205 gtk_list_box_append (GTK_LIST_BOX (self->network_mode_list), row);
206 }
207 }
208
209 static void
210 cc_wwan_mode_dialog_set_property (GObject *object,
211 guint prop_id,
212 const GValue *value,
213 GParamSpec *pspec)
214 {
215 CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (object);
216
217 switch (prop_id)
218 {
219 case PROP_DEVICE:
220 self->device = g_value_dup_object (value);
221 break;
222
223 default:
224 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
225 }
226 }
227
228 static void
229 cc_wwan_mode_dialog_constructed (GObject *object)
230 {
231 CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (object);
232
233 G_OBJECT_CLASS (cc_wwan_mode_dialog_parent_class)->constructed (object);
234
235 if(!cc_wwan_device_get_current_mode (self->device, &self->allowed, &self->preferred))
236 g_warning ("Can't get allowed and preferred wwan modes");
237
238 cc_wwan_mode_dialog_update (self);
239 }
240
241 static void
242 cc_wwan_mode_dialog_dispose (GObject *object)
243 {
244 CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (object);
245
246 g_clear_object (&self->device);
247
248 G_OBJECT_CLASS (cc_wwan_mode_dialog_parent_class)->dispose (object);
249 }
250
251 static void
252 cc_wwan_mode_dialog_update_mode (CcWwanModeRow *row,
253 CcWwanModeDialog *self)
254 {
255 if (self->allowed == row->allowed && self->preferred == row->preferred)
256 {
257 self->selected_row = row;
258 gtk_widget_set_visible (GTK_WIDGET (row->ok_emblem), TRUE);
259 }
260 else
261 gtk_widget_set_visible (GTK_WIDGET (row->ok_emblem), FALSE);
262 }
263
264 static void
265 cc_wwan_mode_dialog_show (GtkWidget *widget)
266 {
267 CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (widget);
268
269 if(!cc_wwan_device_get_current_mode (self->device, &self->allowed, &self->preferred))
270 {
271 g_warning ("Can't get allowed and preferred wwan modes");
272 goto end;
273 }
274
275 self->selected_row = NULL;
276
277 for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->network_mode_list));
278 child;
279 child = gtk_widget_get_next_sibling (child))
280 cc_wwan_mode_dialog_update_mode (CC_WWAN_MODE_ROW (child), self);
281
282 end:
283 GTK_WIDGET_CLASS (cc_wwan_mode_dialog_parent_class)->show (widget);
284 }
285
286 static void
287 cc_wwan_mode_dialog_class_init (CcWwanModeDialogClass *klass)
288 {
289 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
290 GObjectClass *object_class = G_OBJECT_CLASS (klass);
291
292 object_class->set_property = cc_wwan_mode_dialog_set_property;
293 object_class->constructed = cc_wwan_mode_dialog_constructed;
294 object_class->dispose = cc_wwan_mode_dialog_dispose;
295
296 widget_class->show = cc_wwan_mode_dialog_show;
297
298 properties[PROP_DEVICE] =
299 g_param_spec_object ("device",
300 "Device",
301 "The WWAN Device",
302 CC_TYPE_WWAN_DEVICE,
303 G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
304
305 g_object_class_install_properties (object_class, N_PROPS, properties);
306
307 gtk_widget_class_set_template_from_resource (widget_class,
308 "/org/gnome/control-center/wwan/cc-wwan-mode-dialog.ui");
309
310 gtk_widget_class_bind_template_child (widget_class, CcWwanModeDialog, network_mode_list);
311
312 gtk_widget_class_bind_template_callback (widget_class, cc_wwan_mode_changed_cb);
313 gtk_widget_class_bind_template_callback (widget_class, cc_wwan_mode_dialog_ok_clicked_cb);
314 }
315
316 static void
317 cc_wwan_mode_dialog_init (CcWwanModeDialog *self)
318 {
319 gtk_widget_init_template (GTK_WIDGET (self));
320 }
321
322 GtkWindow *
323 cc_wwan_mode_dialog_new (GtkWindow *parent_window,
324 CcWwanDevice *device)
325 {
326 g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
327 g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL);
328
329 return GTK_WINDOW (g_object_new (CC_TYPE_WWAN_MODE_DIALOG,
330 "transient-for", parent_window,
331 "use-header-bar", 1,
332 "device", device,
333 NULL));
334 }
335