In some cases, the network connection UI uses pango markup to denote the SSID name inside a connection name. However, if the SSID matched the connection name, then we would end up setting the SSID as pango markup without it being escaped. Fix this by escaping the SSID before setting it as markup. Fixes: #435
636 lines
19 KiB
C
636 lines
19 KiB
C
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <glib/gi18n.h>
|
|
#include <config.h>
|
|
#include "cc-wifi-connection-row.h"
|
|
|
|
struct _CcWifiConnectionRow
|
|
{
|
|
GtkListBoxRow parent_instance;
|
|
|
|
gboolean constructed;
|
|
|
|
gboolean checkable;
|
|
gboolean checked;
|
|
|
|
NMDeviceWifi *device;
|
|
GPtrArray *aps;
|
|
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_APS,
|
|
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 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)
|
|
{
|
|
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;
|
|
NMActiveConnectionState state;
|
|
|
|
g_assert (self->device);
|
|
g_assert (self->connection || self->aps->len > 0);
|
|
|
|
best_ap = cc_wifi_connection_row_best_access_point (self);
|
|
|
|
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)
|
|
{
|
|
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_markup_escape_text (name, -1);
|
|
}
|
|
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 ("<i>%s</i>%s<i>%s</i>",
|
|
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 (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 (active_connection)
|
|
{
|
|
state = nm_active_connection_get_state (active_connection);
|
|
|
|
active = state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
|
|
connecting = state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING;
|
|
}
|
|
else
|
|
{
|
|
active = FALSE;
|
|
connecting = FALSE;
|
|
}
|
|
|
|
if (self->connection)
|
|
security = get_connection_security (self->connection);
|
|
|
|
if (best_ap != NULL)
|
|
{
|
|
security = get_access_point_security (best_ap);
|
|
strength = nm_access_point_get_strength (best_ap);
|
|
}
|
|
|
|
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)
|
|
{
|
|
gchar *icon_name;
|
|
|
|
gtk_widget_set_child_visible (GTK_WIDGET (self->encrypted_icon), TRUE);
|
|
if (security == NM_AP_SEC_WEP)
|
|
icon_name = "channel-insecure-symbolic";
|
|
else
|
|
icon_name = "network-wireless-encrypted-symbolic";
|
|
|
|
g_object_set (self->encrypted_icon, "icon-name", icon_name, NULL);
|
|
}
|
|
else
|
|
{
|
|
gtk_widget_set_child_visible (GTK_WIDGET (self->encrypted_icon), FALSE);
|
|
}
|
|
|
|
if (best_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);
|
|
GPtrArray *ptr_array;
|
|
gint i;
|
|
|
|
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_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:
|
|
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);
|
|
GPtrArray *ptr_array;
|
|
gint i;
|
|
|
|
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_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:
|
|
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_pointer (&self->aps, g_ptr_array_unref);
|
|
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_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)",
|
|
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);
|
|
|
|
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 (NMDeviceWifi *device,
|
|
NMConnection *connection,
|
|
GPtrArray *aps,
|
|
gboolean checkable)
|
|
{
|
|
return g_object_new (CC_TYPE_WIFI_CONNECTION_ROW,
|
|
"device", device,
|
|
"connection", connection,
|
|
"aps", aps,
|
|
"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;
|
|
}
|
|
|
|
const GPtrArray*
|
|
cc_wifi_connection_row_get_access_points (CcWifiConnectionRow *row)
|
|
{
|
|
g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), NULL);
|
|
|
|
return row->aps;
|
|
}
|
|
|
|
NMConnection*
|
|
cc_wifi_connection_row_get_connection (CcWifiConnectionRow *row)
|
|
{
|
|
g_return_val_if_fail (CC_WIFI_CONNECTION_ROW (row), NULL);
|
|
|
|
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)
|
|
{
|
|
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));
|
|
|
|
}
|
|
|