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 |
|
|
|