GCC Code Coverage Report


Directory: ./
File: panels/network/cc-wifi-connection-row.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 315 0.0%
Functions: 0 28 0.0%
Branches: 0 181 0.0%

Line Branch Exec Source
1 /*
2 * Copyright © 2018 Red Hat Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <glib/gi18n.h>
19 #include <config.h>
20 #include "cc-wifi-connection-row.h"
21 #include "cc-qr-code.h"
22
23 struct _CcWifiConnectionRow
24 {
25 AdwActionRow parent_instance;
26
27 gboolean constructed;
28
29 gboolean checkable;
30 gboolean forgettable;
31 gboolean checked;
32
33 NMDeviceWifi *device;
34 GPtrArray *aps;
35 NMConnection *connection;
36 gboolean known_connection;
37
38 GtkLabel *active_label;
39 GtkCheckButton *checkbutton;
40 GtkSpinner *connecting_spinner;
41 GtkImage *encrypted_icon;
42 GtkButton *options_button;
43 GtkButton *forget_button;
44 GtkButton *qr_code_button;
45 GtkImage *strength_icon;
46 };
47
48 enum
49 {
50 PROP_0,
51 PROP_CHECKABLE,
52 PROP_CHECKED,
53 PROP_DEVICE,
54 PROP_APS,
55 PROP_CONNECTION,
56 PROP_KNOWN_CONNECTION,
57 PROP_FORGETTABLE,
58 PROP_LAST
59 };
60
61 typedef enum
62 {
63 NM_AP_SEC_UNKNOWN,
64 NM_AP_SEC_NONE,
65 NM_AP_SEC_WEP,
66 NM_AP_SEC_WPA,
67 NM_AP_SEC_WPA2,
68 NM_AP_SEC_SAE,
69 NM_AP_SEC_OWE,
70 NM_AP_SEC_OWE_TM
71 } NMAccessPointSecurity;
72
73 G_DEFINE_TYPE (CcWifiConnectionRow, cc_wifi_connection_row, ADW_TYPE_ACTION_ROW)
74
75 static GParamSpec *props[PROP_LAST];
76
77 static void configure_clicked_cb (CcWifiConnectionRow *self);
78 static void forget_clicked_cb (CcWifiConnectionRow *self);
79 static void qr_code_clicked_cb (CcWifiConnectionRow *self);
80
81 static NMAccessPointSecurity
82 get_access_point_security (NMAccessPoint *ap)
83 {
84 NM80211ApFlags flags;
85 NM80211ApSecurityFlags wpa_flags;
86 NM80211ApSecurityFlags rsn_flags;
87 NMAccessPointSecurity type;
88
89 flags = nm_access_point_get_flags (ap);
90 wpa_flags = nm_access_point_get_wpa_flags (ap);
91 rsn_flags = nm_access_point_get_rsn_flags (ap);
92
93 if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) &&
94 wpa_flags == NM_802_11_AP_SEC_NONE &&
95 rsn_flags == NM_802_11_AP_SEC_NONE)
96 {
97 type = NM_AP_SEC_NONE;
98 }
99 else if ((flags & NM_802_11_AP_FLAGS_PRIVACY) &&
100 wpa_flags == NM_802_11_AP_SEC_NONE &&
101 rsn_flags == NM_802_11_AP_SEC_NONE)
102 {
103 type = NM_AP_SEC_WEP;
104 }
105 else if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) &&
106 wpa_flags != NM_802_11_AP_SEC_NONE &&
107 rsn_flags != NM_802_11_AP_SEC_NONE)
108 {
109 type = NM_AP_SEC_WPA;
110 }
111 #if NM_CHECK_VERSION(1,20,6)
112 else if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE)
113 {
114 type = NM_AP_SEC_SAE;
115 }
116 #endif
117 #if NM_CHECK_VERSION(1,24,0)
118 else if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_OWE)
119 {
120 type = NM_AP_SEC_OWE;
121 }
122 #endif
123 #if NM_CHECK_VERSION(1,26,0)
124 else if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)
125 {
126 type = NM_AP_SEC_OWE_TM;
127 }
128 #endif
129 else
130 {
131 type = NM_AP_SEC_WPA2;
132 }
133
134 return type;
135 }
136
137 static NMAccessPointSecurity
138 get_connection_security (NMConnection *con)
139 {
140 NMSettingWirelessSecurity *sws;
141 const gchar *key_mgmt;
142
143 sws = nm_connection_get_setting_wireless_security (con);
144 g_debug ("getting security from %p", sws);
145 if (!sws)
146 return NM_AP_SEC_NONE;
147
148 key_mgmt = nm_setting_wireless_security_get_key_mgmt (sws);
149 g_debug ("key management is %s", key_mgmt);
150
151 if (!key_mgmt)
152 return NM_AP_SEC_NONE;
153 else if (g_str_equal (key_mgmt, "none"))
154 return NM_AP_SEC_WEP;
155 else if (g_str_equal (key_mgmt, "ieee8021x"))
156 return NM_AP_SEC_WEP;
157 else if (g_str_equal (key_mgmt, "wpa-eap"))
158 return NM_AP_SEC_WPA2;
159 else if (strncmp (key_mgmt, "wpa-", 4) == 0)
160 return NM_AP_SEC_WPA;
161 else if (g_str_equal (key_mgmt, "sae"))
162 return NM_AP_SEC_SAE;
163 else if (g_str_equal (key_mgmt, "owe"))
164 return NM_AP_SEC_OWE;
165 else
166 return NM_AP_SEC_UNKNOWN;
167 }
168
169 static void
170 update_ui (CcWifiConnectionRow *self)
171 {
172 GBytes *ssid;
173 g_autofree gchar *title = NULL;
174 NMActiveConnection *active_connection = NULL;
175 gboolean active;
176 gboolean connecting;
177 NMAccessPointSecurity security = NM_AP_SEC_UNKNOWN;
178 NMAccessPoint *best_ap;
179 guint8 strength = 0;
180 NMActiveConnectionState state;
181
182 g_assert (self->device);
183 g_assert (self->connection || self->aps->len > 0);
184
185 best_ap = cc_wifi_connection_row_best_access_point (self);
186
187 if (self->connection)
188 {
189 active_connection = nm_device_get_active_connection (NM_DEVICE (self->device));
190 if (active_connection &&
191 NM_CONNECTION (nm_active_connection_get_connection (active_connection)) != self->connection)
192 active_connection = NULL;
193 }
194
195 if (self->connection)
196 {
197 NMSettingWireless *sw;
198 const gchar *name = NULL;
199 g_autofree gchar *ssid_str = NULL;
200 gchar *ssid_pos;
201
202 sw = nm_connection_get_setting_wireless (self->connection);
203
204 ssid = nm_setting_wireless_get_ssid (sw);
205 ssid_str = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
206 name = nm_connection_get_id (NM_CONNECTION (self->connection));
207
208 ssid_pos = strstr (name, ssid_str);
209 if (ssid_pos == name && strlen (name) == strlen (ssid_str))
210 {
211 title = g_markup_escape_text (name, -1);
212 }
213 else if (ssid_pos)
214 {
215 g_autofree gchar *before = g_strndup (name, ssid_pos - name);
216 g_autofree gchar *after = g_strndup (ssid_pos + strlen (ssid_str), strlen(ssid_pos) - strlen(ssid_str));
217 title = g_markup_printf_escaped ("<i>%s</i>%s<i>%s</i>",
218 before, ssid_str, after);
219 }
220 else
221 {
222 /* TRANSLATORS: This happens when the connection name does not contain the SSID. */
223 title = g_markup_printf_escaped (C_("Wi-Fi Connection", "%s (SSID: %s)"),
224 name, ssid_str);
225 }
226
227 adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), title);
228 }
229 else
230 {
231 g_autofree char *title_escaped = NULL;
232
233 ssid = nm_access_point_get_ssid (best_ap);
234 title = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
235 title_escaped = g_markup_escape_text (title, -1);
236 adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), title_escaped);
237 }
238
239 if (active_connection)
240 {
241 state = nm_active_connection_get_state (active_connection);
242
243 active = state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
244 connecting = state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
245 }
246 else
247 {
248 active = FALSE;
249 connecting = FALSE;
250 }
251
252 if (self->connection)
253 security = get_connection_security (self->connection);
254
255 if (best_ap != NULL)
256 {
257 security = get_access_point_security (best_ap);
258 strength = nm_access_point_get_strength (best_ap);
259 }
260
261 gtk_widget_set_visible (GTK_WIDGET (self->connecting_spinner), connecting);
262 if (connecting)
263 {
264 gtk_spinner_start (self->connecting_spinner);
265 }
266 else
267 {
268 gtk_spinner_stop (self->connecting_spinner);
269 }
270
271 gtk_widget_set_visible (GTK_WIDGET (self->active_label), active);
272 gtk_widget_set_visible (GTK_WIDGET (self->options_button), active || connecting || self->known_connection);
273 gtk_widget_set_visible (GTK_WIDGET (self->qr_code_button), (active || self->known_connection) && is_qr_code_supported (self->connection));
274
275 if (security != NM_AP_SEC_UNKNOWN && security != NM_AP_SEC_NONE && security != NM_AP_SEC_OWE && security != NM_AP_SEC_OWE_TM)
276 {
277 const gchar *icon_name = "lock-small-symbolic";
278
279 gtk_widget_set_child_visible (GTK_WIDGET (self->encrypted_icon), TRUE);
280 if (security == NM_AP_SEC_WEP)
281 {
282 icon_name = "warning-small-symbolic";
283 gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Insecure network (WEP)"));
284 }
285 else if (security == NM_AP_SEC_WPA)
286 {
287 gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Secure network (WPA)"));
288 }
289 else if (security == NM_AP_SEC_WPA2)
290 {
291 gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Secure network (WPA2)"));
292 }
293 else if (security == NM_AP_SEC_SAE)
294 {
295 gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Secure network (WPA3)"));
296 }
297 else
298 {
299 gtk_widget_set_tooltip_text (GTK_WIDGET (self->encrypted_icon), _("Secure network"));
300 }
301
302 gtk_image_set_from_icon_name (self->encrypted_icon, icon_name);
303 }
304 else
305 {
306 gtk_widget_set_child_visible (GTK_WIDGET (self->encrypted_icon), FALSE);
307 }
308
309 if (best_ap)
310 {
311 g_autofree char *description = NULL;
312 gchar *icon_name;
313
314 if (strength < 20)
315 icon_name = "network-wireless-signal-none-symbolic";
316 else if (strength < 40)
317 icon_name = "network-wireless-signal-weak-symbolic";
318 else if (strength < 50)
319 icon_name = "network-wireless-signal-ok-symbolic";
320 else if (strength < 80)
321 icon_name = "network-wireless-signal-good-symbolic";
322 else
323 icon_name = "network-wireless-signal-excellent-symbolic";
324
325 g_object_set (self->strength_icon, "icon-name", icon_name, NULL);
326 gtk_widget_set_child_visible (GTK_WIDGET (self->strength_icon), TRUE);
327
328 description = g_strdup_printf(_("Signal strength %d%%"), strength);
329 gtk_widget_set_tooltip_text (GTK_WIDGET (self->strength_icon), description);
330 gtk_accessible_update_property (GTK_ACCESSIBLE (self->strength_icon),
331 GTK_ACCESSIBLE_PROPERTY_DESCRIPTION,
332 description,
333 -1);
334 }
335 else
336 {
337 gtk_widget_set_child_visible (GTK_WIDGET (self->strength_icon), FALSE);
338 gtk_accessible_reset_property (GTK_ACCESSIBLE (self->strength_icon), GTK_ACCESSIBLE_PROPERTY_DESCRIPTION);
339 }
340 }
341
342 static void
343 cc_wifi_connection_row_constructed (GObject *object)
344 {
345 CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object);
346
347 G_OBJECT_CLASS (cc_wifi_connection_row_parent_class)->constructed (object);
348
349 /* Reparent the label into the checkbox */
350 gtk_widget_set_visible (GTK_WIDGET (self->checkbutton), self->checkable);
351 gtk_widget_set_visible (GTK_WIDGET (self->forget_button), self->forgettable);
352
353 update_ui (CC_WIFI_CONNECTION_ROW (object));
354 }
355
356 static void
357 cc_wifi_connection_row_get_property (GObject *object,
358 guint prop_id,
359 GValue *value,
360 GParamSpec *pspec)
361 {
362 CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object);
363 GPtrArray *ptr_array;
364 gint i;
365
366 switch (prop_id)
367 {
368 case PROP_CHECKABLE:
369 g_value_set_boolean (value, self->checkable);
370 break;
371
372 case PROP_CHECKED:
373 g_value_set_boolean (value, self->checked);
374 break;
375
376 case PROP_DEVICE:
377 g_value_set_object (value, self->device);
378 break;
379
380 case PROP_APS:
381 ptr_array = g_ptr_array_new_full (self->aps->len, NULL);
382 for (i = 0; i < self->aps->len; i++)
383 g_ptr_array_add (ptr_array, g_ptr_array_index (self->aps, i));
384
385 g_value_take_boxed (value, ptr_array);
386 break;
387
388 case PROP_CONNECTION:
389 g_value_set_object (value, self->connection);
390 break;
391
392 case PROP_KNOWN_CONNECTION:
393 g_value_set_boolean (value, self->known_connection);
394 break;
395 case PROP_FORGETTABLE:
396 g_value_set_boolean (value, self->forgettable);
397 break;
398
399 default:
400 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
401 }
402 }
403
404 static void
405 cc_wifi_connection_row_set_property (GObject *object,
406 guint prop_id,
407 const GValue *value,
408 GParamSpec *pspec)
409 {
410 CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object);
411 GPtrArray *ptr_array;
412 gint i;
413
414 switch (prop_id)
415 {
416 case PROP_CHECKABLE:
417 self->checkable = g_value_get_boolean (value);
418 break;
419
420 case PROP_CHECKED:
421 self->checked = g_value_get_boolean (value);
422 break;
423
424 case PROP_DEVICE:
425 self->device = g_value_dup_object (value);
426 break;
427
428 case PROP_APS:
429 ptr_array = g_value_get_boxed (value);
430 g_ptr_array_set_size (self->aps, 0);
431
432 if (ptr_array)
433 {
434 for (i = 0; i < ptr_array->len; i++)
435 g_ptr_array_add (self->aps, g_object_ref (g_ptr_array_index (ptr_array, i)));
436 }
437 if (self->constructed)
438 update_ui (self);
439 break;
440
441 case PROP_CONNECTION:
442 self->connection = g_value_dup_object (value);
443 break;
444
445 case PROP_KNOWN_CONNECTION:
446 self->known_connection = g_value_get_boolean (value);
447 break;
448
449 case PROP_FORGETTABLE:
450 self->forgettable = g_value_get_boolean (value);
451 break;
452
453 default:
454 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
455 }
456 }
457
458 static void
459 cc_wifi_connection_row_finalize (GObject *object)
460 {
461 CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object);
462
463 g_clear_object (&self->device);
464 g_clear_pointer (&self->aps, g_ptr_array_unref);
465 g_clear_object (&self->connection);
466
467 G_OBJECT_CLASS (cc_wifi_connection_row_parent_class)->finalize (object);
468 }
469
470
471 void
472 cc_wifi_connection_row_class_init (CcWifiConnectionRowClass *klass)
473 {
474 GObjectClass *object_class = G_OBJECT_CLASS (klass);
475 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
476
477 object_class->constructed = cc_wifi_connection_row_constructed;
478 object_class->get_property = cc_wifi_connection_row_get_property;
479 object_class->set_property = cc_wifi_connection_row_set_property;
480 object_class->finalize = cc_wifi_connection_row_finalize;
481
482 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/cc-wifi-connection-row.ui");
483
484 gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, active_label);
485 gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, checkbutton);
486 gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, connecting_spinner);
487 gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, encrypted_icon);
488 gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, options_button);
489 gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, forget_button);
490 gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, qr_code_button);
491 gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, strength_icon);
492
493 gtk_widget_class_bind_template_callback (widget_class, configure_clicked_cb);
494 gtk_widget_class_bind_template_callback (widget_class, forget_clicked_cb);
495 gtk_widget_class_bind_template_callback (widget_class, qr_code_clicked_cb);
496
497 props[PROP_CHECKABLE] = g_param_spec_boolean ("checkable", "checkable",
498 "Whether to show a checkbox to select the row",
499 FALSE,
500 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
501
502 props[PROP_CHECKED] = g_param_spec_boolean ("checked", "Checked",
503 "Whether the row is selected by checking it",
504 FALSE,
505 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
506
507 props[PROP_DEVICE] = g_param_spec_object ("device", "WiFi Device",
508 "The WiFi Device for this connection/ap",
509 NM_TYPE_DEVICE_WIFI,
510 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
511
512 props[PROP_APS] = g_param_spec_boxed ("aps", "Access Points",
513 "The access points for this connection (may be empty if a connection is given)",
514 G_TYPE_PTR_ARRAY,
515 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
516
517 props[PROP_CONNECTION] = g_param_spec_object ("connection", "Connection",
518 "The NMConnection (may be NULL if there is an AP)",
519 NM_TYPE_CONNECTION,
520 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
521
522 props[PROP_KNOWN_CONNECTION] = g_param_spec_boolean ("known-connection", "Known Connection",
523 "Whether this row is a known connection or not",
524 FALSE,
525 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
526
527 props[PROP_FORGETTABLE] = g_param_spec_boolean ("forgettable", "forgettable",
528 "Whether to show a checkbox to select the row",
529 FALSE,
530 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
531
532 g_object_class_install_properties (object_class,
533 PROP_LAST,
534 props);
535
536 g_signal_new ("configure",
537 CC_TYPE_WIFI_CONNECTION_ROW,
538 G_SIGNAL_RUN_LAST,
539 0, NULL, NULL, NULL,
540 G_TYPE_NONE, 0);
541 g_signal_new ("forget",
542 CC_TYPE_WIFI_CONNECTION_ROW,
543 G_SIGNAL_RUN_LAST,
544 0, NULL, NULL, NULL,
545 G_TYPE_NONE, 0);
546 g_signal_new ("show-qr-code",
547 CC_TYPE_WIFI_CONNECTION_ROW,
548 G_SIGNAL_RUN_LAST,
549 0, NULL, NULL, NULL,
550 G_TYPE_NONE, 0);
551 }
552
553 static void
554 configure_clicked_cb (CcWifiConnectionRow *self)
555 {
556 g_signal_emit_by_name (self, "configure");
557 }
558
559 static void
560 forget_clicked_cb (CcWifiConnectionRow *self)
561 {
562 g_signal_emit_by_name (self, "forget");
563 }
564
565 static void
566 qr_code_clicked_cb (CcWifiConnectionRow *self)
567 {
568 g_signal_emit_by_name (self, "show-qr-code");
569 }
570
571 void
572 cc_wifi_connection_row_init (CcWifiConnectionRow *self)
573 {
574 gtk_widget_init_template (GTK_WIDGET (self));
575
576 self->aps = g_ptr_array_new_with_free_func (g_object_unref);
577
578 g_object_bind_property (self, "checked",
579 self->checkbutton, "active",
580 G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
581
582 gtk_accessible_update_relation (GTK_ACCESSIBLE (self),
583 GTK_ACCESSIBLE_RELATION_DESCRIBED_BY,
584 self->encrypted_icon, self->strength_icon, NULL,
585 -1);
586 }
587
588 CcWifiConnectionRow *
589 cc_wifi_connection_row_new (NMDeviceWifi *device,
590 NMConnection *connection,
591 GPtrArray *aps,
592 gboolean checkable,
593 gboolean known_connection,
594 gboolean forgettable)
595 {
596 return g_object_new (CC_TYPE_WIFI_CONNECTION_ROW,
597 "device", device,
598 "connection", connection,
599 "aps", aps,
600 "checkable", checkable,
601 "known-connection", known_connection,
602 "forgettable", forgettable,
603 NULL);
604 }
605
606 gboolean
607 cc_wifi_connection_row_get_checkable (CcWifiConnectionRow *self)
608 {
609 g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), FALSE);
610
611 return self->checkable;
612 }
613
614 gboolean
615 cc_wifi_connection_row_get_checked (CcWifiConnectionRow *self)
616 {
617 g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), FALSE);
618
619 return self->checked;
620 }
621
622 NMDeviceWifi*
623 cc_wifi_connection_row_get_device (CcWifiConnectionRow *self)
624 {
625 g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), NULL);
626
627 return self->device;
628 }
629
630 const GPtrArray*
631 cc_wifi_connection_row_get_access_points (CcWifiConnectionRow *self)
632 {
633 g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), NULL);
634
635 return self->aps;
636 }
637
638 NMConnection*
639 cc_wifi_connection_row_get_connection (CcWifiConnectionRow *self)
640 {
641 g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), NULL);
642
643 return self->connection;
644 }
645
646 gboolean
647 cc_wifi_connection_row_get_forgettable (CcWifiConnectionRow *self)
648 {
649 g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), FALSE);
650
651 return self->forgettable;
652 }
653
654 void
655 cc_wifi_connection_row_set_checked (CcWifiConnectionRow *self,
656 gboolean value)
657 {
658 g_return_if_fail (CC_WIFI_CONNECTION_ROW (self));
659
660 self->checked = value;
661 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHECKED]);
662 }
663
664 NMAccessPoint*
665 cc_wifi_connection_row_best_access_point (CcWifiConnectionRow *self)
666 {
667 NMAccessPoint *best_ap = NULL;
668 NMAccessPoint *active_ap = NULL;
669 guint8 strength = 0;
670 gint i;
671
672 g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), NULL);
673
674 if (self->aps->len == 0)
675 return NULL;
676
677 active_ap = nm_device_wifi_get_active_access_point (self->device);
678
679 for (i = 0; i < self->aps->len; i++)
680 {
681 NMAccessPoint *cur;
682 guint8 cur_strength;
683
684 cur = g_ptr_array_index (self->aps, i);
685
686 /* Prefer the active AP in all cases */
687 if (cur == active_ap)
688 return cur;
689
690 cur_strength = nm_access_point_get_strength (cur);
691 /* Use if we don't have an AP, this is the current AP, or it is better */
692 if (!best_ap || cur_strength > strength)
693 {
694 best_ap = cur;
695 strength = cur_strength;
696 }
697 }
698
699 return best_ap;
700 }
701
702 void
703 cc_wifi_connection_row_add_access_point (CcWifiConnectionRow *self,
704 NMAccessPoint *ap)
705 {
706 g_return_if_fail (CC_WIFI_CONNECTION_ROW (self));
707
708 g_ptr_array_add (self->aps, g_object_ref (ap));
709 update_ui (self);
710 }
711
712 gboolean
713 cc_wifi_connection_row_remove_access_point (CcWifiConnectionRow *self,
714 NMAccessPoint *ap)
715 {
716 g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), FALSE);
717
718 if (!g_ptr_array_remove (self->aps, g_object_ref (ap)))
719 return FALSE;
720
721 /* Object might be invalid; this is alright if it is deleted right away */
722 if (self->aps->len > 0 || self->connection)
723 {
724 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_APS]);
725 update_ui (self);
726 }
727
728 return self->aps->len == 0;
729 }
730
731 gboolean
732 cc_wifi_connection_row_has_access_point (CcWifiConnectionRow *self,
733 NMAccessPoint *ap)
734 {
735 g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (self), FALSE);
736
737 return g_ptr_array_find (self->aps, ap, NULL);
738 }
739
740 void
741 cc_wifi_connection_row_update (CcWifiConnectionRow *self)
742 {
743 update_ui (self);
744
745 gtk_list_box_row_changed (GTK_LIST_BOX_ROW (self));
746
747 }
748
749