[gnome-control-center/wip/benzea/wifi-panel: 20/24] wifi: Handle multiple APs in a connection row



commit 5c81b126472afa0ff65058d805f2836caff871f2
Author: Benjamin Berg <bberg redhat com>
Date:   Sat Dec 15 17:47:25 2018 +0100

    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 2f89435e9..3d2b3f614 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 e29075b83..fa0c2ce74 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 2542054c1..8b77b21b0 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);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]