diff options
Diffstat (limited to 'gnome-initial-setup/pages/network')
-rw-r--r-- | gnome-initial-setup/pages/network/gis-network-page.c | 828 | ||||
-rw-r--r-- | gnome-initial-setup/pages/network/gis-network-page.h | 55 | ||||
-rw-r--r-- | gnome-initial-setup/pages/network/gis-network-page.ui | 99 | ||||
-rw-r--r-- | gnome-initial-setup/pages/network/meson.build | 12 | ||||
-rw-r--r-- | gnome-initial-setup/pages/network/network-dialogs.c | 515 | ||||
-rw-r--r-- | gnome-initial-setup/pages/network/network-dialogs.h | 41 | ||||
-rw-r--r-- | gnome-initial-setup/pages/network/network.gresource.xml | 6 |
7 files changed, 1556 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>. + * + * Written by: + * Jasper St. Pierre <jstpierre@mecheye.net> + */ + +/* Network page {{{1 */ + +#define PAGE_ID "network" + +#include "config.h" +#include "network-resources.h" +#include "gis-network-page.h" + +#include <glib/gi18n.h> +#include <gio/gio.h> + +#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); +} diff --git a/gnome-initial-setup/pages/network/gis-network-page.h b/gnome-initial-setup/pages/network/gis-network-page.h new file mode 100644 index 0000000..172b7d1 --- /dev/null +++ b/gnome-initial-setup/pages/network/gis-network-page.h @@ -0,0 +1,55 @@ +/* -*- 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 <http://www.gnu.org/licenses/>. + * + * Written by: + * Jasper St. Pierre <jstpierre@mecheye.net> + */ + +#ifndef __GIS_NETWORK_PAGE_H__ +#define __GIS_NETWORK_PAGE_H__ + +#include "gnome-initial-setup.h" + +G_BEGIN_DECLS + +#define GIS_TYPE_NETWORK_PAGE (gis_network_page_get_type ()) +#define GIS_NETWORK_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_NETWORK_PAGE, GisNetworkPage)) +#define GIS_NETWORK_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_NETWORK_PAGE, GisNetworkPageClass)) +#define GIS_IS_NETWORK_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_NETWORK_PAGE)) +#define GIS_IS_NETWORK_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_NETWORK_PAGE)) +#define GIS_NETWORK_PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_NETWORK_PAGE, GisNetworkPageClass)) + +typedef struct _GisNetworkPage GisNetworkPage; +typedef struct _GisNetworkPageClass GisNetworkPageClass; + +struct _GisNetworkPage +{ + GisPage parent; +}; + +struct _GisNetworkPageClass +{ + GisPageClass parent_class; +}; + +GType gis_network_page_get_type (void); + +GisPage *gis_prepare_network_page (GisDriver *driver); + +G_END_DECLS + +#endif /* __GIS_NETWORK_PAGE_H__ */ diff --git a/gnome-initial-setup/pages/network/gis-network-page.ui b/gnome-initial-setup/pages/network/gis-network-page.ui new file mode 100644 index 0000000..2bda59c --- /dev/null +++ b/gnome-initial-setup/pages/network/gis-network-page.ui @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <template class="GisNetworkPage" parent="GisPage"> + <child> + <object class="AdwPreferencesPage"> + <child> + <object class="AdwPreferencesGroup"> + <child> + <object class="GtkBox" id="box"> + <property name="orientation">vertical</property> + <property name="margin_bottom">32</property> + <child> + <object class="GisPageHeader" id="header"> + <property name="margin_top">24</property> + <property name="title" translatable="yes">Wi-Fi</property> + <property name="subtitle" translatable="yes">Connecting to the internet helps you get new apps, information, and other upgrades. It also helps set the time and your location automatically.</property> + <property name="icon_name">network-wireless-symbolic</property> + <property name="show_icon" bind-source="GisNetworkPage" bind-property="small-screen" bind-flags="invert-boolean|sync-create"/> + </object> + </child> + <child> + <object class="GtkListBox" id="network_list"> + <property name="valign">start</property> + <property name="vexpand">True</property> + <property name="margin-top">18</property> + <style> + <class name="boxed-list" /> + </style> + </object> + </child> + <child> + <object class="GtkGrid" id="no_network_grid"> + <property name="margin_top">18</property> + <property name="halign">center</property> + <property name="valign">start</property> + <property name="row-spacing">10</property> + <child> + <object class="GtkSpinner" id="no_network_spinner"> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="margin_start">6</property> + <property name="margin_end">6</property> + <property name="spinning">True</property> + <layout> + <property name="column">0</property> + <property name="row">0</property> + <property name="column-span">1</property> + <property name="row-span">1</property> + </layout> + </object> + </child> + <child> + <object class="GtkLabel" id="no_network_label"> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="label" translatable="yes">No wireless available</property> + <layout> + <property name="column">1</property> + <property name="row">0</property> + <property name="column-span">2</property> + <property name="row-span">1</property> + </layout> + </object> + </child> + <child> + <object class="GtkLabel" id="turn_on_label"> + <property name="halign">start</property> + <property name="valign">center</property> + <property name="label" translatable="yes">Turn On</property> + <layout> + <property name="column">1</property> + <property name="row">1</property> + <property name="column-span">1</property> + <property name="row-span">1</property> + </layout> + </object> + </child> + <child> + <object class="GtkSwitch" id="turn_on_switch"> + <property name="halign">end</property> + <property name="valign">center</property> + <layout> + <property name="column">2</property> + <property name="row">1</property> + <property name="column-span">1</property> + <property name="row-span">1</property> + </layout> + </object> + </child> + </object> + </child> + </object> + </child> + </object> + </child> + </object> + </child> + </template> +</interface> diff --git a/gnome-initial-setup/pages/network/meson.build b/gnome-initial-setup/pages/network/meson.build new file mode 100644 index 0000000..2c0f2a7 --- /dev/null +++ b/gnome-initial-setup/pages/network/meson.build @@ -0,0 +1,12 @@ +sources += gnome.compile_resources( + 'network-resources', + files('network.gresource.xml'), + c_name: 'network' +) + +sources += files( + 'network-dialogs.c', + 'network-dialogs.h', + 'gis-network-page.c', + 'gis-network-page.h' +) diff --git a/gnome-initial-setup/pages/network/network-dialogs.c b/gnome-initial-setup/pages/network/network-dialogs.c new file mode 100644 index 0000000..9018eac --- /dev/null +++ b/gnome-initial-setup/pages/network/network-dialogs.c @@ -0,0 +1,515 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2011 Giovanni Campagna <scampa.giovanni@gmail.com> + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Portions of this code were taken from network-manager-applet. + * Copyright 2008 - 2011 Red Hat, Inc. + */ + +#include <gtk/gtk.h> +#include <NetworkManager.h> +#include <nma-wifi-dialog.h> +#include <nma-mobile-wizard.h> + +typedef struct { + NMClient *client; +} WirelessDialogClosure; + +typedef struct { + NMClient *client; + NMDevice *device; +} MobileDialogClosure; + +static void +wireless_dialog_closure_closure_notify (gpointer data, + GClosure *gclosure) +{ + WirelessDialogClosure *closure = data; + g_object_unref (closure->client); + + g_slice_free (WirelessDialogClosure, data); +} + +static void +mobile_dialog_closure_free (gpointer data) +{ + MobileDialogClosure *closure = data; + g_object_unref (closure->client); + g_object_unref (closure->device); + + g_slice_free (MobileDialogClosure, data); +} + +static gboolean +wifi_can_create_wifi_network (NMClient *client) +{ + NMClientPermissionResult perm; + + /* FIXME: check WIFI_SHARE_PROTECTED too, and make the wireless dialog + * handle the permissions as well so that admins can restrict open network + * creation separately from protected network creation. + */ + perm = nm_client_get_permission_result (client, NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN); + if (perm == NM_CLIENT_PERMISSION_RESULT_YES || perm == NM_CLIENT_PERMISSION_RESULT_AUTH) + return TRUE; + + return FALSE; +} + +static void +activate_existing_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient *client = NM_CLIENT (object); + NMActiveConnection *connection; + GError *error = NULL; + + connection = nm_client_activate_connection_finish (client, result, &error); + if (connection) { + g_object_unref (connection); + } else { + g_warning ("Failed to activate connection: (%d) %s", error->code, error->message); + g_error_free (error); + } +} + +static void +activate_new_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient *client = NM_CLIENT (object); + NMActiveConnection *connection; + GError *error = NULL; + + connection = nm_client_add_and_activate_connection_finish (client, result, &error); + if (connection) { + g_object_unref (connection); + } else { + g_warning ("Failed to add new connection: (%d) %s", error->code, error->message); + g_error_free (error); + } +} + +static void +wireless_dialog_response_cb (GtkDialog *foo, + gint response, + gpointer user_data) +{ + NMAWifiDialog *dialog = NMA_WIFI_DIALOG (foo); + WirelessDialogClosure *closure = user_data; + NMConnection *connection, *fuzzy_match = NULL; + NMDevice *device; + NMAccessPoint *ap; + const GPtrArray *all; + int i; + + if (response != GTK_RESPONSE_OK) + goto done; + + /* nma_wifi_dialog_get_connection() returns a connection with the + * refcount incremented, so the caller must remember to unref it. + */ + connection = nma_wifi_dialog_get_connection (dialog, &device, &ap); + g_assert (connection); + g_assert (device); + + /* Find a similar connection and use that instead */ + all = nm_client_get_connections (closure->client); + for (i = 0; i < all->len; i++) { + if (nm_connection_compare (connection, + NM_CONNECTION (all->pdata[i]), + (NM_SETTING_COMPARE_FLAG_FUZZY | NM_SETTING_COMPARE_FLAG_IGNORE_ID))) { + fuzzy_match = NM_CONNECTION (all->pdata[i]); + break; + } + } + + if (fuzzy_match) { + nm_client_activate_connection_async (closure->client, + fuzzy_match, + device, + ap ? nm_object_get_path (NM_OBJECT (ap)) : NULL, + NULL, + activate_existing_cb, + NULL); + } else { + NMSetting *s_con; + NMSettingWireless *s_wifi; + const char *mode = NULL; + + /* Entirely new connection */ + + /* Don't autoconnect adhoc networks by default for now */ + s_wifi = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS); + if (s_wifi) + mode = nm_setting_wireless_get_mode (s_wifi); + if (g_strcmp0 (mode, "adhoc") == 0) { + s_con = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + if (!s_con) { + s_con = nm_setting_connection_new (); + nm_connection_add_setting (connection, s_con); + } + g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL); + } + + nm_client_add_and_activate_connection_async (closure->client, + connection, + device, + ap ? nm_object_get_path (NM_OBJECT (ap)) : NULL, + NULL, + activate_new_cb, + NULL); + } + + /* Balance nma_wifi_dialog_get_connection() */ + g_object_unref (connection); + +done: + gtk_window_destroy (GTK_WINDOW (dialog)); +} + +static void +show_wireless_dialog (GtkWidget *toplevel, + NMClient *client, + GtkWidget *dialog) +{ + WirelessDialogClosure *closure; + + g_debug ("About to parent and show a network dialog"); + + g_object_set (G_OBJECT (dialog), + "modal", TRUE, + "transient-for", toplevel, + NULL); + + closure = g_slice_new (WirelessDialogClosure); + closure->client = g_object_ref (client); + g_signal_connect_data (dialog, "response", + G_CALLBACK (wireless_dialog_response_cb), + closure, wireless_dialog_closure_closure_notify, 0); + + g_object_bind_property (G_OBJECT (toplevel), "visible", + G_OBJECT (dialog), "visible", + G_BINDING_SYNC_CREATE); +} + +void +cc_network_panel_create_wifi_network (GtkWidget *toplevel, + NMClient *client) +{ + if (wifi_can_create_wifi_network (client)) { + show_wireless_dialog (toplevel, client, + nma_wifi_dialog_new_for_create (client)); + } +} + +void +cc_network_panel_connect_to_hidden_network (GtkWidget *toplevel, + NMClient *client) +{ + g_debug ("connect to hidden wifi"); + show_wireless_dialog (toplevel, client, + nma_wifi_dialog_new_for_hidden (client)); +} + +void +cc_network_panel_connect_to_8021x_network (GtkWidget *toplevel, + NMClient *client, + NMDevice *device, + const gchar *arg_access_point) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSetting8021x *s_8021x; + NM80211ApSecurityFlags wpa_flags, rsn_flags; + GtkWidget *dialog; + char *uuid; + NMAccessPoint *ap; + + g_debug ("connect to 8021x wifi"); + ap = nm_device_wifi_get_access_point_by_path (NM_DEVICE_WIFI (device), arg_access_point); + if (ap == NULL) { + g_warning ("didn't find access point with path %s", arg_access_point); + return; + } + + /* If the AP is WPA[2]-Enterprise then we need to set up a minimal 802.1x + * setting and ask the user for more information. + */ + rsn_flags = nm_access_point_get_rsn_flags (ap); + wpa_flags = nm_access_point_get_wpa_flags (ap); + if (!(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + && !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + g_warning ("Network panel loaded with connect-8021x-wifi but the " + "access point does not support 802.1x"); + return; + } + + connection = nm_simple_connection_new (); + + /* Need a UUID for the "always ask" stuff in the Dialog of Doom */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, NM_SETTING_CONNECTION_UUID, uuid, NULL); + g_free (uuid); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, nm_access_point_get_ssid (ap), + NULL); + + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + nm_setting_802_1x_add_eap_method (s_8021x, "ttls"); + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", NULL); + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + + dialog = nma_wifi_dialog_new (client, connection, device, ap, FALSE); + show_wireless_dialog (toplevel, client, dialog); +} + +static void +connect_3g (NMConnection *connection, + gboolean canceled, + gpointer user_data) +{ + MobileDialogClosure *closure = user_data; + + if (canceled == FALSE) { + g_return_if_fail (connection != NULL); + + /* Ask NM to add the new connection and activate it; NM will fill in the + * missing details based on the specific object and the device. + */ + nm_client_add_and_activate_connection_async (closure->client, + connection, + closure->device, + "/", + NULL, + activate_new_cb, + NULL); + } + + mobile_dialog_closure_free (closure); +} + +static void +cdma_mobile_wizard_done (NMAMobileWizard *wizard, + gboolean canceled, + NMAMobileWizardAccessMethod *method, + gpointer user_data) +{ + NMConnection *connection = NULL; + + if (!canceled && method) { + NMSetting *setting; + char *uuid, *id; + + if (method->devtype != NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) { + g_warning ("Unexpected device type (not CDMA)."); + canceled = TRUE; + goto done; + } + + connection = nm_simple_connection_new (); + + setting = nm_setting_cdma_new (); + g_object_set (setting, + NM_SETTING_CDMA_NUMBER, "#777", + NM_SETTING_CDMA_USERNAME, method->username, + NM_SETTING_CDMA_PASSWORD, method->password, + NULL); + nm_connection_add_setting (connection, setting); + + /* Serial setting */ + setting = nm_setting_serial_new (); + g_object_set (setting, + NM_SETTING_SERIAL_BAUD, 115200, + NM_SETTING_SERIAL_BITS, 8, + NM_SETTING_SERIAL_PARITY, 'n', + NM_SETTING_SERIAL_STOPBITS, 1, + NULL); + nm_connection_add_setting (connection, setting); + + nm_connection_add_setting (connection, nm_setting_ppp_new ()); + + setting = nm_setting_connection_new (); + if (method->plan_name) + id = g_strdup_printf ("%s %s", method->provider_name, method->plan_name); + else + id = g_strdup_printf ("%s connection", method->provider_name); + uuid = nm_utils_uuid_generate (); + g_object_set (setting, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_CDMA_SETTING_NAME, + NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, + NM_SETTING_CONNECTION_UUID, uuid, + NULL); + g_free (uuid); + g_free (id); + nm_connection_add_setting (connection, setting); + } + + done: + connect_3g (connection, canceled, user_data); + nma_mobile_wizard_destroy (wizard); +} + +static void +gsm_mobile_wizard_done (NMAMobileWizard *wizard, + gboolean canceled, + NMAMobileWizardAccessMethod *method, + gpointer user_data) +{ + NMConnection *connection = NULL; + + if (!canceled && method) { + NMSetting *setting; + char *uuid, *id; + + if (method->devtype != NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) { + g_warning ("Unexpected device type (not GSM)."); + canceled = TRUE; + goto done; + } + + connection = nm_simple_connection_new (); + + setting = nm_setting_gsm_new (); + g_object_set (setting, + NM_SETTING_GSM_NUMBER, "*99#", + NM_SETTING_GSM_USERNAME, method->username, + NM_SETTING_GSM_PASSWORD, method->password, + NM_SETTING_GSM_APN, method->gsm_apn, + NULL); + nm_connection_add_setting (connection, setting); + + /* Serial setting */ + setting = nm_setting_serial_new (); + g_object_set (setting, + NM_SETTING_SERIAL_BAUD, 115200, + NM_SETTING_SERIAL_BITS, 8, + NM_SETTING_SERIAL_PARITY, 'n', + NM_SETTING_SERIAL_STOPBITS, 1, + NULL); + nm_connection_add_setting (connection, setting); + + nm_connection_add_setting (connection, nm_setting_ppp_new ()); + + setting = nm_setting_connection_new (); + if (method->plan_name) + id = g_strdup_printf ("%s %s", method->provider_name, method->plan_name); + else + id = g_strdup_printf ("%s connection", method->provider_name); + uuid = nm_utils_uuid_generate (); + g_object_set (setting, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_GSM_SETTING_NAME, + NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, + NM_SETTING_CONNECTION_UUID, uuid, + NULL); + g_free (uuid); + g_free (id); + nm_connection_add_setting (connection, setting); + } + +done: + connect_3g (connection, canceled, user_data); + nma_mobile_wizard_destroy (wizard); +} + +static void +toplevel_shown (GtkWindow *toplevel, + GParamSpec *pspec, + NMAMobileWizard *wizard) +{ + gboolean visible = FALSE; + + g_object_get (G_OBJECT (toplevel), "visible", &visible, NULL); + if (visible) + nma_mobile_wizard_present (wizard); +} + +static gboolean +show_wizard_idle_cb (NMAMobileWizard *wizard) +{ + nma_mobile_wizard_present (wizard); + return FALSE; +} + +void +cc_network_panel_connect_to_3g_network (GtkWidget *toplevel, + NMClient *client, + NMDevice *device) +{ + MobileDialogClosure *closure; + NMAMobileWizard *wizard; + NMDeviceModemCapabilities caps; + gboolean visible = FALSE; + + g_debug ("connect to 3g"); + if (!NM_IS_DEVICE_MODEM (device)) { + g_warning ("Network panel loaded with connect-3g but the selected device" + " is not a modem"); + return; + } + + closure = g_slice_new (MobileDialogClosure); + closure->client = g_object_ref (client); + closure->device = g_object_ref (device); + + caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device)); + if (caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) { + wizard = nma_mobile_wizard_new (GTK_WINDOW (toplevel), NULL, NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS, FALSE, + gsm_mobile_wizard_done, closure); + if (wizard == NULL) { + g_warning ("failed to construct GSM wizard"); + return; + } + } else if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) { + wizard = nma_mobile_wizard_new (GTK_WINDOW (toplevel), NULL, NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO, FALSE, + cdma_mobile_wizard_done, closure); + if (wizard == NULL) { + g_warning ("failed to construct CDMA wizard"); + return; + } + } else { + g_warning ("Network panel loaded with connect-3g but the selected device" + " does not support GSM or CDMA"); + mobile_dialog_closure_free (closure); + return; + } + + g_object_get (G_OBJECT (toplevel), "visible", &visible, NULL); + if (visible) { + g_debug ("Scheduling showing the Mobile wizard"); + g_idle_add ((GSourceFunc) show_wizard_idle_cb, wizard); + } else { + g_debug ("Will show wizard a bit later, toplevel is not visible"); + g_signal_connect (G_OBJECT (toplevel), "notify::visible", + G_CALLBACK (toplevel_shown), wizard); + } +} diff --git a/gnome-initial-setup/pages/network/network-dialogs.h b/gnome-initial-setup/pages/network/network-dialogs.h new file mode 100644 index 0000000..0f02a52 --- /dev/null +++ b/gnome-initial-setup/pages/network/network-dialogs.h @@ -0,0 +1,41 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2011 Giovanni Campagna <scampa.giovanni@gmail.com> + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _NETWORK_DIALOGS_H +#define _NETWORK_DIALOGS_H + +#include <NetworkManager.h> +#include <gtk/gtk.h> + +void cc_network_panel_create_wifi_network (GtkWidget *toplevel, + NMClient *client); + +void cc_network_panel_connect_to_hidden_network (GtkWidget *toplevel, + NMClient *client); + +void cc_network_panel_connect_to_8021x_network (GtkWidget *toplevel, + NMClient *client, + NMDevice *device, + const gchar *arg_access_point); + +void cc_network_panel_connect_to_3g_network (GtkWidget *toplevel, + NMClient *client, + NMDevice *device); + +#endif /* _NETWORK_DIALOGS_H */ diff --git a/gnome-initial-setup/pages/network/network.gresource.xml b/gnome-initial-setup/pages/network/network.gresource.xml new file mode 100644 index 0000000..bf5394f --- /dev/null +++ b/gnome-initial-setup/pages/network/network.gresource.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/org/gnome/initial-setup"> + <file preprocess="xml-stripblanks" alias="gis-network-page.ui">gis-network-page.ui</file> + </gresource> +</gresources> |