From e05fb7b3e36c052baf0dd607ddeb22c0a2b5cbde Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:47:04 +0200 Subject: Adding upstream version 43.2. Signed-off-by: Daniel Baumann --- .../pages/network/gis-network-page.c | 828 +++++++++++++++++++++ 1 file changed, 828 insertions(+) create mode 100644 gnome-initial-setup/pages/network/gis-network-page.c (limited to 'gnome-initial-setup/pages/network/gis-network-page.c') diff --git a/gnome-initial-setup/pages/network/gis-network-page.c b/gnome-initial-setup/pages/network/gis-network-page.c new file mode 100644 index 0000000..859288f --- /dev/null +++ b/gnome-initial-setup/pages/network/gis-network-page.c @@ -0,0 +1,828 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* + * Copyright (C) 2012 Red Hat + * + * 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 . + * + * Written by: + * Jasper St. Pierre + */ + +/* Network page {{{1 */ + +#define PAGE_ID "network" + +#include "config.h" +#include "network-resources.h" +#include "gis-network-page.h" + +#include +#include + +#include "network-dialogs.h" + +#include "gis-page-header.h" + +typedef enum { + NM_AP_SEC_UNKNOWN, + NM_AP_SEC_NONE, + NM_AP_SEC_WEP, + NM_AP_SEC_WPA, + NM_AP_SEC_WPA2 +} NMAccessPointSecurity; + +struct _GisNetworkPagePrivate { + GtkWidget *network_list; + GtkWidget *no_network_label; + GtkWidget *no_network_spinner; + GtkWidget *turn_on_label; + GtkWidget *turn_on_switch; + + NMClient *nm_client; + NMDevice *nm_device; + gboolean refreshing; + GtkSizeGroup *icons; + + guint refresh_timeout_id; + + /* TRUE if the page has ever been shown to the user. */ + gboolean ever_shown; +}; +typedef struct _GisNetworkPagePrivate GisNetworkPagePrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (GisNetworkPage, gis_network_page, GIS_TYPE_PAGE); + +static GPtrArray * +get_strongest_unique_aps (const GPtrArray *aps) +{ + GBytes *ssid; + GBytes *ssid_tmp; + GPtrArray *unique = NULL; + gboolean add_ap; + guint i; + guint j; + NMAccessPoint *ap; + NMAccessPoint *ap_tmp; + + /* we will have multiple entries for typical hotspots, + * just keep the one with the strongest signal + */ + unique = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + if (aps == NULL) + goto out; + + for (i = 0; i < aps->len; i++) { + ap = NM_ACCESS_POINT (g_ptr_array_index (aps, i)); + ssid = nm_access_point_get_ssid (ap); + add_ap = TRUE; + + if (!ssid) + continue; + + /* get already added list */ + for (j = 0; j < unique->len; j++) { + ap_tmp = NM_ACCESS_POINT (g_ptr_array_index (unique, j)); + ssid_tmp = nm_access_point_get_ssid (ap_tmp); + + /* is this the same type and data? */ + if (ssid_tmp && + 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)) { + /* the new access point is stronger */ + if (nm_access_point_get_strength (ap) > + nm_access_point_get_strength (ap_tmp)) { + g_ptr_array_remove (unique, ap_tmp); + add_ap = TRUE; + } else { + add_ap = FALSE; + } + break; + } + } + if (add_ap) { + g_ptr_array_add (unique, g_object_ref (ap)); + } + } + + out: + return unique; +} + +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 gint +ap_sort (GtkListBoxRow *a, + GtkListBoxRow *b, + gpointer data) +{ + GtkWidget *wa, *wb; + guint sa, sb; + + wa = gtk_list_box_row_get_child (a); + wb = gtk_list_box_row_get_child (b); + + sa = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (wa), "strength")); + sb = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (wb), "strength")); + if (sa > sb) return -1; + if (sb > sa) return 1; + + return 0; +} + +static void +add_access_point (GisNetworkPage *page, NMAccessPoint *ap, NMAccessPoint *active) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + GBytes *ssid; + GBytes *ssid_active = NULL; + gchar *ssid_text; + const gchar *object_path; + gboolean activated, activating; + guint security; + guint strength; + const gchar *icon_name; + GtkWidget *row; + GtkWidget *widget; + GtkWidget *grid; + GtkWidget *state_widget = NULL; + + ssid = nm_access_point_get_ssid (ap); + object_path = nm_object_get_path (NM_OBJECT (ap)); + + if (ssid == NULL) + return; + ssid_text = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); + + if (active) + ssid_active = nm_access_point_get_ssid (active); + if (ssid_active && nm_utils_same_ssid (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), + g_bytes_get_data (ssid_active, NULL), g_bytes_get_size (ssid_active), TRUE)) { + switch (nm_device_get_state (priv->nm_device)) + { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_SECONDARIES: + activated = FALSE; + activating = TRUE; + break; + case NM_DEVICE_STATE_ACTIVATED: + activated = TRUE; + activating = FALSE; + break; + default: + activated = FALSE; + activating = FALSE; + break; + } + } else { + activated = FALSE; + activating = FALSE; + } + + security = get_access_point_security (ap); + strength = nm_access_point_get_strength (ap); + + row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_widget_set_margin_start (row, 12); + gtk_widget_set_margin_end (row, 12); + widget = gtk_label_new (ssid_text); + gtk_widget_set_margin_top (widget, 12); + gtk_widget_set_margin_bottom (widget, 12); + gtk_box_append (GTK_BOX (row), widget); + + if (activated) { + state_widget = gtk_image_new_from_icon_name ("object-select-symbolic"); + } else if (activating) { + state_widget = gtk_spinner_new (); + gtk_spinner_start (GTK_SPINNER (state_widget)); + } + + if (state_widget) { + gtk_widget_set_halign (state_widget, GTK_ALIGN_START); + gtk_widget_set_valign (state_widget, GTK_ALIGN_CENTER); + gtk_widget_set_hexpand (state_widget, TRUE); + gtk_box_append (GTK_BOX (row), state_widget); + } + + grid = gtk_grid_new (); + gtk_grid_set_column_spacing (GTK_GRID (grid), 6); + gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE); + gtk_widget_set_valign (grid, GTK_ALIGN_CENTER); + gtk_size_group_add_widget (priv->icons, grid); + gtk_box_append (GTK_BOX (row), grid); + + if (security != NM_AP_SEC_UNKNOWN && + security != NM_AP_SEC_NONE) { + widget = gtk_image_new_from_icon_name ("network-wireless-encrypted-symbolic"); + gtk_grid_attach (GTK_GRID (grid), widget, 0, 0, 1, 1); + } + + 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_widget_set_halign (widget, GTK_ALIGN_END); + gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1); + + /* if this connection is the active one or is being activated, then make sure + * it's sorted before all others */ + if (activating || activated) + strength = G_MAXUINT; + + g_object_set_data (G_OBJECT (row), "object-path", (gpointer) object_path); + g_object_set_data (G_OBJECT (row), "ssid", (gpointer) ssid); + g_object_set_data (G_OBJECT (row), "strength", GUINT_TO_POINTER (strength)); + + gtk_list_box_append (GTK_LIST_BOX (priv->network_list), row); +} + +static void +add_access_point_other (GisNetworkPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + GtkWidget *row; + GtkWidget *widget; + + row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_widget_set_margin_start (row, 12); + gtk_widget_set_margin_end (row, 12); + widget = gtk_label_new (C_("Wireless access point", "Other…")); + gtk_widget_set_margin_top (widget, 12); + gtk_widget_set_margin_bottom (widget, 12); + gtk_box_append (GTK_BOX (row), widget); + + g_object_set_data (G_OBJECT (row), "object-path", "ap-other..."); + g_object_set_data (G_OBJECT (row), "strength", GUINT_TO_POINTER (0)); + + gtk_list_box_append (GTK_LIST_BOX (priv->network_list), row); +} + +static gboolean refresh_wireless_list (GisNetworkPage *page); + +static void +cancel_periodic_refresh (GisNetworkPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + + if (priv->refresh_timeout_id == 0) + return; + + g_debug ("Stopping periodic/scheduled Wi-Fi list refresh"); + + g_clear_handle_id (&priv->refresh_timeout_id, g_source_remove); +} + +static gboolean +refresh_again (gpointer user_data) +{ + GisNetworkPage *page = GIS_NETWORK_PAGE (user_data); + refresh_wireless_list (page); + return G_SOURCE_REMOVE; +} + +static void +start_periodic_refresh (GisNetworkPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + static const guint periodic_wifi_refresh_timeout_sec = 10; + + cancel_periodic_refresh (page); + + g_debug ("Starting periodic Wi-Fi list refresh (every %u secs)", + periodic_wifi_refresh_timeout_sec); + priv->refresh_timeout_id = g_timeout_add_seconds (periodic_wifi_refresh_timeout_sec, + refresh_again, page); +} + +static gboolean +refresh_wireless_list (GisNetworkPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + NMAccessPoint *active_ap = NULL; + NMAccessPoint *ap; + const GPtrArray *aps; + GPtrArray *unique_aps; + GtkWidget *child; + guint i; + gboolean enabled; + + g_debug ("Refreshing Wi-Fi networks list"); + + priv->refreshing = TRUE; + + g_assert (NM_IS_DEVICE_WIFI (priv->nm_device)); + + cancel_periodic_refresh (page); + + active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (priv->nm_device)); + + while ((child = gtk_widget_get_first_child (priv->network_list)) != NULL) + gtk_list_box_remove (GTK_LIST_BOX (priv->network_list), child); + + aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (priv->nm_device)); + enabled = nm_client_wireless_get_enabled (priv->nm_client); + + if (aps == NULL || aps->len == 0) { + gboolean hw_enabled; + + hw_enabled = nm_client_wireless_hardware_get_enabled (priv->nm_client); + + if (!enabled || !hw_enabled) { + gtk_label_set_text (GTK_LABEL (priv->no_network_label), _("Wireless networking is disabled")); + gtk_widget_show (priv->no_network_label); + gtk_widget_hide (priv->no_network_spinner); + + gtk_widget_set_visible (priv->turn_on_label, hw_enabled); + gtk_widget_set_visible (priv->turn_on_switch, hw_enabled); + } else { + gtk_label_set_text (GTK_LABEL (priv->no_network_label), _("Checking for available wireless networks")); + gtk_widget_show (priv->no_network_spinner); + gtk_widget_show (priv->no_network_label); + gtk_widget_hide (priv->turn_on_label); + gtk_widget_hide (priv->turn_on_switch); + } + + gtk_widget_hide (priv->network_list); + goto out; + + } else { + gtk_widget_hide (priv->no_network_spinner); + gtk_widget_hide (priv->no_network_label); + gtk_widget_hide (priv->turn_on_label); + gtk_widget_hide (priv->turn_on_switch); + gtk_widget_show (priv->network_list); + } + + unique_aps = get_strongest_unique_aps (aps); + for (i = 0; i < unique_aps->len; i++) { + ap = NM_ACCESS_POINT (g_ptr_array_index (unique_aps, i)); + add_access_point (page, ap, active_ap); + } + g_ptr_array_unref (unique_aps); + add_access_point_other (page); + + out: + + if (enabled) + start_periodic_refresh (page); + + priv->refreshing = FALSE; + + return G_SOURCE_REMOVE; +} + +/* Avoid repeated calls to refreshing the wireless list by making it refresh at + * most once per second */ +static void +schedule_refresh_wireless_list (GisNetworkPage *page) +{ + static const guint refresh_wireless_list_timeout_sec = 1; + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + + cancel_periodic_refresh (page); + + g_debug ("Delaying Wi-Fi list refresh (for %u sec)", + refresh_wireless_list_timeout_sec); + + priv->refresh_timeout_id = g_timeout_add_seconds (refresh_wireless_list_timeout_sec, + (GSourceFunc) refresh_wireless_list, + page); +} + +static void +connection_activate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient *client = NM_CLIENT (object); + NMActiveConnection *connection = NULL; + g_autoptr(GError) error = NULL; + + connection = nm_client_activate_connection_finish (client, result, &error); + if (connection != NULL) { + g_clear_object (&connection); + } else { + /* failed to activate */ + g_warning ("Failed to activate a connection: %s", error->message); + } +} + +static void +connection_add_activate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient *client = NM_CLIENT (object); + NMActiveConnection *connection = NULL; + g_autoptr(GError) error = NULL; + + connection = nm_client_add_and_activate_connection_finish (client, result, &error); + if (connection != NULL) { + g_clear_object (&connection); + } else { + /* failed to activate */ + g_warning ("Failed to add and activate a connection: %s", error->message); + } +} + +static void +connect_to_hidden_network (GisNetworkPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (page)); + + cc_network_panel_connect_to_hidden_network (GTK_WIDGET (root), priv->nm_client); +} + +static void +row_activated (GtkListBox *box, + GtkListBoxRow *row, + GisNetworkPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + gchar *object_path; + const GPtrArray *list; + GPtrArray *filtered; + NMConnection *connection; + NMConnection *connection_to_activate; + NMSettingWireless *setting; + GBytes *ssid; + GBytes *ssid_target; + GtkWidget *child; + int i; + + if (priv->refreshing) + return; + + child = gtk_list_box_row_get_child (row); + object_path = g_object_get_data (G_OBJECT (child), "object-path"); + ssid_target = g_object_get_data (G_OBJECT (child), "ssid"); + + if (g_strcmp0 (object_path, "ap-other...") == 0) { + connect_to_hidden_network (page); + goto out; + } + + list = nm_client_get_connections (priv->nm_client); + filtered = nm_device_filter_connections (priv->nm_device, list); + + connection_to_activate = NULL; + + for (i = 0; i < filtered->len; i++) { + connection = NM_CONNECTION (filtered->pdata[i]); + setting = nm_connection_get_setting_wireless (connection); + if (!NM_IS_SETTING_WIRELESS (setting)) + continue; + + ssid = nm_setting_wireless_get_ssid (setting); + if (ssid == NULL) + continue; + + if (nm_utils_same_ssid (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid), + g_bytes_get_data (ssid_target, NULL), g_bytes_get_size (ssid_target), TRUE)) { + connection_to_activate = connection; + break; + } + } + g_ptr_array_unref (filtered); + + if (connection_to_activate != NULL) { + nm_client_activate_connection_async (priv->nm_client, + connection_to_activate, + priv->nm_device, NULL, + NULL, + connection_activate_cb, page); + return; + } + + nm_client_add_and_activate_connection_async (priv->nm_client, + NULL, + priv->nm_device, object_path, + NULL, + connection_add_activate_cb, page); + + out: + schedule_refresh_wireless_list (page); +} + +static void +connection_state_changed (NMActiveConnection *c, GParamSpec *pspec, GisNetworkPage *page) +{ + schedule_refresh_wireless_list (page); +} + +static void +active_connections_changed (NMClient *client, GParamSpec *pspec, GisNetworkPage *page) +{ + const GPtrArray *connections; + guint i; + + connections = nm_client_get_active_connections (client); + for (i = 0; connections && (i < connections->len); i++) { + NMActiveConnection *connection; + + connection = g_ptr_array_index (connections, i); + if (!g_object_get_data (G_OBJECT (connection), "has-state-changed-handler")) { + g_signal_connect (connection, "notify::state", + G_CALLBACK (connection_state_changed), page); + g_object_set_data (G_OBJECT (connection), "has-state-changed-handler", GINT_TO_POINTER (1)); + } + } +} + +static void +sync_complete (GisNetworkPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + gboolean has_device; + gboolean activated; + gboolean visible; + + has_device = priv->nm_device != NULL; + activated = priv->nm_device != NULL + && nm_device_get_state (priv->nm_device) == NM_DEVICE_STATE_ACTIVATED; + + if (priv->ever_shown) { + visible = TRUE; + } else if (!has_device) { + g_debug ("No network device found, hiding network page"); + visible = FALSE; + } else if (activated) { + g_debug ("Activated network device found, hiding network page"); + visible = FALSE; + } else { + visible = TRUE; + } + + gis_page_set_complete (GIS_PAGE (page), activated); + gtk_widget_set_visible (GTK_WIDGET (page), visible); + + if (has_device) + schedule_refresh_wireless_list (page); +} + +static void +device_state_changed (GObject *object, GParamSpec *param, GisNetworkPage *page) +{ + sync_complete (page); +} + +static void +find_best_device (GisNetworkPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + const GPtrArray *devices; + guint i; + + /* FIXME: deal with multiple devices and devices being removed */ + if (priv->nm_device != NULL) { + g_debug ("Already showing network device %s", + nm_device_get_description (priv->nm_device)); + return; + } + + devices = nm_client_get_devices (priv->nm_client); + g_return_if_fail (devices != NULL); + for (i = 0; i < devices->len; i++) { + NMDevice *device = g_ptr_array_index (devices, i); + + if (!nm_device_get_managed (device)) + continue; + + if (nm_device_get_device_type (device) == NM_DEVICE_TYPE_WIFI) { + /* FIXME deal with multiple, dynamic devices */ + priv->nm_device = g_object_ref (device); + g_debug ("Showing network device %s", + nm_device_get_description (priv->nm_device)); + + g_signal_connect (priv->nm_device, "notify::state", + G_CALLBACK (device_state_changed), page); + g_signal_connect (priv->nm_client, "notify::active-connections", + G_CALLBACK (active_connections_changed), page); + + break; + } + } + + sync_complete (page); +} +static void +device_notify_managed (NMDevice *device, + GParamSpec *param, + void *user_data) +{ + GisNetworkPage *page = GIS_NETWORK_PAGE (user_data); + + find_best_device (page); +} + +static void +client_device_added (NMClient *client, + NMDevice *device, + void *user_data) +{ + GisNetworkPage *page = GIS_NETWORK_PAGE (user_data); + + g_signal_connect_object (device, + "notify::managed", + G_CALLBACK (device_notify_managed), + G_OBJECT (page), + 0); + + find_best_device (page); +} + +static void +client_device_removed (NMClient *client, + NMDevice *device, + void *user_data) +{ + GisNetworkPage *page = GIS_NETWORK_PAGE (user_data); + + /* TODO: reset page if priv->nm_device == device */ + g_signal_handlers_disconnect_by_func (device, device_notify_managed, page); + + find_best_device (page); +} + +static void +monitor_network_devices (GisNetworkPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + const GPtrArray *devices; + guint i; + + g_assert (priv->nm_client != NULL); + devices = nm_client_get_devices (priv->nm_client); + g_return_if_fail (devices != NULL); + for (i = 0; devices != NULL && i < devices->len; i++) { + NMDevice *device = g_ptr_array_index (devices, i); + + g_signal_connect_object (device, + "notify::managed", + G_CALLBACK (device_notify_managed), + G_OBJECT (page), + 0); + } + + g_signal_connect_object (priv->nm_client, + "device-added", + G_CALLBACK (client_device_added), + G_OBJECT (page), + 0); + g_signal_connect_object (priv->nm_client, + "device-removed", + G_CALLBACK (client_device_removed), + G_OBJECT (page), + 0); + + find_best_device (page); +} + +static void +gis_network_page_constructed (GObject *object) +{ + GisNetworkPage *page = GIS_NETWORK_PAGE (object); + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + g_autoptr(GError) error = NULL; + + G_OBJECT_CLASS (gis_network_page_parent_class)->constructed (object); + + gis_page_set_skippable (GIS_PAGE (page), TRUE); + + priv->ever_shown = g_getenv ("GIS_ALWAYS_SHOW_NETWORK_PAGE") != NULL; + priv->icons = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + gtk_list_box_set_selection_mode (GTK_LIST_BOX (priv->network_list), GTK_SELECTION_NONE); + gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->network_list), ap_sort, NULL, NULL); + g_signal_connect (priv->network_list, "row-activated", + G_CALLBACK (row_activated), page); + + priv->nm_client = nm_client_new (NULL, &error); + if (!priv->nm_client) { + g_warning ("Can't create NetworkManager client, hiding network page: %s", + error->message); + sync_complete (page); + return; + } + + g_object_bind_property (priv->nm_client, "wireless-enabled", + priv->turn_on_switch, "active", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + monitor_network_devices (page); +} + +static void +gis_network_page_dispose (GObject *object) +{ + GisNetworkPage *page = GIS_NETWORK_PAGE (object); + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (page); + + g_clear_object (&priv->nm_client); + g_clear_object (&priv->nm_device); + g_clear_object (&priv->icons); + + cancel_periodic_refresh (page); + + G_OBJECT_CLASS (gis_network_page_parent_class)->dispose (object); +} + +static void +gis_network_page_locale_changed (GisPage *page) +{ + gis_page_set_title (GIS_PAGE (page), _("Network")); +} + +static void +gis_network_page_shown (GisPage *page) +{ + GisNetworkPagePrivate *priv = gis_network_page_get_instance_private (GIS_NETWORK_PAGE (page)); + + priv->ever_shown = TRUE; +} + +static void +gis_network_page_class_init (GisNetworkPageClass *klass) +{ + GisPageClass *page_class = GIS_PAGE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/initial-setup/gis-network-page.ui"); + + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisNetworkPage, network_list); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisNetworkPage, no_network_label); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisNetworkPage, no_network_spinner); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisNetworkPage, turn_on_label); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisNetworkPage, turn_on_switch); + + page_class->page_id = PAGE_ID; + page_class->locale_changed = gis_network_page_locale_changed; + page_class->shown = gis_network_page_shown; + object_class->constructed = gis_network_page_constructed; + object_class->dispose = gis_network_page_dispose; +} + +static void +gis_network_page_init (GisNetworkPage *page) +{ + g_resources_register (network_get_resource ()); + g_type_ensure (GIS_TYPE_PAGE_HEADER); + + gtk_widget_init_template (GTK_WIDGET (page)); +} + +GisPage * +gis_prepare_network_page (GisDriver *driver) +{ + return g_object_new (GIS_TYPE_NETWORK_PAGE, + "driver", driver, + NULL); +} -- cgit v1.2.3