From 0922f1095aa0d2e505a49fe4d04cd5b630294e40 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 13 Dec 2018 10:46:28 +0100 Subject: [PATCH 01/13] wifi: Avoid one level of indentation Convert an if into an early return rather than nesting the entire logic. --- panels/network/net-device-wifi.c | 78 ++++++++++++++++---------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c index 262e8122fe..c2244c307e 100644 --- a/panels/network/net-device-wifi.c +++ b/panels/network/net-device-wifi.c @@ -165,54 +165,56 @@ panel_get_strongest_unique_aps (const GPtrArray *aps) /* we will have multiple entries for typical hotspots, just * filter to the one with the strongest signal */ aps_unique = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); - if (aps != NULL) - for (i = 0; i < aps->len; i++) { - ap = NM_ACCESS_POINT (g_ptr_array_index (aps, i)); + if (aps == NULL) + return aps_unique; - /* Hidden SSIDs don't get shown in the list */ - ssid = nm_access_point_get_ssid (ap); - if (!ssid) - continue; + for (i = 0; i < aps->len; i++) { + ap = NM_ACCESS_POINT (g_ptr_array_index (aps, i)); - add_ap = TRUE; + /* Hidden SSIDs don't get shown in the list */ + ssid = nm_access_point_get_ssid (ap); + if (!ssid) + continue; - /* get already added list */ - for (j=0; jlen; j++) { - ap_tmp = NM_ACCESS_POINT (g_ptr_array_index (aps_unique, j)); - ssid_tmp = nm_access_point_get_ssid (ap_tmp); - g_assert (ssid_tmp); + add_ap = TRUE; - /* is this the same type and data? */ - if (nm_utils_same_ssid (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), - g_bytes_get_data (ssid_tmp, NULL), g_bytes_get_size (ssid_tmp), - TRUE)) { + /* get already added list */ + for (j=0; jlen; j++) { + ap_tmp = NM_ACCESS_POINT (g_ptr_array_index (aps_unique, j)); + ssid_tmp = nm_access_point_get_ssid (ap_tmp); + g_assert (ssid_tmp); + + /* is this the same type and data? */ + if (nm_utils_same_ssid (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), + g_bytes_get_data (ssid_tmp, NULL), g_bytes_get_size (ssid_tmp), + TRUE)) { - g_debug ("found duplicate: %s", + g_debug ("found duplicate: %s", + nm_utils_escape_ssid (g_bytes_get_data (ssid_tmp, NULL), + g_bytes_get_size (ssid_tmp))); + + /* the new access point is stronger */ + if (nm_access_point_get_strength (ap) > + nm_access_point_get_strength (ap_tmp)) { + g_debug ("removing %s", nm_utils_escape_ssid (g_bytes_get_data (ssid_tmp, NULL), g_bytes_get_size (ssid_tmp))); - - /* the new access point is stronger */ - if (nm_access_point_get_strength (ap) > - nm_access_point_get_strength (ap_tmp)) { - g_debug ("removing %s", - nm_utils_escape_ssid (g_bytes_get_data (ssid_tmp, NULL), - g_bytes_get_size (ssid_tmp))); - g_ptr_array_remove (aps_unique, ap_tmp); - add_ap = TRUE; - } else { - add_ap = FALSE; - } - - break; + g_ptr_array_remove (aps_unique, ap_tmp); + add_ap = TRUE; + } else { + add_ap = FALSE; } + + break; } - if (add_ap) { - g_debug ("adding %s", - nm_utils_escape_ssid (g_bytes_get_data (ssid, NULL), - g_bytes_get_size (ssid))); - g_ptr_array_add (aps_unique, g_object_ref (ap)); - } } + if (add_ap) { + g_debug ("adding %s", + nm_utils_escape_ssid (g_bytes_get_data (ssid, NULL), + g_bytes_get_size (ssid))); + g_ptr_array_add (aps_unique, g_object_ref (ap)); + } + } return aps_unique; } -- GitLab From 88183c0e9f4b7bcb2394759fe5323096db5de14e Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 13 Dec 2018 18:43:29 +0100 Subject: [PATCH 02/13] wifi: Remove old and unused column definitions --- panels/network/net-device-wifi.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c index c2244c307e..87b6f35d1f 100644 --- a/panels/network/net-device-wifi.c +++ b/panels/network/net-device-wifi.c @@ -69,21 +69,6 @@ struct _NetDeviceWifi G_DEFINE_TYPE (NetDeviceWifi, net_device_wifi, NET_TYPE_DEVICE) -enum { - COLUMN_CONNECTION_ID, - COLUMN_ACCESS_POINT_ID, - COLUMN_TITLE, - COLUMN_SORT, - COLUMN_STRENGTH, - COLUMN_MODE, - COLUMN_SECURITY, - COLUMN_ACTIVE, - COLUMN_AP_IN_RANGE, - COLUMN_AP_OUT_OF_RANGE, - COLUMN_AP_IS_SAVED, - COLUMN_LAST -}; - GtkWidget * net_device_wifi_get_header_widget (NetDeviceWifi *device_wifi) { -- GitLab From 6fc89e8e8dcd8691085215804b464aa86dcd93fd Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 13 Dec 2018 15:06:02 +0100 Subject: [PATCH 03/13] shell: Fix warning by marking initialize_dependencies static --- shell/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/main.c b/shell/main.c index e38aeeede3..425306bc25 100644 --- a/shell/main.c +++ b/shell/main.c @@ -38,7 +38,7 @@ #include "cc-application.h" -void +static void initialize_dependencies (gint *argc, gchar ***argv) { -- GitLab From 417624cdab53947c2427d7c02c1258f20e6f4257 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sat, 15 Dec 2018 17:55:04 +0100 Subject: [PATCH 04/13] wifi: Fix invalid variant unref in connection editor If the WiFi secret is not set, then a NULL variant is passed back. We should not free this variant. Fix this by using g_autoptr instead. --- panels/network/connection-editor/net-connection-editor.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/panels/network/connection-editor/net-connection-editor.c b/panels/network/connection-editor/net-connection-editor.c index 556b57fb8d..2c8108ecd5 100644 --- a/panels/network/connection-editor/net-connection-editor.c +++ b/panels/network/connection-editor/net-connection-editor.c @@ -448,20 +448,18 @@ get_secrets_cb (GObject *source_object, { NMRemoteConnection *connection; GetSecretsInfo *info = user_data; - GError *error = NULL; - GVariant *variant; + g_autoptr(GError) error = NULL; + g_autoptr(GVariant) variant = NULL; connection = NM_REMOTE_CONNECTION (source_object); variant = nm_remote_connection_get_secrets_finish (connection, res, &error); if (!variant && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - g_error_free (error); g_free (info); return; } - ce_page_complete_init (info->page, info->setting_name, variant, error); - g_variant_unref (variant); + ce_page_complete_init (info->page, info->setting_name, variant, g_steal_pointer (&error)); g_free (info); } -- GitLab From 0fb86c82d2ee191a1806ec6adf4a234e06ab6345 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 13 Dec 2018 18:02:12 +0100 Subject: [PATCH 05/13] wifi: Add new CcWifiConnectionRow widget for the AP list This is in preparation to optimize list to not be rebuild completely for every change. --- panels/network/cc-wifi-connection-row.c | 443 +++++++++++++++++++++++ panels/network/cc-wifi-connection-row.h | 41 +++ panels/network/cc-wifi-connection-row.ui | 132 +++++++ panels/network/meson.build | 2 + panels/network/network.gresource.xml | 1 + 5 files changed, 619 insertions(+) create mode 100644 panels/network/cc-wifi-connection-row.c create mode 100644 panels/network/cc-wifi-connection-row.h create mode 100644 panels/network/cc-wifi-connection-row.ui diff --git a/panels/network/cc-wifi-connection-row.c b/panels/network/cc-wifi-connection-row.c new file mode 100644 index 0000000000..0f971fe1fd --- /dev/null +++ b/panels/network/cc-wifi-connection-row.c @@ -0,0 +1,443 @@ +/* + * Copyright © 2018 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include "cc-wifi-connection-row.h" + +struct _CcWifiConnectionRow +{ + GtkListBoxRow parent_instance; + + gboolean checkable; + gboolean checked; + + NMDeviceWifi *device; + NMAccessPoint *ap; + NMConnection *connection; + + GtkImage *active_icon; + GtkStack *button_stack; + GtkCheckButton *checkbutton; + GtkButton *configure_button; + GtkSpinner *connecting_spinner; + GtkImage *encrypted_icon; + GtkLabel *name_label; + GtkImage *strength_icon; +}; + +enum +{ + PROP_0, + PROP_CHECKABLE, + PROP_CHECKED, + PROP_DEVICE, + PROP_AP, + PROP_CONNECTION, + PROP_LAST +}; + +typedef enum +{ + NM_AP_SEC_UNKNOWN, + NM_AP_SEC_NONE, + NM_AP_SEC_WEP, + NM_AP_SEC_WPA, + NM_AP_SEC_WPA2 +} NMAccessPointSecurity; + +G_DEFINE_TYPE (CcWifiConnectionRow, cc_wifi_connection_row, GTK_TYPE_LIST_BOX_ROW) + +static GParamSpec *props[PROP_LAST]; + +static NMAccessPointSecurity +get_access_point_security (NMAccessPoint *ap) +{ + NM80211ApFlags flags; + NM80211ApSecurityFlags wpa_flags; + NM80211ApSecurityFlags rsn_flags; + NMAccessPointSecurity type; + + flags = nm_access_point_get_flags (ap); + wpa_flags = nm_access_point_get_wpa_flags (ap); + rsn_flags = nm_access_point_get_rsn_flags (ap); + + if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) && + wpa_flags == NM_802_11_AP_SEC_NONE && + rsn_flags == NM_802_11_AP_SEC_NONE) + { + type = NM_AP_SEC_NONE; + } + else if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && + wpa_flags == NM_802_11_AP_SEC_NONE && + rsn_flags == NM_802_11_AP_SEC_NONE) + { + type = NM_AP_SEC_WEP; + } + else if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) && + wpa_flags != NM_802_11_AP_SEC_NONE && + rsn_flags != NM_802_11_AP_SEC_NONE) + { + type = NM_AP_SEC_WPA; + } + else + { + type = NM_AP_SEC_WPA2; + } + + return type; +} + +static void +update_ui (CcWifiConnectionRow *self) +{ + GBytes *ssid; + g_autofree gchar *title = NULL; + gboolean active; + gboolean connecting; + NMAccessPointSecurity security; + guint8 strength; + NMDeviceState state; + NMAccessPoint *active_ap; + + g_assert (self->device); + g_assert (self->connection || self->ap); + + active_ap = nm_device_wifi_get_active_access_point (self->device); + + if (self->connection) + { + NMSettingWireless *sw = nm_connection_get_setting_wireless (self->connection); + + ssid = nm_setting_wireless_get_ssid (sw); + } + else + { + ssid = nm_access_point_get_ssid (self->ap); + } + + if (self->ap != NULL) + { + state = nm_device_get_state (NM_DEVICE (self->device)); + + active = (self->ap == active_ap) && (state == NM_DEVICE_STATE_ACTIVATED); + connecting = (self->ap == active_ap) && + (state == NM_DEVICE_STATE_PREPARE || + state == NM_DEVICE_STATE_CONFIG || + state == NM_DEVICE_STATE_IP_CONFIG || + state == NM_DEVICE_STATE_IP_CHECK || + state == NM_DEVICE_STATE_NEED_AUTH); + security = get_access_point_security (self->ap); + strength = nm_access_point_get_strength (self->ap); + } + else + { + active = FALSE; + connecting = FALSE; + security = NM_AP_SEC_UNKNOWN; + strength = 0; + } + + title = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); + gtk_label_set_text (self->name_label, title); + + if (connecting) + { + gtk_stack_set_visible_child_name (self->button_stack, "connecting"); + gtk_spinner_start (self->connecting_spinner); + } + else + { + gtk_spinner_stop (self->connecting_spinner); + + if (self->connection) + gtk_stack_set_visible_child_name (self->button_stack, "configure"); + else + gtk_stack_set_visible_child_name (self->button_stack, "empty"); + } + + gtk_widget_set_visible (GTK_WIDGET (self->active_icon), active); + + if (security != NM_AP_SEC_UNKNOWN && security != NM_AP_SEC_NONE) + gtk_widget_set_child_visible (GTK_WIDGET (self->encrypted_icon), TRUE); + else + gtk_widget_set_child_visible (GTK_WIDGET (self->encrypted_icon), FALSE); + + if (self->ap) + { + gchar *icon_name; + + if (strength < 20) + icon_name = "network-wireless-signal-none-symbolic"; + else if (strength < 40) + icon_name = "network-wireless-signal-weak-symbolic"; + else if (strength < 50) + icon_name = "network-wireless-signal-ok-symbolic"; + else if (strength < 80) + icon_name = "network-wireless-signal-good-symbolic"; + else + icon_name = "network-wireless-signal-excellent-symbolic"; + + g_object_set (self->strength_icon, "icon-name", icon_name, NULL); + gtk_widget_set_child_visible (GTK_WIDGET (self->strength_icon), TRUE); + } + else + { + gtk_widget_set_child_visible (GTK_WIDGET (self->strength_icon), FALSE); + } +} + +static void +cc_wifi_connection_row_constructed (GObject *object) +{ + CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object); + + G_OBJECT_CLASS (cc_wifi_connection_row_parent_class)->constructed (object); + + /* Reparent the label into the checkbox */ + if (self->checkable) + { + gtk_widget_set_visible (GTK_WIDGET (self->checkbutton), TRUE); + g_object_ref (self->name_label); + gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (GTK_WIDGET (self->name_label))), + GTK_WIDGET (self->name_label)); + gtk_container_add (GTK_CONTAINER (self->checkbutton), GTK_WIDGET (self->name_label)); + gtk_widget_show (GTK_WIDGET (self->name_label)); + g_object_unref (self->name_label); + } + else + { + gtk_widget_set_visible (GTK_WIDGET (self->checkbutton), FALSE); + } + + update_ui (CC_WIFI_CONNECTION_ROW (object)); +} + +static void +cc_wifi_connection_row_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object); + + switch (prop_id) + { + case PROP_CHECKABLE: + g_value_set_boolean (value, self->checkable); + break; + + case PROP_CHECKED: + g_value_set_boolean (value, self->checked); + break; + + case PROP_DEVICE: + g_value_set_object (value, self->device); + break; + + case PROP_AP: + g_value_set_object (value, self->ap); + break; + + case PROP_CONNECTION: + g_value_set_object (value, self->connection); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +cc_wifi_connection_row_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object); + + switch (prop_id) + { + case PROP_CHECKABLE: + self->checkable = g_value_get_boolean (value); + break; + + case PROP_CHECKED: + self->checked = g_value_get_boolean (value); + break; + + case PROP_DEVICE: + self->device = g_value_dup_object (value); + break; + + case PROP_AP: + self->ap = g_value_dup_object (value); + break; + + case PROP_CONNECTION: + self->connection = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +cc_wifi_connection_row_finalize (GObject *object) +{ + CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object); + + g_clear_object (&self->device); + g_clear_object (&self->ap); + g_clear_object (&self->connection); + + G_OBJECT_CLASS (cc_wifi_connection_row_parent_class)->finalize (object); +} + + +void +cc_wifi_connection_row_class_init (CcWifiConnectionRowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->constructed = cc_wifi_connection_row_constructed; + object_class->get_property = cc_wifi_connection_row_get_property; + object_class->set_property = cc_wifi_connection_row_set_property; + object_class->finalize = cc_wifi_connection_row_finalize; + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/cc-wifi-connection-row.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, active_icon); + gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, button_stack); + gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, checkbutton); + gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, configure_button); + gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, connecting_spinner); + gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, encrypted_icon); + gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, name_label); + gtk_widget_class_bind_template_child (widget_class, CcWifiConnectionRow, strength_icon); + + props[PROP_CHECKABLE] = g_param_spec_boolean ("checkable", "checkable", + "Whether to show a checkbox to select the row", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + props[PROP_CHECKED] = g_param_spec_boolean ("checked", "Checked", + "Whether the row is selected by checking it", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + props[PROP_DEVICE] = g_param_spec_object ("device", "WiFi Device", + "The WiFi Device for this connection/ap", + NM_TYPE_DEVICE_WIFI, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + props[PROP_AP] = g_param_spec_object ("ap", "Access Point", + "The best access point for this connection (may be NULL if there is a connection)", + NM_TYPE_ACCESS_POINT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + props[PROP_CONNECTION] = g_param_spec_object ("connection", "Connection", + "The NMConnection (may be NULL if there is an AP)", + NM_TYPE_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, + PROP_LAST, + props); + + g_signal_new ("configure", + CC_TYPE_WIFI_CONNECTION_ROW, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + +} + +static void +configure_clicked_cb (GtkButton *btn, + CcWifiConnectionRow *row) +{ + g_signal_emit_by_name (row, "configure"); +} + +void +cc_wifi_connection_row_init (CcWifiConnectionRow *row) +{ + gtk_widget_init_template (GTK_WIDGET (row)); + + g_signal_connect (row->configure_button, "clicked", G_CALLBACK (configure_clicked_cb), row); + + g_object_bind_property (row, "checked", + row->checkbutton, "active", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); +} + +CcWifiConnectionRow * +cc_wifi_connection_row_new (NMDevice *device, + NMConnection *connection, + NMAccessPoint *ap, + gboolean checkable) +{ + return g_object_new (CC_TYPE_WIFI_CONNECTION_ROW, + "device", device, + "connection", connection, + "ap", ap, + "checkable", checkable, + NULL); +} + +gboolean +cc_wifi_connection_row_get_checkable (CcWifiConnectionRow *row) +{ + g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), FALSE); + + return row->checkable; +} + +gboolean +cc_wifi_connection_row_get_checked (CcWifiConnectionRow *row) +{ + g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), FALSE); + + return row->checked; +} + +NMDeviceWifi* +cc_wifi_connection_row_get_device (CcWifiConnectionRow *row) +{ + g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), NULL); + + return row->device; +} + +NMAccessPoint* +cc_wifi_connection_row_get_access_point (CcWifiConnectionRow *row) +{ + g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), NULL); + + return row->ap; +} + +NMConnection* +cc_wifi_connection_row_get_connection (CcWifiConnectionRow *row) +{ + g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), NULL); + + return row->connection; +} + diff --git a/panels/network/cc-wifi-connection-row.h b/panels/network/cc-wifi-connection-row.h new file mode 100644 index 0000000000..e29075b83c --- /dev/null +++ b/panels/network/cc-wifi-connection-row.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2018 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +typedef struct _CcWifiConnectionRow CcWifiConnectionRow; + +#define CC_TYPE_WIFI_CONNECTION_ROW (cc_wifi_connection_row_get_type ()) +G_DECLARE_FINAL_TYPE (CcWifiConnectionRow, cc_wifi_connection_row, CC, WIFI_CONNECTION_ROW, GtkListBoxRow) + +CcWifiConnectionRow *cc_wifi_connection_row_new (NMDeviceWifi *device, + NMConnection *connection, + GPtrArray *aps, + gboolean checkable); + +gboolean cc_wifi_connection_row_get_checkable (CcWifiConnectionRow *row); +gboolean cc_wifi_connection_row_get_checked (CcWifiConnectionRow *row); +NMDeviceWifi *cc_wifi_connection_row_get_device (CcWifiConnectionRow *row); +NMAccessPoint *cc_wifi_connection_row_get_access_point (CcWifiConnectionRow *row); +NMConnection *cc_wifi_connection_row_get_connection (CcWifiConnectionRow *row); + +G_END_DECLS diff --git a/panels/network/cc-wifi-connection-row.ui b/panels/network/cc-wifi-connection-row.ui new file mode 100644 index 0000000000..715694bc7b --- /dev/null +++ b/panels/network/cc-wifi-connection-row.ui @@ -0,0 +1,132 @@ + + + + + + diff --git a/panels/network/meson.build b/panels/network/meson.build index 049b4b0ead..151b589b6b 100644 --- a/panels/network/meson.build +++ b/panels/network/meson.build @@ -35,6 +35,7 @@ endforeach sources = files( 'cc-network-panel.c', + 'cc-wifi-connection-row.c', 'cc-wifi-panel.c', 'net-device.c', 'net-device-ethernet.c', @@ -50,6 +51,7 @@ sources = files( resource_data = files( 'cc-network-panel.ui', + 'cc-wifi-connection-row.ui', 'cc-wifi-panel.ui', 'network-ethernet.ui', 'network-mobile.ui', diff --git a/panels/network/network.gresource.xml b/panels/network/network.gresource.xml index 348c5dc666..a3691b1a93 100644 --- a/panels/network/network.gresource.xml +++ b/panels/network/network.gresource.xml @@ -3,6 +3,7 @@ cc-network-panel.ui + cc-wifi-connection-row.ui network-proxy.ui network-vpn.ui network-wifi.ui -- GitLab From fb089b7c55516ad7e400e8f00ba0cd4efb47c5d4 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 13 Dec 2018 18:04:01 +0100 Subject: [PATCH 06/13] wifi: Use new CcWifiConnectionRow widget This is in preparation to optimise the AP list updating. --- panels/network/net-device-wifi.c | 327 +++++-------------------------- 1 file changed, 53 insertions(+), 274 deletions(-) diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c index 87b6f35d1f..f77adbda85 100644 --- a/panels/network/net-device-wifi.c +++ b/panels/network/net-device-wifi.c @@ -37,15 +37,9 @@ #include "connection-editor/net-connection-editor.h" #include "net-device-wifi.h" -#define PERIODIC_WIFI_SCAN_TIMEOUT 15 +#include "cc-wifi-connection-row.h" -typedef enum { - NM_AP_SEC_UNKNOWN, - NM_AP_SEC_NONE, - NM_AP_SEC_WEP, - NM_AP_SEC_WPA, - NM_AP_SEC_WPA2 -} NMAccessPointSecurity; +#define PERIODIC_WIFI_SCAN_TIMEOUT 15 static void nm_device_wifi_refresh_ui (NetDeviceWifi *device_wifi); static void show_wifi_list (NetDeviceWifi *device_wifi); @@ -106,36 +100,6 @@ device_wifi_proxy_add_to_stack (NetObject *object, return widget; } -static guint -get_access_point_security (NMAccessPoint *ap) -{ - NM80211ApFlags flags; - NM80211ApSecurityFlags wpa_flags; - NM80211ApSecurityFlags rsn_flags; - guint type; - - flags = nm_access_point_get_flags (ap); - wpa_flags = nm_access_point_get_wpa_flags (ap); - rsn_flags = nm_access_point_get_rsn_flags (ap); - - if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) && - wpa_flags == NM_802_11_AP_SEC_NONE && - rsn_flags == NM_802_11_AP_SEC_NONE) - type = NM_AP_SEC_NONE; - else if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && - wpa_flags == NM_802_11_AP_SEC_NONE && - rsn_flags == NM_802_11_AP_SEC_NONE) - type = NM_AP_SEC_WEP; - else if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) && - wpa_flags != NM_802_11_AP_SEC_NONE && - rsn_flags != NM_802_11_AP_SEC_NONE) - type = NM_AP_SEC_WPA; - else - type = NM_AP_SEC_WPA2; - - return type; -} - static GPtrArray * panel_get_strongest_unique_aps (const GPtrArray *aps) { @@ -1677,7 +1641,7 @@ static void really_forget (GtkDialog *dialog, gint response, gpointer data) { GtkWidget *forget = data; - GtkWidget *row; + CcWifiConnectionRow *row; GList *rows; GList *r; NMRemoteConnection *connection; @@ -1694,9 +1658,9 @@ really_forget (GtkDialog *dialog, gint response, gpointer data) rows = g_object_steal_data (G_OBJECT (forget), "rows"); for (r = rows; r; r = r->next) { row = r->data; - connection = g_object_get_data (G_OBJECT (row), "connection"); + connection = NM_REMOTE_CONNECTION (cc_wifi_connection_row_get_connection (row)); nm_remote_connection_delete_async (connection, cancellable, really_forgotten, device_wifi); - gtk_widget_destroy (row); + gtk_widget_destroy (GTK_WIDGET (row)); } g_list_free (rows); } @@ -1726,14 +1690,12 @@ forget_selected (GtkButton *forget, NetDeviceWifi *device_wifi) } static void -check_toggled (GtkToggleButton *check, GtkWidget *forget) +check_toggled (GtkWidget *forget, GParamSpec *pspec, CcWifiConnectionRow *row) { gboolean active; - GtkWidget *row; GList *rows; - row = gtk_widget_get_ancestor (GTK_WIDGET (check), GTK_TYPE_LIST_BOX_ROW); - active = gtk_toggle_button_get_active (check); + active = cc_wifi_connection_row_get_checked (row); rows = g_object_steal_data (G_OBJECT (forget), "rows"); if (active) { @@ -1758,198 +1720,30 @@ update_forget (GtkWidget *forget, gtk_widget_set_sensitive (forget, rows != NULL); } -static void -make_row (GtkSizeGroup *rows, - GtkSizeGroup *icons, - GtkWidget *forget, - NMDevice *device, - NMConnection *connection, - NMAccessPoint *ap, - NMAccessPoint *active_ap, - GtkWidget **row_out, - GtkWidget **check_out, - GtkWidget **edit_out) -{ - GtkWidget *row, *row_box; - GtkWidget *widget; - GtkWidget *box; - GtkWidget *button_stack; - GtkWidget *image; - gchar *title; - gboolean active; - gboolean in_range; - gboolean connecting; - guint security; - guint strength; - GBytes *ssid; - const gchar *icon_name; - guint64 timestamp; - NMDeviceState state; - - g_assert (connection || ap); +static gint +history_sort (gconstpointer a, gconstpointer b, gpointer data) +{ + guint64 ta, tb; + NMConnection *ca, *cb; + NMSettingConnection *sc; - state = nm_device_get_state (device); + ca = cc_wifi_connection_row_get_connection (CC_WIFI_CONNECTION_ROW ((gpointer) a)); + cb = cc_wifi_connection_row_get_connection (CC_WIFI_CONNECTION_ROW ((gpointer) b)); - if (connection != NULL) { - NMSettingWireless *sw; - NMSettingConnection *sc; - sw = nm_connection_get_setting_wireless (connection); - ssid = nm_setting_wireless_get_ssid (sw); - sc = nm_connection_get_setting_connection (connection); - timestamp = nm_setting_connection_get_timestamp (sc); + if (ca) { + sc = nm_connection_get_setting_connection (ca); + ta = nm_setting_connection_get_timestamp (sc); } else { - ssid = nm_access_point_get_ssid (ap); - timestamp = 0; + ta = 0; } - if (ap != NULL) { - in_range = TRUE; - active = (ap == active_ap) && (state == NM_DEVICE_STATE_ACTIVATED); - connecting = (ap == active_ap) && - (state == NM_DEVICE_STATE_PREPARE || - state == NM_DEVICE_STATE_CONFIG || - state == NM_DEVICE_STATE_IP_CONFIG || - state == NM_DEVICE_STATE_IP_CHECK || - state == NM_DEVICE_STATE_NEED_AUTH); - security = get_access_point_security (ap); - strength = nm_access_point_get_strength (ap); + if (cb) { + sc = nm_connection_get_setting_connection (cb); + tb = nm_setting_connection_get_timestamp (sc); } else { - in_range = FALSE; - active = FALSE; - connecting = FALSE; - security = 0; - strength = 0; - } - - row = gtk_list_box_row_new (); - gtk_size_group_add_widget (rows, row); - - row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_widget_set_margin_start (row_box, 12); - gtk_widget_set_margin_end (row_box, 12); - gtk_container_add (GTK_CONTAINER (row), row_box); - - button_stack = gtk_stack_new (); - gtk_widget_show (button_stack); - - widget = gtk_label_new (""); - gtk_widget_show (widget); - gtk_container_add (GTK_CONTAINER (button_stack), widget); - - widget = NULL; - if (forget) { - widget = gtk_check_button_new (); - g_signal_connect (widget, "toggled", - G_CALLBACK (check_toggled), forget); - gtk_widget_set_halign (widget, GTK_ALIGN_CENTER); - gtk_widget_set_valign (widget, GTK_ALIGN_CENTER); - gtk_box_pack_start (GTK_BOX (row_box), widget, FALSE, FALSE, 0); - g_signal_connect_object (row, "destroy", - G_CALLBACK (update_forget), forget, G_CONNECT_SWAPPED); - } - if (check_out) - *check_out = widget; - - title = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); - widget = gtk_label_new (title); - g_free (title); - gtk_widget_set_margin_top (widget, 12); - gtk_widget_set_margin_bottom (widget, 12); - gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); - gtk_label_set_xalign (GTK_LABEL (widget), 0.f); - gtk_box_pack_start (GTK_BOX (row_box), widget, FALSE, FALSE, 0); - - if (active) { - widget = gtk_image_new_from_icon_name ("object-select-symbolic", GTK_ICON_SIZE_MENU); - gtk_widget_set_halign (widget, GTK_ALIGN_CENTER); - gtk_widget_set_valign (widget, GTK_ALIGN_CENTER); - gtk_box_pack_start (GTK_BOX (row_box), widget, FALSE, FALSE, 0); - } - - gtk_box_pack_start (GTK_BOX (row_box), gtk_label_new (""), TRUE, FALSE, 0); - - widget = NULL; - image = gtk_image_new_from_icon_name ("emblem-system-symbolic", GTK_ICON_SIZE_MENU); - gtk_widget_show (image); - widget = gtk_button_new (); - gtk_style_context_add_class (gtk_widget_get_style_context (widget), "image-button"); - gtk_style_context_add_class (gtk_widget_get_style_context (widget), "circular"); - gtk_widget_show (widget); - gtk_container_add (GTK_CONTAINER (widget), image); - gtk_widget_set_halign (widget, GTK_ALIGN_CENTER); - gtk_widget_set_valign (widget, GTK_ALIGN_CENTER); - atk_object_set_name (gtk_widget_get_accessible (widget), _("Options…")); - gtk_stack_add_named (GTK_STACK (button_stack), widget, "button"); - g_object_set_data (G_OBJECT (row), "edit", widget); - - if (connection) - gtk_stack_set_visible_child_name (GTK_STACK (button_stack), "button"); - - gtk_box_pack_start (GTK_BOX (row_box), button_stack, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (row), "button_stack", button_stack); - - - if (edit_out) - *edit_out = widget; - - widget = gtk_spinner_new (); - gtk_spinner_start (GTK_SPINNER (widget)); - gtk_widget_show (widget); - - gtk_widget_set_halign (widget, GTK_ALIGN_CENTER); - gtk_widget_set_valign (widget, GTK_ALIGN_CENTER); - gtk_stack_add_named (GTK_STACK (button_stack), widget, "spinner"); - if (connecting) - gtk_stack_set_visible_child_name (GTK_STACK (button_stack), "spinner"); - - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - gtk_box_set_homogeneous (GTK_BOX (box), TRUE); - gtk_size_group_add_widget (icons, box); - gtk_box_pack_start (GTK_BOX (row_box), box, FALSE, FALSE, 0); - - if (in_range) { - if (security != NM_AP_SEC_UNKNOWN && - security != NM_AP_SEC_NONE) { - widget = gtk_image_new_from_icon_name ("network-wireless-encrypted-symbolic", GTK_ICON_SIZE_MENU); - } else { - widget = gtk_label_new (""); - } - gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0); - - if (strength < 20) - icon_name = "network-wireless-signal-none-symbolic"; - else if (strength < 40) - icon_name = "network-wireless-signal-weak-symbolic"; - else if (strength < 50) - icon_name = "network-wireless-signal-ok-symbolic"; - else if (strength < 80) - icon_name = "network-wireless-signal-good-symbolic"; - else - icon_name = "network-wireless-signal-excellent-symbolic"; - widget = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); - gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0); + tb = 0; } - gtk_widget_show_all (row); - - g_object_set_data (G_OBJECT (row), "ap", ap); - if (connection) - g_object_set_data (G_OBJECT (row), "connection", connection); - g_object_set_data (G_OBJECT (row), "timestamp", GUINT_TO_POINTER (timestamp)); - g_object_set_data (G_OBJECT (row), "active", GUINT_TO_POINTER (active)); - g_object_set_data (G_OBJECT (row), "strength", GUINT_TO_POINTER (strength)); - - *row_out = row; -} - -static gint -history_sort (gconstpointer a, gconstpointer b, gpointer data) -{ - guint64 ta, tb; - - ta = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (a), "timestamp")); - tb = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (b), "timestamp")); - if (ta > tb) return -1; if (tb > ta) return 1; @@ -1959,10 +1753,22 @@ history_sort (gconstpointer a, gconstpointer b, gpointer data) static gint ap_sort (gconstpointer a, gconstpointer b, gpointer data) { + NMAccessPoint *apa, *apb; guint sa, sb; - sa = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (a), "strength")); - sb = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (b), "strength")); + apa = cc_wifi_connection_row_get_access_point (CC_WIFI_CONNECTION_ROW ((gpointer) a)); + apb = cc_wifi_connection_row_get_access_point (CC_WIFI_CONNECTION_ROW ((gpointer) b)); + + if (apa) + sa = nm_access_point_get_strength (apa); + else + sa = 0; + + if (apb) + sb = nm_access_point_get_strength (apb); + else + sb = 0; + if (sa > sb) return -1; if (sb > sa) return 1; @@ -1978,9 +1784,8 @@ editor_done (NetConnectionEditor *editor, } static void -show_details_for_row (GtkButton *button, NetDeviceWifi *device_wifi) +show_details_for_row (CcWifiConnectionRow *row, NetDeviceWifi *device_wifi) { - GtkWidget *row; NMConnection *connection; NMAccessPoint *ap; GtkWidget *window; @@ -1988,11 +1793,10 @@ show_details_for_row (GtkButton *button, NetDeviceWifi *device_wifi) NMClient *client; NMDevice *device; - window = gtk_widget_get_toplevel (GTK_WIDGET (button)); + window = gtk_widget_get_toplevel (GTK_WIDGET (row)); - row = GTK_WIDGET (g_object_get_data (G_OBJECT (button), "row")); - connection = NM_CONNECTION (g_object_get_data (G_OBJECT (row), "connection")); - ap = NM_ACCESS_POINT (g_object_get_data (G_OBJECT (row), "ap")); + connection = cc_wifi_connection_row_get_connection (row); + ap = cc_wifi_connection_row_get_access_point (row); device = net_device_get_nm_device (NET_DEVICE (device_wifi)); client = net_object_get_client (NET_OBJECT (device_wifi)); @@ -2007,7 +1811,6 @@ open_history (NetDeviceWifi *device_wifi) GtkWidget *dialog; GtkWidget *window; CcNetworkPanel *panel; - GtkWidget *button; GtkWidget *forget; GtkWidget *header; GtkWidget *swin; @@ -2017,13 +1820,10 @@ open_history (NetDeviceWifi *device_wifi) GSList *l; const GPtrArray *aps; GPtrArray *aps_unique = NULL; - NMAccessPoint *active_ap; guint i; NMDevice *nm_device; GtkWidget *list; GtkWidget *row; - GtkSizeGroup *rows; - GtkSizeGroup *icons; dialog = g_object_new (GTK_TYPE_DIALOG, "use-header-bar", 1, NULL); panel = net_object_get_panel (NET_OBJECT (device_wifi)); @@ -2083,18 +1883,12 @@ open_history (NetDeviceWifi *device_wifi) g_object_set_data (G_OBJECT (forget), "net", device_wifi); gtk_container_add (GTK_CONTAINER (content_area), forget); - rows = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); - icons = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); - g_object_set_data_full (G_OBJECT (list), "rows", rows, g_object_unref); - g_object_set_data_full (G_OBJECT (list), "icons", icons, g_object_unref); - nm_device = net_device_get_nm_device (NET_DEVICE (device_wifi)); connections = net_device_get_valid_connections (NET_DEVICE (device_wifi)); aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (nm_device)); aps_unique = panel_get_strongest_unique_aps (aps); - active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (nm_device)); for (l = connections; l; l = l->next) { NMConnection *connection = l->data; @@ -2117,13 +1911,15 @@ open_history (NetDeviceWifi *device_wifi) ap = NULL; } - make_row (rows, icons, forget, nm_device, connection, ap, active_ap, &row, NULL, &button); + row = GTK_WIDGET (cc_wifi_connection_row_new (nm_device, connection, ap, TRUE)); + + g_signal_connect_object (row, "notify::checked", + G_CALLBACK (check_toggled), forget, G_CONNECT_SWAPPED); + g_signal_connect_object (row, "destroy", + G_CALLBACK (update_forget), forget, G_CONNECT_SWAPPED); + g_signal_connect (row, "configure", G_CALLBACK (show_details_for_row), device_wifi); + gtk_container_add (GTK_CONTAINER (list), row); - if (button) { - g_signal_connect (button, "clicked", - G_CALLBACK (show_details_for_row), device_wifi); - g_object_set_data (G_OBJECT (button), "row", row); - } } g_slist_free (connections); g_ptr_array_free (aps_unique, TRUE); @@ -2135,17 +1931,13 @@ static void populate_ap_list (NetDeviceWifi *device_wifi) { GtkWidget *list; - GtkSizeGroup *rows; - GtkSizeGroup *icons; NMDevice *nm_device; GSList *connections; GSList *l; const GPtrArray *aps; GPtrArray *aps_unique = NULL; - NMAccessPoint *active_ap; guint i; GtkWidget *row; - GtkWidget *button; GList *children, *child; list = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder, "listbox")); @@ -2156,16 +1948,12 @@ populate_ap_list (NetDeviceWifi *device_wifi) } g_list_free (children); - rows = GTK_SIZE_GROUP (g_object_get_data (G_OBJECT (list), "rows")); - icons = GTK_SIZE_GROUP (g_object_get_data (G_OBJECT (list), "icons")); - nm_device = net_device_get_nm_device (NET_DEVICE (device_wifi)); connections = net_device_get_valid_connections (NET_DEVICE (device_wifi)); aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (nm_device)); aps_unique = panel_get_strongest_unique_aps (aps); - active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (nm_device)); for (i = 0; i < aps_unique->len; i++) { GBytes *ssid_ap; @@ -2192,13 +1980,11 @@ populate_ap_list (NetDeviceWifi *device_wifi) connection = NULL; } - make_row (rows, icons, NULL, nm_device, connection, ap, active_ap, &row, NULL, &button); + row = GTK_WIDGET (cc_wifi_connection_row_new (nm_device, connection, ap, FALSE)); + + g_signal_connect (row, "configure", G_CALLBACK (show_details_for_row), device_wifi); + gtk_container_add (GTK_CONTAINER (list), row); - if (button) { - g_signal_connect (button, "clicked", - G_CALLBACK (show_details_for_row), device_wifi); - g_object_set_data (G_OBJECT (button), "row", row); - } } g_slist_free (connections); @@ -2251,8 +2037,6 @@ net_device_wifi_init (NetDeviceWifi *device_wifi) GError *error = NULL; GtkWidget *widget; GtkWidget *list; - GtkSizeGroup *rows; - GtkSizeGroup *icons; device_wifi->builder = gtk_builder_new (); gtk_builder_add_from_resource (device_wifi->builder, @@ -2282,11 +2066,6 @@ net_device_wifi_init (NetDeviceWifi *device_wifi) g_signal_connect (list, "row-activated", G_CALLBACK (ap_activated), device_wifi); - rows = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); - icons = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); - g_object_set_data_full (G_OBJECT (list), "rows", rows, g_object_unref); - g_object_set_data_full (G_OBJECT (list), "icons", icons, g_object_unref); - /* setup view */ widget = GTK_WIDGET (gtk_builder_get_object (device_wifi->builder, "notebook_view")); -- GitLab From 8f706f45bdf60b84c8c153439bbe078fe2c418e8 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sat, 15 Dec 2018 17:18:36 +0100 Subject: [PATCH 07/13] wifi: Remove unused code in wireless_try_to_connect The code tries to establish a connect by using an existing connection. However, if that is possible the function will not even be called. Remove the code in question. --- panels/network/net-device-wifi.c | 40 -------------------------------- 1 file changed, 40 deletions(-) diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c index f77adbda85..2542054c15 100644 --- a/panels/network/net-device-wifi.c +++ b/panels/network/net-device-wifi.c @@ -768,12 +768,8 @@ wireless_try_to_connect (NetDeviceWifi *device_wifi, GBytes *ssid, const gchar *ap_object_path) { - GBytes *match_ssid; const gchar *ssid_target; - GSList *list, *l; - NMConnection *connection_activate = NULL; NMDevice *device; - NMSettingWireless *setting_wireless; NMClient *client; GCancellable *cancellable; @@ -791,45 +787,9 @@ wireless_try_to_connect (NetDeviceWifi *device_wifi, g_debug ("try to connect to WIFI network %s [%s]", ssid_target, ap_object_path); - /* look for an existing connection we can use */ - list = net_device_get_valid_connections (NET_DEVICE (device_wifi)); - g_debug ("%i suitable remote connections to check", g_slist_length (list)); - for (l = list; l; l = g_slist_next (l)) { - NMConnection *connection; - - connection = NM_CONNECTION (l->data); - setting_wireless = nm_connection_get_setting_wireless (connection); - if (!NM_IS_SETTING_WIRELESS (setting_wireless)) - continue; - match_ssid = nm_setting_wireless_get_ssid (setting_wireless); - if (match_ssid == NULL) - continue; - if (g_bytes_equal (ssid, match_ssid)) { - g_debug ("we found an existing connection %s to activate!", - nm_connection_get_id (connection)); - connection_activate = connection; - break; - } - } - - g_slist_free (list); - /* activate the connection */ client = net_object_get_client (NET_OBJECT (device_wifi)); cancellable = net_object_get_cancellable (NET_OBJECT (device_wifi)); - if (connection_activate != NULL) { - nm_client_activate_connection_async (client, - connection_activate, - device, - NULL, - cancellable, - connection_activate_cb, - device_wifi); - goto out; - } - - /* create one, as it's missing */ - g_debug ("no existing connection found for %s, creating", ssid_target); if (!is_8021x (device, ap_object_path)) { GPermission *permission; -- GitLab From 3962aa3028ccd9237703f79d4fd5ccf8f8619633 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sat, 15 Dec 2018 17:35:44 +0100 Subject: [PATCH 08/13] wifi: Show the connection name when it is different to SSID In almost all cases, the SSID will be identical with the connection name (in fact, we do not even allow modifying the connection name). However, as it is now, we can end up with multiple connections with the same name in the list. Change the list to indicate the SSID separately in a way that will not result in any changes in the usual case. --- panels/network/cc-wifi-connection-row.c | 77 ++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/panels/network/cc-wifi-connection-row.c b/panels/network/cc-wifi-connection-row.c index 0f971fe1fd..2f89435e95 100644 --- a/panels/network/cc-wifi-connection-row.c +++ b/panels/network/cc-wifi-connection-row.c @@ -15,6 +15,7 @@ * along with this program; if not, see . */ +#include #include #include "cc-wifi-connection-row.h" @@ -101,6 +102,34 @@ get_access_point_security (NMAccessPoint *ap) return type; } +static NMAccessPointSecurity +get_connection_security (NMConnection *con) +{ + NMSettingWirelessSecurity *sws; + const gchar *key_mgmt; + + sws = nm_connection_get_setting_wireless_security (con); + g_debug ("getting security from %p", sws); + if (!sws) + return NM_AP_SEC_NONE; + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (sws); + g_debug ("key management is %s", key_mgmt); + + if (!key_mgmt) + return NM_AP_SEC_NONE; + else if (g_str_equal (key_mgmt, "none")) + return NM_AP_SEC_WEP; + else if (g_str_equal (key_mgmt, "ieee8021x")) + return NM_AP_SEC_WEP; + else if (g_str_equal (key_mgmt, "wpa-eap")) + return NM_AP_SEC_WPA2; + else if (strncmp (key_mgmt, "wpa-", 4) == 0) + return NM_AP_SEC_WPA; + else + return NM_AP_SEC_UNKNOWN; +} + static void update_ui (CcWifiConnectionRow *self) { @@ -108,8 +137,8 @@ update_ui (CcWifiConnectionRow *self) g_autofree gchar *title = NULL; gboolean active; gboolean connecting; - NMAccessPointSecurity security; - guint8 strength; + NMAccessPointSecurity security = NM_AP_SEC_UNKNOWN; + guint8 strength = 0; NMDeviceState state; NMAccessPoint *active_ap; @@ -120,13 +149,43 @@ update_ui (CcWifiConnectionRow *self) if (self->connection) { - NMSettingWireless *sw = nm_connection_get_setting_wireless (self->connection); + NMSettingWireless *sw; + const gchar *name = NULL; + g_autofree gchar *ssid_str = NULL; + gchar *ssid_pos; + + sw = nm_connection_get_setting_wireless (self->connection); ssid = nm_setting_wireless_get_ssid (sw); + ssid_str = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); + name = nm_connection_get_id (NM_CONNECTION (self->connection)); + + ssid_pos = strstr (name, ssid_str); + if (ssid_pos == name && strlen (name) == strlen (ssid_str)) + { + title = g_strdup (name); + } + else if (ssid_pos) + { + g_autofree gchar *before = g_strndup (name, ssid_pos - name); + g_autofree gchar *after = g_strndup (ssid_pos + strlen (ssid_str), strlen(ssid_pos) - strlen(ssid_str)); + title = g_markup_printf_escaped ("%s%s%s", + before, ssid_str, after); + } + else + { + /* TRANSLATORS: This happens when the connection name does not contain the SSID. */ + title = g_markup_printf_escaped (C_("Wi-Fi Connection", "%s (SSID: %s)"), + name, ssid_str); + } + + gtk_label_set_markup (self->name_label, title); } else { ssid = nm_access_point_get_ssid (self->ap); + title = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); + gtk_label_set_text (self->name_label, title); } if (self->ap != NULL) @@ -147,12 +206,16 @@ update_ui (CcWifiConnectionRow *self) { active = FALSE; connecting = FALSE; - security = NM_AP_SEC_UNKNOWN; - strength = 0; } - title = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); - gtk_label_set_text (self->name_label, title); + if (self->connection) + security = get_connection_security (self->connection); + + if (self->ap != NULL) + { + security = get_access_point_security (best_ap); + strength = nm_access_point_get_strength (best_ap); + } if (connecting) { -- GitLab From 5c81b126472afa0ff65058d805f2836caff871f2 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sat, 15 Dec 2018 17:47:25 +0100 Subject: [PATCH 09/13] wifi: Handle multiple APs in a connection row Note that this also changes the way to detect that the connection is currently active. This change is not required but but does simplify the code a little bit. --- panels/network/cc-wifi-connection-row.c | 180 +++++++++++++++++++----- panels/network/cc-wifi-connection-row.h | 31 ++-- panels/network/net-device-wifi.c | 22 +-- 3 files changed, 176 insertions(+), 57 deletions(-) diff --git a/panels/network/cc-wifi-connection-row.c b/panels/network/cc-wifi-connection-row.c index 2f89435e95..3d2b3f6140 100644 --- a/panels/network/cc-wifi-connection-row.c +++ b/panels/network/cc-wifi-connection-row.c @@ -23,11 +23,13 @@ struct _CcWifiConnectionRow { GtkListBoxRow parent_instance; + gboolean constructed; + gboolean checkable; gboolean checked; NMDeviceWifi *device; - NMAccessPoint *ap; + GPtrArray *aps; NMConnection *connection; GtkImage *active_icon; @@ -46,7 +48,7 @@ enum PROP_CHECKABLE, PROP_CHECKED, PROP_DEVICE, - PROP_AP, + PROP_APS, PROP_CONNECTION, PROP_LAST }; @@ -135,17 +137,26 @@ update_ui (CcWifiConnectionRow *self) { GBytes *ssid; g_autofree gchar *title = NULL; + NMActiveConnection *active_connection = NULL; gboolean active; gboolean connecting; NMAccessPointSecurity security = NM_AP_SEC_UNKNOWN; + NMAccessPoint *best_ap; guint8 strength = 0; - NMDeviceState state; - NMAccessPoint *active_ap; + NMActiveConnectionState state; g_assert (self->device); - g_assert (self->connection || self->ap); + g_assert (self->connection || self->aps->len > 0); + + best_ap = cc_wifi_connection_row_best_access_point (self); - active_ap = nm_device_wifi_get_active_access_point (self->device); + if (self->connection) + { + active_connection = nm_device_get_active_connection (NM_DEVICE (self->device)); + if (active_connection && + NM_CONNECTION (nm_active_connection_get_connection (active_connection)) != self->connection) + active_connection = NULL; + } if (self->connection) { @@ -183,24 +194,17 @@ update_ui (CcWifiConnectionRow *self) } else { - ssid = nm_access_point_get_ssid (self->ap); + ssid = nm_access_point_get_ssid (best_ap); title = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); gtk_label_set_text (self->name_label, title); } - if (self->ap != NULL) + if (active_connection) { - state = nm_device_get_state (NM_DEVICE (self->device)); - - active = (self->ap == active_ap) && (state == NM_DEVICE_STATE_ACTIVATED); - connecting = (self->ap == active_ap) && - (state == NM_DEVICE_STATE_PREPARE || - state == NM_DEVICE_STATE_CONFIG || - state == NM_DEVICE_STATE_IP_CONFIG || - state == NM_DEVICE_STATE_IP_CHECK || - state == NM_DEVICE_STATE_NEED_AUTH); - security = get_access_point_security (self->ap); - strength = nm_access_point_get_strength (self->ap); + state = nm_active_connection_get_state (active_connection); + + active = state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED; + connecting = state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING; } else { @@ -211,7 +215,7 @@ update_ui (CcWifiConnectionRow *self) if (self->connection) security = get_connection_security (self->connection); - if (self->ap != NULL) + if (best_ap != NULL) { security = get_access_point_security (best_ap); strength = nm_access_point_get_strength (best_ap); @@ -239,7 +243,7 @@ update_ui (CcWifiConnectionRow *self) else gtk_widget_set_child_visible (GTK_WIDGET (self->encrypted_icon), FALSE); - if (self->ap) + if (best_ap) { gchar *icon_name; @@ -296,6 +300,8 @@ cc_wifi_connection_row_get_property (GObject *object, GParamSpec *pspec) { CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object); + GPtrArray *ptr_array; + gint i; switch (prop_id) { @@ -311,8 +317,12 @@ cc_wifi_connection_row_get_property (GObject *object, g_value_set_object (value, self->device); break; - case PROP_AP: - g_value_set_object (value, self->ap); + case PROP_APS: + ptr_array = g_ptr_array_new_full (self->aps->len, NULL); + for (i = 0; i < self->aps->len; i++) + g_ptr_array_add (ptr_array, g_ptr_array_index (self->aps, i)); + + g_value_take_boxed (value, ptr_array); break; case PROP_CONNECTION: @@ -331,6 +341,8 @@ cc_wifi_connection_row_set_property (GObject *object, GParamSpec *pspec) { CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object); + GPtrArray *ptr_array; + gint i; switch (prop_id) { @@ -346,8 +358,17 @@ cc_wifi_connection_row_set_property (GObject *object, self->device = g_value_dup_object (value); break; - case PROP_AP: - self->ap = g_value_dup_object (value); + case PROP_APS: + ptr_array = g_value_get_boxed (value); + g_ptr_array_set_size (self->aps, 0); + + if (ptr_array) + { + for (i = 0; i < ptr_array->len; i++) + g_ptr_array_add (self->aps, g_object_ref (g_ptr_array_index (ptr_array, i))); + } + if (self->constructed) + update_ui (self); break; case PROP_CONNECTION: @@ -365,7 +386,7 @@ cc_wifi_connection_row_finalize (GObject *object) CcWifiConnectionRow *self = CC_WIFI_CONNECTION_ROW (object); g_clear_object (&self->device); - g_clear_object (&self->ap); + g_clear_pointer (&self->aps, g_ptr_array_unref); g_clear_object (&self->connection); G_OBJECT_CLASS (cc_wifi_connection_row_parent_class)->finalize (object); @@ -409,10 +430,10 @@ cc_wifi_connection_row_class_init (CcWifiConnectionRowClass *klass) NM_TYPE_DEVICE_WIFI, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - props[PROP_AP] = g_param_spec_object ("ap", "Access Point", - "The best access point for this connection (may be NULL if there is a connection)", - NM_TYPE_ACCESS_POINT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + props[PROP_APS] = g_param_spec_boxed ("aps", "Access Points", + "The access points for this connection (may be empty if a connection is given)", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); props[PROP_CONNECTION] = g_param_spec_object ("connection", "Connection", "The NMConnection (may be NULL if there is an AP)", @@ -445,21 +466,23 @@ cc_wifi_connection_row_init (CcWifiConnectionRow *row) g_signal_connect (row->configure_button, "clicked", G_CALLBACK (configure_clicked_cb), row); + row->aps = g_ptr_array_new_with_free_func (g_object_unref); + g_object_bind_property (row, "checked", row->checkbutton, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); } CcWifiConnectionRow * -cc_wifi_connection_row_new (NMDevice *device, +cc_wifi_connection_row_new (NMDeviceWifi *device, NMConnection *connection, - NMAccessPoint *ap, + GPtrArray *aps, gboolean checkable) { return g_object_new (CC_TYPE_WIFI_CONNECTION_ROW, "device", device, "connection", connection, - "ap", ap, + "aps", aps, "checkable", checkable, NULL); } @@ -488,12 +511,12 @@ cc_wifi_connection_row_get_device (CcWifiConnectionRow *row) return row->device; } -NMAccessPoint* -cc_wifi_connection_row_get_access_point (CcWifiConnectionRow *row) +const GPtrArray* +cc_wifi_connection_row_get_access_points (CcWifiConnectionRow *row) { g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), NULL); - return row->ap; + return row->aps; } NMConnection* @@ -504,3 +527,88 @@ cc_wifi_connection_row_get_connection (CcWifiConnectionRow *row) return row->connection; } +NMAccessPoint* +cc_wifi_connection_row_best_access_point (CcWifiConnectionRow *row) +{ + NMAccessPoint *best_ap = NULL; + NMAccessPoint *active_ap = NULL; + guint8 strength = 0; + gint i; + + g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), NULL); + + if (row->aps->len == 0) + return NULL; + + active_ap = nm_device_wifi_get_active_access_point (row->device); + + for (i = 0; i < row->aps->len; i++) + { + NMAccessPoint *cur; + guint8 cur_strength; + + cur = g_ptr_array_index (row->aps, i); + + /* Prefer the active AP in all cases */ + if (cur == active_ap) + return cur; + + cur_strength = nm_access_point_get_strength (cur); + /* Use if we don't have an AP, this is the current AP, or it is better */ + if (!best_ap || cur_strength > strength) + { + best_ap = cur; + strength = cur_strength; + } + } + + return best_ap; +} + +void +cc_wifi_connection_row_add_access_point (CcWifiConnectionRow *row, + NMAccessPoint *ap) +{ + g_return_if_fail (CC_WIFI_CONNECTION_ROW (row)); + + g_ptr_array_add (row->aps, g_object_ref (ap)); + update_ui (row); +} + +gboolean +cc_wifi_connection_row_remove_access_point (CcWifiConnectionRow *row, + NMAccessPoint *ap) +{ + g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), FALSE); + + if (!g_ptr_array_remove (row->aps, g_object_ref (ap))) + return FALSE; + + /* Object might be invalid; this is alright if it is deleted right away */ + if (row->aps->len > 0 || row->connection) + { + g_object_notify_by_pspec (G_OBJECT (row), props[PROP_APS]); + update_ui (row); + } + + return row->aps->len == 0; +} + +gboolean +cc_wifi_connection_row_has_access_point (CcWifiConnectionRow *row, + NMAccessPoint *ap) +{ + g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), FALSE); + + return g_ptr_array_find (row->aps, ap, NULL); +} + +void +cc_wifi_connection_row_update (CcWifiConnectionRow *row) +{ + update_ui (row); + + gtk_list_box_row_changed (GTK_LIST_BOX_ROW (row)); + +} + diff --git a/panels/network/cc-wifi-connection-row.h b/panels/network/cc-wifi-connection-row.h index e29075b83c..fa0c2ce74b 100644 --- a/panels/network/cc-wifi-connection-row.h +++ b/panels/network/cc-wifi-connection-row.h @@ -27,15 +27,24 @@ typedef struct _CcWifiConnectionRow CcWifiConnectionRow; #define CC_TYPE_WIFI_CONNECTION_ROW (cc_wifi_connection_row_get_type ()) G_DECLARE_FINAL_TYPE (CcWifiConnectionRow, cc_wifi_connection_row, CC, WIFI_CONNECTION_ROW, GtkListBoxRow) -CcWifiConnectionRow *cc_wifi_connection_row_new (NMDeviceWifi *device, - NMConnection *connection, - GPtrArray *aps, - gboolean checkable); - -gboolean cc_wifi_connection_row_get_checkable (CcWifiConnectionRow *row); -gboolean cc_wifi_connection_row_get_checked (CcWifiConnectionRow *row); -NMDeviceWifi *cc_wifi_connection_row_get_device (CcWifiConnectionRow *row); -NMAccessPoint *cc_wifi_connection_row_get_access_point (CcWifiConnectionRow *row); -NMConnection *cc_wifi_connection_row_get_connection (CcWifiConnectionRow *row); - +CcWifiConnectionRow *cc_wifi_connection_row_new (NMDeviceWifi *device, + NMConnection *connection, + GPtrArray *aps, + gboolean checkable); + +gboolean cc_wifi_connection_row_get_checkable (CcWifiConnectionRow *row); +gboolean cc_wifi_connection_row_get_checked (CcWifiConnectionRow *row); +NMDeviceWifi *cc_wifi_connection_row_get_device (CcWifiConnectionRow *row); +const GPtrArray *cc_wifi_connection_row_get_access_points (CcWifiConnectionRow *row); +NMConnection *cc_wifi_connection_row_get_connection (CcWifiConnectionRow *row); + +NMAccessPoint *cc_wifi_connection_row_best_access_point (CcWifiConnectionRow *row); +void cc_wifi_connection_row_add_access_point (CcWifiConnectionRow *row, + NMAccessPoint *ap); +gboolean cc_wifi_connection_row_remove_access_point (CcWifiConnectionRow *row, + NMAccessPoint *ap); +gboolean cc_wifi_connection_row_has_access_point (CcWifiConnectionRow *row, + NMAccessPoint *ap); + +void cc_wifi_connection_row_update (CcWifiConnectionRow *row); G_END_DECLS diff --git a/panels/network/net-device-wifi.c b/panels/network/net-device-wifi.c index 2542054c15..8b77b21b03 100644 --- a/panels/network/net-device-wifi.c +++ b/panels/network/net-device-wifi.c @@ -1716,8 +1716,8 @@ ap_sort (gconstpointer a, gconstpointer b, gpointer data) NMAccessPoint *apa, *apb; guint sa, sb; - apa = cc_wifi_connection_row_get_access_point (CC_WIFI_CONNECTION_ROW ((gpointer) a)); - apb = cc_wifi_connection_row_get_access_point (CC_WIFI_CONNECTION_ROW ((gpointer) b)); + apa = cc_wifi_connection_row_best_access_point (CC_WIFI_CONNECTION_ROW ((gpointer) a)); + apb = cc_wifi_connection_row_best_access_point (CC_WIFI_CONNECTION_ROW ((gpointer) b)); if (apa) sa = nm_access_point_get_strength (apa); @@ -1756,7 +1756,7 @@ show_details_for_row (CcWifiConnectionRow *row, NetDeviceWifi *device_wifi) window = gtk_widget_get_toplevel (GTK_WIDGET (row)); connection = cc_wifi_connection_row_get_connection (row); - ap = cc_wifi_connection_row_get_access_point (row); + ap = cc_wifi_connection_row_best_access_point (row); device = net_device_get_nm_device (NET_DEVICE (device_wifi)); client = net_object_get_client (NET_OBJECT (device_wifi)); @@ -1783,7 +1783,7 @@ open_history (NetDeviceWifi *device_wifi) guint i; NMDevice *nm_device; GtkWidget *list; - GtkWidget *row; + CcWifiConnectionRow *row; dialog = g_object_new (GTK_TYPE_DIALOG, "use-header-bar", 1, NULL); panel = net_object_get_panel (NET_OBJECT (device_wifi)); @@ -1858,6 +1858,8 @@ open_history (NetDeviceWifi *device_wifi) if (connection_is_shared (connection)) continue; + row = cc_wifi_connection_row_new (NM_DEVICE_WIFI (nm_device), connection, NULL, TRUE); + setting = nm_connection_get_setting_by_name (connection, NM_SETTING_WIRELESS_SETTING_NAME); ssid = nm_setting_wireless_get_ssid (NM_SETTING_WIRELESS (setting)); for (i = 0; i < aps_unique->len; i++) { @@ -1867,19 +1869,16 @@ open_history (NetDeviceWifi *device_wifi) if (nm_utils_same_ssid (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), g_bytes_get_data (ssid_ap, NULL), g_bytes_get_size (ssid_ap), TRUE)) - break; - ap = NULL; + cc_wifi_connection_row_add_access_point (row, ap); } - row = GTK_WIDGET (cc_wifi_connection_row_new (nm_device, connection, ap, TRUE)); - g_signal_connect_object (row, "notify::checked", G_CALLBACK (check_toggled), forget, G_CONNECT_SWAPPED); g_signal_connect_object (row, "destroy", G_CALLBACK (update_forget), forget, G_CONNECT_SWAPPED); g_signal_connect (row, "configure", G_CALLBACK (show_details_for_row), device_wifi); - gtk_container_add (GTK_CONTAINER (list), row); + gtk_container_add (GTK_CONTAINER (list), GTK_WIDGET (row)); } g_slist_free (connections); g_ptr_array_free (aps_unique, TRUE); @@ -1916,6 +1915,7 @@ populate_ap_list (NetDeviceWifi *device_wifi) aps_unique = panel_get_strongest_unique_aps (aps); for (i = 0; i < aps_unique->len; i++) { + g_autoptr(GPtrArray) aps = NULL; GBytes *ssid_ap; NMAccessPoint *ap; NMConnection *connection = NULL; @@ -1940,7 +1940,9 @@ populate_ap_list (NetDeviceWifi *device_wifi) connection = NULL; } - row = GTK_WIDGET (cc_wifi_connection_row_new (nm_device, connection, ap, FALSE)); + aps = g_ptr_array_new (); + g_ptr_array_add (aps, ap); + row = GTK_WIDGET (cc_wifi_connection_row_new (NM_DEVICE_WIFI (nm_device), connection, aps, FALSE)); g_signal_connect (row, "configure", G_CALLBACK (show_details_for_row), device_wifi); -- GitLab From eec784102712a1ae72026637cb6fe17b6b475796 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sat, 15 Dec 2018 17:50:24 +0100 Subject: [PATCH 10/13] wifi: Add set_checked function to connection row --- panels/network/cc-wifi-connection-row.c | 10 ++++++++++ panels/network/cc-wifi-connection-row.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/panels/network/cc-wifi-connection-row.c b/panels/network/cc-wifi-connection-row.c index 3d2b3f6140..3feec0d6e1 100644 --- a/panels/network/cc-wifi-connection-row.c +++ b/panels/network/cc-wifi-connection-row.c @@ -527,6 +527,16 @@ cc_wifi_connection_row_get_connection (CcWifiConnectionRow *row) return row->connection; } +void +cc_wifi_connection_row_set_checked (CcWifiConnectionRow *row, + gboolean value) +{ + g_return_if_fail (CC_WIFI_CONNECTION_ROW (row)); + + row->checked = value; + g_object_notify_by_pspec (G_OBJECT (row), props[PROP_CHECKED]); +} + NMAccessPoint* cc_wifi_connection_row_best_access_point (CcWifiConnectionRow *row) { diff --git a/panels/network/cc-wifi-connection-row.h b/panels/network/cc-wifi-connection-row.h index fa0c2ce74b..4be2305235 100644 --- a/panels/network/cc-wifi-connection-row.h +++ b/panels/network/cc-wifi-connection-row.h @@ -38,6 +38,9 @@ NMDeviceWifi *cc_wifi_connection_row_get_device (CcWifiConnectio const GPtrArray *cc_wifi_connection_row_get_access_points (CcWifiConnectionRow *row); NMConnection *cc_wifi_connection_row_get_connection (CcWifiConnectionRow *row); +void cc_wifi_connection_row_set_checked (CcWifiConnectionRow *row, + gboolean value); + NMAccessPoint *cc_wifi_connection_row_best_access_point (CcWifiConnectionRow *row); void cc_wifi_connection_row_add_access_point (CcWifiConnectionRow *row, NMAccessPoint *ap); -- GitLab From fb7e09eb46413014211231eb444113fbf95b401d Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sat, 15 Dec 2018 17:51:38 +0100 Subject: [PATCH 11/13] wifi: Add new connection list widget This widget keep track of connections and APs and automatically creates/refreshes the corresponding list entries. --- panels/network/cc-wifi-connection-list.c | 759 +++++++++++++++++++++++ panels/network/cc-wifi-connection-list.h | 39 ++ panels/network/meson.build | 1 + 3 files changed, 799 insertions(+) create mode 100644 panels/network/cc-wifi-connection-list.c create mode 100644 panels/network/cc-wifi-connection-list.h diff --git a/panels/network/cc-wifi-connection-list.c b/panels/network/cc-wifi-connection-list.c new file mode 100644 index 0000000000..6b612bb740 --- /dev/null +++ b/panels/network/cc-wifi-connection-list.c @@ -0,0 +1,759 @@ +/* + * Copyright © 2018 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "cc-wifi-connection-list.h" +#include "cc-wifi-connection-row.h" + +struct _CcWifiConnectionList +{ + GtkListBox parent_instance; + + guint freeze_count; + gboolean updating; + + gboolean checkable; + gboolean hide_unavailable; + gboolean show_aps; + + NMClient *client; + NMDeviceWifi *device; + + NMConnection *last_active; + + GPtrArray *connections; + GPtrArray *connections_row; + + /* AP SSID cache stores the APs SSID used for assigning it to a row. + * This is necessary to efficiently remove it when its SSID changes. + * + * Note that we only group APs that cannot be assigned to a connection + * by the SSID. In principle this is wrong, because other attributes may + * be different rendering them separate networks. + * In practice this will almost never happen, and if it does, we just + * show and select the strongest AP. + */ + GHashTable *ap_ssid_cache; + GHashTable *ssid_to_row; +}; + +static void on_device_ap_added_cb (CcWifiConnectionList *self, + NMAccessPoint *ap, + NMDeviceWifi *device); +static void on_device_ap_removed_cb (CcWifiConnectionList *self, + NMAccessPoint *ap, + NMDeviceWifi *device); +static void on_row_configured_cb (CcWifiConnectionRow *row, + CcWifiConnectionList *list); + +G_DEFINE_TYPE (CcWifiConnectionList, cc_wifi_connection_list, GTK_TYPE_LIST_BOX) + +enum +{ + PROP_0, + PROP_CHECKABLE, + PROP_HIDE_UNAVAILABLE, + PROP_SHOW_APS, + PROP_CLIENT, + PROP_DEVICE, + PROP_LAST +}; + +static GParamSpec *props [PROP_LAST]; + +static GBytes* +new_hashable_ssid (GBytes *ssid) +{ + GBytes *res; + const guint8 *data; + gsize size; + + /* This is what nm_utils_same_ssid does, but returning it so that we can + * use the result in other ways (i.e. hash table lookups). */ + data = g_bytes_get_data ((GBytes*) ssid, &size); + if (data[size-1] == '\0') + size -= 1; + res = g_bytes_new (data, size); + + return res; +} + +static gboolean +connection_ignored (NMConnection *connection) +{ + NMSettingWireless *sw; + + /* Ignore AP and adhoc modes (i.e. accept infrastructure or empty) */ + sw = nm_connection_get_setting_wireless (connection); + if (!sw) + return TRUE; + if (g_strcmp0 (nm_setting_wireless_get_mode (sw), "adhoc") == 0 || + g_strcmp0 (nm_setting_wireless_get_mode (sw), "ap") == 0) + { + return TRUE; + } + + return FALSE; +} + +static CcWifiConnectionRow* +cc_wifi_connection_list_row_add (CcWifiConnectionList *self, + NMConnection *connection, + NMAccessPoint *ap) +{ + CcWifiConnectionRow *res; + g_autoptr(GPtrArray) aps = NULL; + + if (ap) + { + aps = g_ptr_array_new (); + g_ptr_array_add (aps, ap); + } + + res = cc_wifi_connection_row_new (self->device, + connection, + aps, + self->checkable); + gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (res)); + gtk_widget_show (GTK_WIDGET (res)); + + g_signal_connect (res, "configure", G_CALLBACK (on_row_configured_cb), self); + + return res; +} + +static void +clear_widget (CcWifiConnectionList *self) +{ + const GPtrArray *aps; + GHashTableIter iter; + CcWifiConnectionRow *row; + gint i; + + /* Clear everything; disconnect all AP signals first */ + aps = nm_device_wifi_get_access_points (self->device); + for (i = 0; i < aps->len; i++) + g_signal_handlers_disconnect_by_data (g_ptr_array_index (aps, i), self); + + /* Remove all AP only rows */ + g_hash_table_iter_init (&iter, self->ssid_to_row); + while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &row)) + { + g_hash_table_iter_remove (&iter); + gtk_container_remove (GTK_CONTAINER (self), GTK_WIDGET (row)); + } + + /* Remove all connection rows */ + for (i = 0; i < self->connections_row->len; i++) + { + if (!g_ptr_array_index (self->connections_row, i)) + continue; + + row = g_ptr_array_index (self->connections_row, i); + g_ptr_array_index (self->connections_row, i) = NULL; + gtk_container_remove (GTK_CONTAINER (self), + GTK_WIDGET (row)); + } + + /* Reset the internal state */ + g_ptr_array_set_size (self->connections, 0); + g_ptr_array_set_size (self->connections_row, 0); + g_hash_table_remove_all (self->ssid_to_row); + g_hash_table_remove_all (self->ap_ssid_cache); +} + +static void +update_connections (CcWifiConnectionList *self) +{ + const GPtrArray *aps; + const GPtrArray *acs_client; + g_autoptr(GPtrArray) acs = NULL; + NMActiveConnection *ac; + NMConnection *ac_con = NULL; + gint i; + + /* We don't want full UI rebuilds during some UI interactions, so allow freezing the list. */ + if (self->freeze_count > 0) + return; + + /* Prevent recursion (maybe move this into an idle handler instead?) */ + if (self->updating) + return; + self->updating = TRUE; + + clear_widget (self); + + /* Copy the new connections; also create a row if we show unavailable + * connections */ + acs_client = nm_client_get_connections (self->client); + + acs = g_ptr_array_new_full (acs_client->len + 1, NULL); + for (i = 0; i < acs_client->len; i++) + g_ptr_array_add (acs, g_ptr_array_index (acs_client, i)); + + ac = nm_device_get_active_connection (NM_DEVICE (self->device)); + if (ac) + ac_con = NM_CONNECTION (nm_active_connection_get_connection (ac)); + + if (ac_con && !g_ptr_array_find (acs, ac_con, NULL)) + { + g_debug ("Adding remote connection for active connection"); + g_ptr_array_add (acs, g_object_ref (ac_con)); + } + + for (i = 0; i < acs->len; i++) + { + NMConnection *con; + + con = g_ptr_array_index (acs, i); + if (connection_ignored (con)) + continue; + + g_ptr_array_add (self->connections, g_object_ref (con)); + if (self->hide_unavailable && con != ac_con) + g_ptr_array_add (self->connections_row, NULL); + else + g_ptr_array_add (self->connections_row, + cc_wifi_connection_list_row_add (self, con, + NULL)); + } + + /* Coldplug all known APs again */ + aps = nm_device_wifi_get_access_points (self->device); + for (i = 0; i < aps->len; i++) + on_device_ap_added_cb (self, g_ptr_array_index (aps, i), self->device); + + self->updating = FALSE; +} + +static void +on_row_configured_cb (CcWifiConnectionRow *row, CcWifiConnectionList *list) +{ + g_signal_emit_by_name (list, "configure", row); +} + +static void +on_access_point_property_changed (CcWifiConnectionList *self, + GParamSpec *pspec, + NMAccessPoint *ap) +{ + CcWifiConnectionRow *row; + GBytes *ssid; + gboolean has_connection = FALSE; + gint i; + + /* If the SSID changed then the AP needs to be added/removed from rows. + * Do this by simulating an AP addition/removal. */ + if (g_str_equal (pspec->name, NM_ACCESS_POINT_SSID)) + { + g_debug ("Simulating add/remove for SSID change"); + on_device_ap_removed_cb (self, ap, self->device); + on_device_ap_added_cb (self, ap, self->device); + return; + } + + /* Otherwise, find all rows that contain the AP and update it. Do this by + * first searching all rows with connections, and then looking it up in the + * SSID rows if not found. */ + for (i = 0; i < self->connections_row->len; i++) + { + row = g_ptr_array_index (self->connections_row, i); + if (row && cc_wifi_connection_row_has_access_point (row, ap)) + { + cc_wifi_connection_row_update (row); + has_connection = TRUE; + } + } + + if (!self->show_aps || has_connection) + return; + + ssid = g_hash_table_lookup (self->ap_ssid_cache, ap); + if (!ssid) + return; + + row = g_hash_table_lookup (self->ssid_to_row, ssid); + if (!row) + g_assert_not_reached (); + else + cc_wifi_connection_row_update (row); +} + +static void +on_device_ap_added_cb (CcWifiConnectionList *self, + NMAccessPoint *ap, + NMDeviceWifi *device) +{ + g_autoptr(GPtrArray) connections = NULL; + CcWifiConnectionRow *row; + GBytes *ap_ssid; + g_autoptr(GBytes) ssid = NULL; + guint i, j; + + g_signal_connect_object (ap, "notify", + G_CALLBACK (on_access_point_property_changed), + self, G_CONNECT_SWAPPED); + + connections = nm_access_point_filter_connections (ap, self->connections); + + /* If this is the active AP, then add the active connection to the list. This + * is a workaround because nm_access_pointer_filter_connections() will not + * include it otherwise. + * So it seems like the dummy AP entry that NM creates internaly is not actually + * compatible with the connection that is being activated. + */ + if (ap == nm_device_wifi_get_active_access_point (device)) + { + NMActiveConnection *ac; + NMConnection *ac_con; + + ac = nm_device_get_active_connection (NM_DEVICE (self->device)); + + if (ac) + { + guint idx; + + ac_con = NM_CONNECTION (nm_active_connection_get_connection (ac)); + + if (!g_ptr_array_find (connections, ac_con, NULL) && + g_ptr_array_find (self->connections, ac_con, &idx)) + { + g_debug ("Adding active connection to list of valid connections for AP"); + g_ptr_array_add (connections, g_object_ref (ac_con)); + } + } + } + + /* Add the AP to all connection related rows, creating the row if neccessary. */ + for (i = 0; i < connections->len; i++) + { + gboolean found = g_ptr_array_find (self->connections, g_ptr_array_index (connections, i), &j); + + g_assert (found); + + row = g_ptr_array_index (self->connections_row, j); + if (!row) + row = cc_wifi_connection_list_row_add (self, g_ptr_array_index (connections, i), NULL); + cc_wifi_connection_row_add_access_point (row, ap); + g_ptr_array_index (self->connections_row, j) = row; + } + + if (connections->len > 0) + return; + + if (!self->show_aps) + return; + + /* The AP is not compatible to any known connection, generate an entry for the + * SSID or add to existing one. However, not for hidden APs that don't have an SSID. + */ + ap_ssid = nm_access_point_get_ssid (ap); + if (ap_ssid == NULL) + return; + ssid = new_hashable_ssid (ap_ssid); + + g_hash_table_insert (self->ap_ssid_cache, ap, g_bytes_ref (ssid)); + + row = g_hash_table_lookup (self->ssid_to_row, ssid); + if (!row) + { + row = cc_wifi_connection_list_row_add (self, NULL, ap); + + g_hash_table_insert (self->ssid_to_row, g_bytes_ref (ssid), row); + } + else + { + cc_wifi_connection_row_add_access_point (row, ap); + } +} + +static void +on_device_ap_removed_cb (CcWifiConnectionList *self, + NMAccessPoint *ap, + NMDeviceWifi *device) +{ + CcWifiConnectionRow *row; + g_autoptr(GBytes) ssid = NULL; + gboolean found = FALSE; + gint i; + + g_signal_handlers_disconnect_by_data (ap, self); + + /* Find any connection related row with the AP and remove the AP from it. Remove the + * row if it was the last AP and we are hiding unavailable connections. */ + for (i = 0; i < self->connections_row->len; i++) + { + row = g_ptr_array_index (self->connections_row, i); + if (row && cc_wifi_connection_row_remove_access_point (row, ap)) + { + found = TRUE; + + if (self->hide_unavailable) + { + g_ptr_array_index (self->connections_row, i) = NULL; + gtk_container_remove (GTK_CONTAINER (self), GTK_WIDGET (row)); + } + } + } + + if (found || !self->show_aps) + return; + + /* If the AP was inserted into a row without a connection, then we will get an + * SSID for it here. */ + g_hash_table_steal_extended (self->ap_ssid_cache, ap, NULL, (gpointer*) &ssid); + if (!ssid) + return; + + /* And we can update the row (possibly removing it) */ + row = g_hash_table_lookup (self->ssid_to_row, ssid); + g_assert (row != NULL); + + if (cc_wifi_connection_row_remove_access_point (row, ap)) + { + g_hash_table_remove (self->ssid_to_row, ssid); + gtk_container_remove (GTK_CONTAINER (self), GTK_WIDGET (row)); + } +} + +static void +on_client_connection_added_cb (CcWifiConnectionList *self, + NMConnection *connection, + NMClient *client) +{ + if (!nm_device_connection_compatible (NM_DEVICE (self->device), connection, NULL)) + return; + + if (connection_ignored (connection)) + return; + + /* The approach we take to handle connection changes is to do a full rebuild. + * It happens seldom enough to make this feasible. + */ + update_connections (self); +} + +static void +on_client_connection_removed_cb (CcWifiConnectionList *self, + NMConnection *connection, + NMClient *client) +{ + if (!g_ptr_array_find (self->connections, connection, NULL)) + return; + + /* The approach we take to handle connection changes is to do a full rebuild. + * It happens seldom enough to make this feasible. + */ + update_connections (self); +} + +static void +on_device_state_changed_cb (CcWifiConnectionList *self, + GParamSpec *pspec, + NMDeviceWifi *device) +{ + NMActiveConnection *ac; + NMConnection *connection = NULL; + guint idx; + + ac = nm_device_get_active_connection (NM_DEVICE (self->device)); + if (ac) + connection = NM_CONNECTION (nm_active_connection_get_connection (ac)); + + /* Just update the corresponding row if the AC is still the same. */ + if (self->last_active == connection && + g_ptr_array_find (self->connections, connection, &idx) && + g_ptr_array_index (self->connections_row, idx)) + { + cc_wifi_connection_row_update (g_ptr_array_index (self->connections_row, idx)); + return; + } + + /* Give up and do a full update. */ + update_connections (self); + self->last_active = connection; +} + +static void +on_device_active_ap_changed_cb (CcWifiConnectionList *self, + GParamSpec *pspec, + NMDeviceWifi *device) +{ + NMAccessPoint *ap; + /* We need to make sure the active AP is grouped with the active connection. + * Do so by simply removing and adding it. + * + * This is necessary because the AP is added before this property + * is updated. */ + ap = nm_device_wifi_get_active_access_point (self->device); + if (ap) + { + g_debug ("Simulating add/remove for active AP change"); + on_device_ap_removed_cb (self, ap, self->device); + on_device_ap_added_cb (self, ap, self->device); + } +} + +static void +cc_wifi_connection_list_dispose (GObject *object) +{ + CcWifiConnectionList *self = (CcWifiConnectionList *)object; + + /* Prevent any further updates; clear_widget must not indirectly recurse + * through updates_connections */ + self->updating = TRUE; + + /* Drop all external references */ + clear_widget (self); + + G_OBJECT_CLASS (cc_wifi_connection_list_parent_class)->dispose (object); +} + +static void +cc_wifi_connection_list_finalize (GObject *object) +{ + CcWifiConnectionList *self = (CcWifiConnectionList *)object; + + g_clear_object (&self->client); + g_clear_object (&self->device); + + g_clear_pointer (&self->connections, g_ptr_array_unref); + g_clear_pointer (&self->connections_row, g_ptr_array_unref); + g_clear_pointer (&self->ssid_to_row, g_hash_table_unref); + g_clear_pointer (&self->ap_ssid_cache, g_hash_table_unref); + + G_OBJECT_CLASS (cc_wifi_connection_list_parent_class)->finalize (object); +} + +static void +cc_wifi_connection_list_constructed (GObject *object) +{ + CcWifiConnectionList *self = (CcWifiConnectionList *)object; + + G_OBJECT_CLASS (cc_wifi_connection_list_parent_class)->constructed (object); + + g_assert (self->client); + g_assert (self->device); + + g_signal_connect_object (self->client, "connection-added", + G_CALLBACK (on_client_connection_added_cb), + self, G_CONNECT_SWAPPED); + g_signal_connect_object (self->client, "connection-removed", + G_CALLBACK (on_client_connection_removed_cb), + self, G_CONNECT_SWAPPED); + + g_signal_connect_object (self->device, "access-point-added", + G_CALLBACK (on_device_ap_added_cb), + self, G_CONNECT_SWAPPED); + g_signal_connect_object (self->device, "access-point-removed", + G_CALLBACK (on_device_ap_removed_cb), + self, G_CONNECT_SWAPPED); + + g_signal_connect_object (self->device, "notify::state", + G_CALLBACK (on_device_state_changed_cb), + self, G_CONNECT_SWAPPED); + g_signal_connect_object (self->device, "notify::active-connection", + G_CALLBACK (on_device_state_changed_cb), + self, G_CONNECT_SWAPPED); + g_signal_connect_object (self->device, "notify::active-access-point", + G_CALLBACK (on_device_active_ap_changed_cb), + self, G_CONNECT_SWAPPED); + on_device_state_changed_cb (self, NULL, self->device); + + /* Simulate a change notification on the available connections. + * This uses the implementation detail that the list is rebuild + * completely in this case. */ + update_connections (self); +} + +static void +cc_wifi_connection_list_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + CcWifiConnectionList *self = CC_WIFI_CONNECTION_LIST (object); + + switch (prop_id) + { + case PROP_CHECKABLE: + g_value_set_boolean (value, self->checkable); + break; + + case PROP_HIDE_UNAVAILABLE: + g_value_set_boolean (value, self->hide_unavailable); + break; + + case PROP_SHOW_APS: + g_value_set_boolean (value, self->show_aps); + break; + + case PROP_CLIENT: + g_value_set_object (value, self->client); + break; + + case PROP_DEVICE: + g_value_set_object (value, self->device); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +cc_wifi_connection_list_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + CcWifiConnectionList *self = CC_WIFI_CONNECTION_LIST (object); + + switch (prop_id) + { + case PROP_CHECKABLE: + self->checkable = g_value_get_boolean (value); + break; + + case PROP_HIDE_UNAVAILABLE: + self->hide_unavailable = g_value_get_boolean (value); + break; + + case PROP_SHOW_APS: + self->show_aps = g_value_get_boolean (value); + break; + + case PROP_CLIENT: + self->client = g_value_dup_object (value); + break; + + case PROP_DEVICE: + self->device = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +cc_wifi_connection_list_class_init (CcWifiConnectionListClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = cc_wifi_connection_list_constructed; + object_class->dispose = cc_wifi_connection_list_dispose; + object_class->finalize = cc_wifi_connection_list_finalize; + object_class->get_property = cc_wifi_connection_list_get_property; + object_class->set_property = cc_wifi_connection_list_set_property; + + props[PROP_CHECKABLE] = + g_param_spec_boolean ("checkable", "checkable", + "Passed to the created rows to show/hide the checkbox for deletion", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + props[PROP_HIDE_UNAVAILABLE] = + g_param_spec_boolean ("hide-unavailable", "HideUnavailable", + "Whether to show or hide unavailable connections", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + props[PROP_SHOW_APS] = + g_param_spec_boolean ("show-aps", "ShowAPs", + "Whether to show available SSIDs/APs without a connection", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + props[PROP_CLIENT] = + g_param_spec_object ("client", "NMClient", + "The NM Client", + NM_TYPE_CLIENT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + props[PROP_DEVICE] = + g_param_spec_object ("device", "WiFi Device", + "The WiFi Device for this connection list", + NM_TYPE_DEVICE_WIFI, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, + PROP_LAST, + props); + + g_signal_new ("configure", + CC_TYPE_WIFI_CONNECTION_LIST, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 1, CC_TYPE_WIFI_CONNECTION_ROW); +} + +static void +cc_wifi_connection_list_init (CcWifiConnectionList *self) +{ + self->hide_unavailable = TRUE; + self->show_aps = TRUE; + + self->connections = g_ptr_array_new_with_free_func (g_object_unref); + self->connections_row = g_ptr_array_new (); + self->ssid_to_row = g_hash_table_new_full (g_bytes_hash, g_bytes_equal, + (GDestroyNotify) g_bytes_unref, NULL); + self->ap_ssid_cache = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) g_bytes_unref); +} + +CcWifiConnectionList * +cc_wifi_connection_list_new (NMClient *client, + NMDeviceWifi *device, + gboolean hide_unavailable, + gboolean show_aps, + gboolean checkable) +{ + return g_object_new (CC_TYPE_WIFI_CONNECTION_LIST, + "client", client, + "device", device, + "hide-unavailable", hide_unavailable, + "show-aps", show_aps, + "checkable", checkable, + NULL); +} + +void +cc_wifi_connection_list_freeze (CcWifiConnectionList *list) +{ + g_return_if_fail (CC_WIFI_CONNECTION_LIST (list)); + + if (list->freeze_count == 0) + g_debug ("wifi connection list has been frozen"); + + list->freeze_count += 1; +} + +void +cc_wifi_connection_list_thaw (CcWifiConnectionList *list) +{ + g_return_if_fail (CC_WIFI_CONNECTION_LIST (list)); + + g_return_if_fail (list->freeze_count > 0); + + list->freeze_count -= 1; + + if (list->freeze_count == 0) + { + g_debug ("wifi connection list has been thawed"); + update_connections (list); + } +} diff --git a/panels/network/cc-wifi-connection-list.h b/panels/network/cc-wifi-connection-list.h new file mode 100644 index 0000000000..67dc23d81a --- /dev/null +++ b/panels/network/cc-wifi-connection-list.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2018 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +#define CC_TYPE_WIFI_CONNECTION_LIST (cc_wifi_connection_list_get_type()) + +G_DECLARE_FINAL_TYPE (CcWifiConnectionList, cc_wifi_connection_list, CC, WIFI_CONNECTION_LIST, GtkListBox) + +CcWifiConnectionList *cc_wifi_connection_list_new (NMClient *client, + NMDeviceWifi *device, + gboolean hide_unavailable, + gboolean show_aps, + gboolean checkable); + + +void cc_wifi_connection_list_freeze (CcWifiConnectionList *list); +void cc_wifi_connection_list_thaw (CcWifiConnectionList *list); + +G_END_DECLS diff --git a/panels/network/meson.build b/panels/network/meson.build index 151b589b6b..ec9df3263f 100644 --- a/panels/network/meson.build +++ b/panels/network/meson.build @@ -36,6 +36,7 @@ endforeach sources = files( 'cc-network-panel.c', 'cc-wifi-connection-row.c', + 'cc-wifi-connection-list.c', 'cc-wifi-panel.c', 'net-device.c', 'net-device-ethernet.c', -- GitLab From d126b3db5e8b4fd58bf96151c73b341f5b2eced8 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sat, 15 Dec 2018 17:54:13 +0100 Subject: [PATCH 12/13] wifi: Hook up new connection list widget --- panels/network/cc-wifi-connection-row.ui | 2 +- panels/network/net-device-wifi.c | 463 ++++++----------------- panels/network/network-wifi.ui | 11 +- 3 files changed, 118 insertions(+), 358 deletions(-) diff --git a/panels/network/cc-wifi-connection-row.ui b/panels/network/cc-wifi-connection-row.ui index 715694bc7b..d0c8960932 100644 --- a/panels/network/cc-wifi-connection-row.ui +++ b/panels/network/cc-wifi-connection-row.ui @@ -4,7 +4,7 @@