From 8b593e6ac8dbee259dfbb153fa960e248b15dda6 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 17 Dec 2012 14:17:42 -0500 Subject: [PATCH] network: Implement the new design for wired This expands the connection editor to cover ethernet, and adds support for multiple wired profiles. --- .../connection-editor/8021x-security-page.ui | 295 +++++++++ panels/network/connection-editor/Makefile.am | 6 +- .../ce-page-8021x-security.c | 194 ++++++ .../ce-page-8021x-security.h | 64 ++ .../connection-editor/ce-page-details.c | 44 +- .../connection-editor/ce-page-ethernet.c | 214 +++++++ .../connection-editor/ce-page-ethernet.h | 72 +++ .../network/connection-editor/ce-page-ip4.c | 4 + .../network/connection-editor/ce-page-ip6.c | 4 + panels/network/connection-editor/ce-page.c | 120 +++- panels/network/connection-editor/ce-page.h | 8 + .../connection-editor.gresource.xml | 2 + .../connection-editor/ethernet-page.ui | 273 +++++++++ .../connection-editor/net-connection-editor.c | 82 ++- .../connection-editor/net-connection-editor.h | 1 + panels/network/net-device-ethernet.c | 579 +++++++++++++++++- panels/network/net-device-ethernet.h | 16 +- panels/network/network-ethernet.ui | 216 +++++++ panels/network/network-simple.ui | 370 +++++------ panels/network/network.gresource.xml | 1 + panels/network/panel-common.c | 20 +- panels/network/panel-common.h | 3 + 22 files changed, 2356 insertions(+), 232 deletions(-) create mode 100644 panels/network/connection-editor/8021x-security-page.ui create mode 100644 panels/network/connection-editor/ce-page-8021x-security.c create mode 100644 panels/network/connection-editor/ce-page-8021x-security.h create mode 100644 panels/network/connection-editor/ce-page-ethernet.c create mode 100644 panels/network/connection-editor/ce-page-ethernet.h create mode 100644 panels/network/connection-editor/ethernet-page.ui create mode 100644 panels/network/network-ethernet.ui diff --git a/panels/network/connection-editor/8021x-security-page.ui b/panels/network/connection-editor/8021x-security-page.ui new file mode 100644 index 000000000..7bc8c3a7e --- /dev/null +++ b/panels/network/connection-editor/8021x-security-page.ui @@ -0,0 +1,295 @@ + + + + + True + True + False + False + + + True + False + 50 + 50 + 12 + 12 + True + True + 10 + 6 + + + True + False + 1 + 802.1x _Security + True + 8021x_switch + + + 0 + 0 + 1 + 1 + + + + + True + False + start + True + + + 1 + 0 + 1 + 1 + + + + + True + False + vertical + + + + + + 0 + 1 + 2 + 1 + + + + + + + True + False + page 1 + + + False + + + + + True + False + 50 + 50 + 12 + 12 + 10 + 6 + + + True + True + + 35 + + + 1 + 0 + 1 + 1 + + + + + True + True + + + + 1 + 1 + 1 + 1 + + + + + True + True + + + + 1 + 2 + 1 + 1 + + + + + True + True + + + + 1 + 3 + 1 + 1 + + + + + True + True + + + + 1 + 4 + 1 + 1 + + + + + True + True + + + + 1 + 5 + 1 + 1 + + + + + True + True + + + + 1 + 6 + 1 + 1 + + + + + True + True + + + + 1 + 7 + 1 + 1 + + + + + True + True + + + + 1 + 8 + 1 + 1 + + + + + True + True + + + + 1 + 9 + 1 + 1 + + + + + True + False + Anony_mous identity + True + + + 0 + 0 + 1 + 1 + + + + + True + False + Inner _authentication + True + + + 0 + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + True + False + page 2 + + + 1 + False + + + + + + + + + + diff --git a/panels/network/connection-editor/Makefile.am b/panels/network/connection-editor/Makefile.am index 2dec64abe..db1c15031 100644 --- a/panels/network/connection-editor/Makefile.am +++ b/panels/network/connection-editor/Makefile.am @@ -21,7 +21,11 @@ libconnection_editor_la_SOURCES = \ ce-page-security.h \ ce-page-security.c \ ce-page-reset.h \ - ce-page-reset.c + ce-page-reset.c \ + ce-page-ethernet.h \ + ce-page-ethernet.c \ + ce-page-8021x-security.h \ + ce-page-8021x-security.c libconnection_editor_la_CPPFLAGS = \ -I$(srcdir)/../wireless-security \ diff --git a/panels/network/connection-editor/ce-page-8021x-security.c b/panels/network/connection-editor/ce-page-8021x-security.c new file mode 100644 index 000000000..8a41120e1 --- /dev/null +++ b/panels/network/connection-editor/ce-page-8021x-security.c @@ -0,0 +1,194 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager Connection editor -- Connection editor for NetworkManager + * + * Dan Williams + * + * 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. + * + * (C) Copyright 2008 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "wireless-security.h" +#include "ce-page-ethernet.h" +#include "ce-page-8021x-security.h" + +G_DEFINE_TYPE (CEPage8021xSecurity, ce_page_8021x_security, CE_TYPE_PAGE) + +static void +enable_toggled (GObject *sw, GParamSpec *pspec, gpointer user_data) +{ + CEPage8021xSecurity *page = CE_PAGE_8021X_SECURITY (user_data); + + gtk_widget_set_sensitive (page->security_widget, gtk_switch_get_active (page->enabled)); + ce_page_changed (CE_PAGE (page)); +} + +static void +stuff_changed (WirelessSecurity *sec, gpointer user_data) +{ + ce_page_changed (CE_PAGE (user_data)); +} + +static void +finish_setup (CEPage8021xSecurity *page, gpointer unused, GError *error, gpointer user_data) +{ + GtkWidget *parent; + GtkWidget *vbox; + GtkWidget *heading; + + if (error) + return; + + vbox = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "vbox")); + heading = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "heading_sec")); + + page->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + page->security = (WirelessSecurity *) ws_wpa_eap_new (CE_PAGE (page)->connection, TRUE, FALSE); + if (!page->security) { + g_warning ("Could not load 802.1x user interface."); + return; + } + + wireless_security_set_changed_notify (page->security, stuff_changed, page); + page->security_widget = wireless_security_get_widget (page->security); + parent = gtk_widget_get_parent (page->security_widget); + if (parent) + gtk_container_remove (GTK_CONTAINER (parent), page->security_widget); + + gtk_switch_set_active (page->enabled, page->initial_have_8021x); + g_signal_connect (page->enabled, "notify::active", G_CALLBACK (enable_toggled), page); + gtk_widget_set_sensitive (page->security_widget, page->initial_have_8021x); + + gtk_size_group_add_widget (page->group, heading); + wireless_security_add_to_size_group (page->security, page->group); + + gtk_container_add (GTK_CONTAINER (vbox), page->security_widget); + +} + +CEPage * +ce_page_8021x_security_new (NMConnection *connection, + NMClient *client, + NMRemoteSettings *settings) +{ + CEPage8021xSecurity *page; + + page = CE_PAGE_8021X_SECURITY (ce_page_new (CE_TYPE_PAGE_8021X_SECURITY, + connection, + client, + settings, + "/org/gnome/control-center/network/8021x-security-page.ui", + _("Security"))); + + if (nm_connection_get_setting_802_1x (connection)) + page->initial_have_8021x = TRUE; + + page->enabled = GTK_SWITCH (gtk_builder_get_object (CE_PAGE (page)->builder, "8021x_switch")); + + g_signal_connect (page, "initialized", G_CALLBACK (finish_setup), NULL); + + if (page->initial_have_8021x) + CE_PAGE (page)->security_setting = NM_SETTING_802_1X_SETTING_NAME; + + return CE_PAGE (page); +} + +static gboolean +validate (CEPage *cepage, NMConnection *connection, GError **error) +{ + CEPage8021xSecurity *page = CE_PAGE_8021X_SECURITY (cepage); + gboolean valid = TRUE; + + if (gtk_switch_get_active (page->enabled)) { + NMConnection *tmp_connection; + NMSetting *s_8021x; + + /* FIXME: get failed property and error out of wireless security objects */ + valid = wireless_security_validate (page->security, NULL); + if (valid) { + NMSetting *s_con; + + /* Here's a nice hack to work around the fact that ws_802_1x_fill_connection needs wireless setting. */ + tmp_connection = nm_connection_new (); + nm_connection_add_setting (tmp_connection, nm_setting_wireless_new ()); + + /* temp connection needs a 'connection' setting too, since most of + * the EAP methods need the UUID for CA cert ignore stuff. + */ + s_con = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + nm_connection_add_setting (tmp_connection, nm_setting_duplicate (s_con)); + + ws_802_1x_fill_connection (page->security, "wpa_eap_auth_combo", tmp_connection); + + s_8021x = nm_connection_get_setting (tmp_connection, NM_TYPE_SETTING_802_1X); + nm_connection_add_setting (connection, NM_SETTING (g_object_ref (s_8021x))); + + g_object_unref (tmp_connection); + } else + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_UNKNOWN, "Invalid 802.1x security"); + } else { + nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X); + valid = TRUE; + } + + return valid; +} + +static void +ce_page_8021x_security_init (CEPage8021xSecurity *page) +{ +} + +static void +dispose (GObject *object) +{ + CEPage8021xSecurity *page = CE_PAGE_8021X_SECURITY (object); + + if (page->security) { + wireless_security_unref (page->security); + page->security = NULL; + } + + g_clear_object (&page->group); + + G_OBJECT_CLASS (ce_page_8021x_security_parent_class)->dispose (object); +} + +static void +ce_page_8021x_security_class_init (CEPage8021xSecurityClass *security_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (security_class); + CEPageClass *parent_class = CE_PAGE_CLASS (security_class); + + /* virtual methods */ + object_class->dispose = dispose; + + parent_class->validate = validate; +} diff --git a/panels/network/connection-editor/ce-page-8021x-security.h b/panels/network/connection-editor/ce-page-8021x-security.h new file mode 100644 index 000000000..f61de9e6f --- /dev/null +++ b/panels/network/connection-editor/ce-page-8021x-security.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager Connection editor -- Connection editor for NetworkManager + * + * Dan Williams + * + * 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. + * + * (C) Copyright 2008 - 2012 Red Hat, Inc. + */ + +#ifndef __CE_PAGE_8021X_SECURITY_H +#define __CE_PAGE_8021X_SECURITY_H + +#include +#include "wireless-security.h" + +#include +#include + +#include "ce-page.h" + +#define CE_TYPE_PAGE_8021X_SECURITY (ce_page_8021x_security_get_type ()) +#define CE_PAGE_8021X_SECURITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CE_TYPE_PAGE_8021X_SECURITY, CEPage8021xSecurity)) +#define CE_PAGE_8021X_SECURITY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CE_TYPE_PAGE_8021X_SECURITY, CEPage8021xSecurityClass)) +#define CE_IS_PAGE_8021X_SECURITY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CE_TYPE_PAGE_8021X_SECURITY)) +#define CE_IS_PAGE_8021X_SECURITY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CE_TYPE_PAGE_8021X_SECURITY)) +#define CE_PAGE_8021X_SECURITY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CE_TYPE_PAGE_8021X_SECURITY, CEPage8021xSecurityClass)) + +typedef struct CEPage8021xSecurity CEPage8021xSecurity; +typedef struct CEPage8021xSecurityClass CEPage8021xSecurityClass; + +struct CEPage8021xSecurity { + CEPage parent; + + GtkSwitch *enabled; + GtkWidget *security_widget; + WirelessSecurity *security; + GtkSizeGroup *group; + gboolean initial_have_8021x; +}; + +struct CEPage8021xSecurityClass { + CEPageClass parent; +}; + +GType ce_page_8021x_security_get_type (void); + +CEPage *ce_page_8021x_security_new (NMConnection *connection, + NMClient *client, + NMRemoteSettings *settings); + +#endif /* __CE_PAGE_8021X_SECURITY_H */ diff --git a/panels/network/connection-editor/ce-page-details.c b/panels/network/connection-editor/ce-page-details.c index 0ffe3293a..5bb05d843 100644 --- a/panels/network/connection-editor/ce-page-details.c +++ b/panels/network/connection-editor/ce-page-details.c @@ -26,6 +26,7 @@ #include #include +#include #include "../panel-common.h" #include "ce-page-details.h" @@ -120,12 +121,35 @@ connect_details_page (CEPageDetails *page) NMDeviceState state; NMAccessPoint *active_ap; const gchar *str; + gboolean device_is_active; + + if (NM_IS_DEVICE_WIFI (page->device)) + active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (page->device)); + else + active_ap = NULL; state = nm_device_get_state (page->device); + device_is_active = FALSE; speed = 0; - if (page->ap == active_ap && state != NM_DEVICE_STATE_UNAVAILABLE) { - speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (page->device)) / 1000; + if (active_ap && page->ap == active_ap && state != NM_DEVICE_STATE_UNAVAILABLE) { + device_is_active = TRUE; + if (NM_IS_DEVICE_WIFI (page->device)) + speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (page->device)) / 1000; + } else { + NMActiveConnection *ac; + const gchar *p1, *p2; + + ac = nm_device_get_active_connection (page->device); + p1 = ac ? nm_active_connection_get_connection (ac) : NULL; + p2 = nm_connection_get_path (CE_PAGE (page)->connection); + if (g_strcmp0 (p1, p2) == 0) { + device_is_active = TRUE; + if (NM_IS_DEVICE_WIFI (page->device)) + speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (page->device)) / 1000; + else if (NM_IS_DEVICE_ETHERNET (page->device)) + speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (page->device)); + } } if (speed > 0) str = g_strdup_printf (_("%d Mb/s"), speed); @@ -133,11 +157,15 @@ connect_details_page (CEPageDetails *page) str = NULL; panel_set_device_widget_details (CE_PAGE (page)->builder, "speed", str); - str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (page->device)); + if (NM_IS_DEVICE_WIFI (page->device)) + str = nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (page->device)); + else if (NM_IS_DEVICE_ETHERNET (page->device)) + str = nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (page->device)); + panel_set_device_widget_details (CE_PAGE (page)->builder, "mac", str); str = NULL; - if (page->ap == active_ap) + if (device_is_active && active_ap) str = get_ap_security_string (active_ap); panel_set_device_widget_details (CE_PAGE (page)->builder, "security", str); @@ -160,12 +188,12 @@ connect_details_page (CEPageDetails *page) panel_set_device_widget_details (CE_PAGE (page)->builder, "strength", str); /* set IP entries */ - if (page->ap != active_ap) - panel_unset_device_widgets (CE_PAGE (page)->builder); - else + if (device_is_active) panel_set_device_widgets (CE_PAGE (page)->builder, page->device); + else + panel_unset_device_widgets (CE_PAGE (page)->builder); - if (page->ap != active_ap && CE_PAGE (page)->connection) + if (!device_is_active && CE_PAGE (page)->connection) update_last_used (page, CE_PAGE (page)->connection); else panel_set_device_widget_details (CE_PAGE (page)->builder, "last_used", NULL); diff --git a/panels/network/connection-editor/ce-page-ethernet.c b/panels/network/connection-editor/ce-page-ethernet.c new file mode 100644 index 000000000..9d8a90a94 --- /dev/null +++ b/panels/network/connection-editor/ce-page-ethernet.c @@ -0,0 +1,214 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2012 Red Hat, Inc + * + * Licensed under the GNU General Public License Version 2 + * + * 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. + */ + +#include "config.h" + +#include +#include + +#include +#include + +#include + +#include "ce-page-ethernet.h" + +G_DEFINE_TYPE (CEPageEthernet, ce_page_ethernet, CE_TYPE_PAGE) + +static void +all_user_changed (GtkToggleButton *b, CEPageEthernet *page) +{ + gboolean all_users; + NMSettingConnection *sc; + + sc = nm_connection_get_setting_connection (CE_PAGE (page)->connection); + all_users = gtk_toggle_button_get_active (b); + + g_object_set (sc, "permissions", NULL, NULL); + if (!all_users) + nm_setting_connection_add_permission (sc, "user", g_get_user_name (), NULL); +} + +static void +mtu_changed (GtkSpinButton *mtu, CEPageEthernet *page) +{ + if (gtk_spin_button_get_value_as_int (mtu) == 0) + gtk_widget_hide (page->mtu_label); + else + gtk_widget_show (page->mtu_label); +} + +static void +connect_ethernet_page (CEPageEthernet *page) +{ + NMSettingWired *setting = page->setting_wired; + NMSettingConnection *sc; + int mtu_def; + char **mac_list; + const GByteArray *s_mac; + char *s_mac_str; + GtkWidget *widget; + const gchar *name; + + name = nm_setting_connection_get_id (page->setting_connection); + gtk_entry_set_text (page->name, name); + + /* Device MAC address */ + mac_list = ce_page_get_mac_list (CE_PAGE (page)->client, NM_TYPE_DEVICE_ETHERNET, + NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS); + s_mac = nm_setting_wired_get_mac_address (setting); + s_mac_str = s_mac ? nm_utils_hwaddr_ntoa (s_mac->data, ARPHRD_ETHER) : NULL; + ce_page_setup_mac_combo (page->device_mac, s_mac_str, mac_list); + g_free (s_mac_str); + g_strfreev (mac_list); + g_signal_connect_swapped (page->device_mac, "changed", G_CALLBACK (ce_page_changed), page); + + /* Cloned MAC address */ + ce_page_mac_to_entry (nm_setting_wired_get_cloned_mac_address (setting), + ARPHRD_ETHER, page->cloned_mac); + g_signal_connect_swapped (page->cloned_mac, "changed", G_CALLBACK (ce_page_changed), page); + + /* MTU */ + mtu_def = ce_get_property_default (NM_SETTING (setting), NM_SETTING_WIRED_MTU); + g_signal_connect (page->mtu, "output", + G_CALLBACK (ce_spin_output_with_default), + GINT_TO_POINTER (mtu_def)); + gtk_spin_button_set_value (page->mtu, (gdouble) nm_setting_wired_get_mtu (setting)); + g_signal_connect (page->mtu, "value-changed", + G_CALLBACK (mtu_changed), page); + mtu_changed (page->mtu, page); + + g_signal_connect_swapped (page->name, "changed", G_CALLBACK (ce_page_changed), page); + g_signal_connect_swapped (page->mtu, "value-changed", G_CALLBACK (ce_page_changed), page); + + widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, + "auto_connect_check")); + sc = nm_connection_get_setting_connection (CE_PAGE (page)->connection); + g_object_bind_property (sc, "autoconnect", + widget, "active", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + widget = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, + "all_user_check")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), + nm_setting_connection_get_num_permissions (sc) == 0); + g_signal_connect (widget, "toggled", + G_CALLBACK (all_user_changed), page); +} + +static void +ui_to_setting (CEPageEthernet *page) +{ + GByteArray *device_mac = NULL; + GByteArray *cloned_mac = NULL; + GtkWidget *entry; + + entry = gtk_bin_get_child (GTK_BIN (page->device_mac)); + if (entry) + device_mac = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, NULL); + cloned_mac = ce_page_entry_to_mac (page->cloned_mac, ARPHRD_ETHER, NULL); + + g_object_set (page->setting_wired, + NM_SETTING_WIRED_MAC_ADDRESS, device_mac, + NM_SETTING_WIRED_CLONED_MAC_ADDRESS, cloned_mac, + NM_SETTING_WIRED_MTU, (guint32) gtk_spin_button_get_value_as_int (page->mtu), + NULL); + + if (device_mac) + g_byte_array_free (device_mac, TRUE); + if (cloned_mac) + g_byte_array_free (cloned_mac, TRUE); + + g_object_set (page->setting_connection, + NM_SETTING_CONNECTION_ID, gtk_entry_get_text (page->name), + NULL); +} + +static gboolean +validate (CEPage *page, + NMConnection *connection, + GError **error) +{ + CEPageEthernet *self = CE_PAGE_ETHERNET (page); + gboolean invalid = FALSE; + GByteArray *ignore; + GtkWidget *entry; + + entry = gtk_bin_get_child (GTK_BIN (self->device_mac)); + if (entry) { + ignore = ce_page_entry_to_mac (GTK_ENTRY (entry), ARPHRD_ETHER, &invalid); + if (invalid) + return FALSE; + if (ignore) + g_byte_array_free (ignore, TRUE); + } + + ignore = ce_page_entry_to_mac (self->cloned_mac, ARPHRD_ETHER, &invalid); + if (invalid) + return FALSE; + if (ignore) + g_byte_array_free (ignore, TRUE); + + ui_to_setting (self); + + return nm_setting_verify (NM_SETTING (self->setting_connection), NULL, error) && + nm_setting_verify (NM_SETTING (self->setting_wired), NULL, error); +} + +static void +ce_page_ethernet_init (CEPageEthernet *page) +{ +} + +static void +ce_page_ethernet_class_init (CEPageEthernetClass *class) +{ + CEPageClass *page_class= CE_PAGE_CLASS (class); + + page_class->validate = validate; +} + +CEPage * +ce_page_ethernet_new (NMConnection *connection, + NMClient *client, + NMRemoteSettings *settings) +{ + CEPageEthernet *page; + + page = CE_PAGE_ETHERNET (ce_page_new (CE_TYPE_PAGE_ETHERNET, + connection, + client, + settings, + "/org/gnome/control-center/network/ethernet-page.ui", + _("Identity"))); + + page->name = GTK_ENTRY (gtk_builder_get_object (CE_PAGE (page)->builder, "entry_name")); + page->device_mac = GTK_COMBO_BOX_TEXT (gtk_builder_get_object (CE_PAGE (page)->builder, "combo_mac")); + page->cloned_mac = GTK_ENTRY (gtk_builder_get_object (CE_PAGE (page)->builder, "entry_cloned_mac")); + page->mtu = GTK_SPIN_BUTTON (gtk_builder_get_object (CE_PAGE (page)->builder, "spin_mtu")); + page->mtu_label = GTK_WIDGET (gtk_builder_get_object (CE_PAGE (page)->builder, "label_mtu")); + + page->setting_connection = nm_connection_get_setting_connection (connection); + page->setting_wired = nm_connection_get_setting_wired (connection); + + connect_ethernet_page (page); + + return CE_PAGE (page); +} diff --git a/panels/network/connection-editor/ce-page-ethernet.h b/panels/network/connection-editor/ce-page-ethernet.h new file mode 100644 index 000000000..daa24a2f3 --- /dev/null +++ b/panels/network/connection-editor/ce-page-ethernet.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2012 Red Hat, Inc. + * + * Licensed under the GNU General Public License Version 2 + * + * 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 ethernet. + * + * 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 __CE_PAGE_ETHERNET_H +#define __CE_PAGE_ETHERNET_H + +#include + +#include + +#include +#include "ce-page.h" + +G_BEGIN_DECLS + +#define CE_TYPE_PAGE_ETHERNET (ce_page_ethernet_get_type ()) +#define CE_PAGE_ETHERNET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CE_TYPE_PAGE_ETHERNET, CEPageEthernet)) +#define CE_PAGE_ETHERNET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CE_TYPE_PAGE_ETHERNET, CEPageEthernetClass)) +#define CE_IS_PAGE_ETHERNET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CE_TYPE_PAGE_ETHERNET)) +#define CE_IS_PAGE_ETHERNET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CE_TYPE_PAGE_ETHERNET)) +#define CE_PAGE_ETHERNET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CE_TYPE_PAGE_ETHERNET, CEPageEthernetClass)) + +typedef struct _CEPageEthernet CEPageEthernet; +typedef struct _CEPageEthernetClass CEPageEthernetClass; + +struct _CEPageEthernet +{ + CEPage parent; + + NMSettingConnection *setting_connection; + NMSettingWired *setting_wired; + + GtkEntry *name; + GtkComboBoxText *device_mac; + GtkEntry *cloned_mac; + GtkSpinButton *mtu; + GtkWidget *mtu_label; +}; + +struct _CEPageEthernetClass +{ + CEPageClass parent_class; +}; + +GType ce_page_ethernet_get_type (void); + +CEPage *ce_page_ethernet_new (NMConnection *connection, + NMClient *client, + NMRemoteSettings *settings); + +G_END_DECLS + +#endif /* __CE_PAGE_ETHERNET_H */ + diff --git a/panels/network/connection-editor/ce-page-ip4.c b/panels/network/connection-editor/ce-page-ip4.c index 46c9d89a5..9bc1c7c7f 100644 --- a/panels/network/connection-editor/ce-page-ip4.c +++ b/panels/network/connection-editor/ce-page-ip4.c @@ -887,6 +887,10 @@ ce_page_ip4_new (NMConnection *connection, _("IPv4"))); page->setting = nm_connection_get_setting_ip4_config (connection); + if (!page->setting) { + page->setting = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ()); + nm_connection_add_setting (connection, NM_SETTING (page->setting)); + } connect_ip4_page (page); diff --git a/panels/network/connection-editor/ce-page-ip6.c b/panels/network/connection-editor/ce-page-ip6.c index fea679342..b4d760311 100644 --- a/panels/network/connection-editor/ce-page-ip6.c +++ b/panels/network/connection-editor/ce-page-ip6.c @@ -848,6 +848,10 @@ ce_page_ip6_new (NMConnection *connection, _("IPv6"))); page->setting = nm_connection_get_setting_ip6_config (connection); + if (!page->setting) { + page->setting = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ()); + nm_connection_add_setting (connection, NM_SETTING (page->setting)); + } connect_ip6_page (page); diff --git a/panels/network/connection-editor/ce-page.c b/panels/network/connection-editor/ce-page.c index 99b20e772..a82927c1a 100644 --- a/panels/network/connection-editor/ce-page.c +++ b/panels/network/connection-editor/ce-page.c @@ -28,6 +28,8 @@ #include +#include + #include "ce-page.h" @@ -224,20 +226,23 @@ ce_page_new (GType type, page->title = g_strdup (title); page->client = client; page->settings= settings; - if (!gtk_builder_add_from_resource (page->builder, ui_resource, &error)) { - g_warning ("Couldn't load builder file: %s", error->message); - g_error_free (error); - g_object_unref (page); - return NULL; - } - page->page = GTK_WIDGET (gtk_builder_get_object (page->builder, "page")); - if (!page->page) { - g_warning ("Couldn't load page widget from %s", ui_resource); - g_object_unref (page); - return NULL; - } - g_object_ref_sink (page->page); + if (ui_resource) { + if (!gtk_builder_add_from_resource (page->builder, ui_resource, &error)) { + g_warning ("Couldn't load builder file: %s", error->message); + g_error_free (error); + g_object_unref (page); + return NULL; + } + page->page = GTK_WIDGET (gtk_builder_get_object (page->builder, "page")); + if (!page->page) { + g_warning ("Couldn't load page widget from %s", ui_resource); + g_object_unref (page); + return NULL; + } + + g_object_ref_sink (page->page); + } return page; } @@ -452,3 +457,92 @@ ce_page_get_security_setting (CEPage *page) { return page->security_setting; } + +gint +ce_get_property_default (NMSetting *setting, const gchar *property_name) +{ + GParamSpec *spec; + GValue value = { 0, }; + + spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name); + g_return_val_if_fail (spec != NULL, -1); + + g_value_init (&value, spec->value_type); + g_param_value_set_default (spec, &value); + + if (G_VALUE_HOLDS_CHAR (&value)) + return (int) g_value_get_schar (&value); + else if (G_VALUE_HOLDS_INT (&value)) + return g_value_get_int (&value); + else if (G_VALUE_HOLDS_INT64 (&value)) + return (int) g_value_get_int64 (&value); + else if (G_VALUE_HOLDS_LONG (&value)) + return (int) g_value_get_long (&value); + else if (G_VALUE_HOLDS_UINT (&value)) + return (int) g_value_get_uint (&value); + else if (G_VALUE_HOLDS_UINT64 (&value)) + return (int) g_value_get_uint64 (&value); + else if (G_VALUE_HOLDS_ULONG (&value)) + return (int) g_value_get_ulong (&value); + else if (G_VALUE_HOLDS_UCHAR (&value)) + return (int) g_value_get_uchar (&value); + g_return_val_if_fail (FALSE, 0); + return 0; +} + +gint +ce_spin_output_with_default (GtkSpinButton *spin, gpointer user_data) +{ + gint defvalue = GPOINTER_TO_INT (user_data); + gint val; + gchar *buf = NULL; + + val = gtk_spin_button_get_value_as_int (spin); + if (val == defvalue) + buf = g_strdup (_("automatic")); + else + buf = g_strdup_printf ("%d", val); + + if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin)))) + gtk_entry_set_text (GTK_ENTRY (spin), buf); + + g_free (buf); + return TRUE; +} + +gchar * +ce_page_get_next_available_name (GSList *connections, const gchar *format) +{ + GSList *names = NULL, *l; + gchar *cname = NULL; + gint i = 0; + + for (l = connections; l; l = l->next) { + const gchar *id; + + id = nm_connection_get_id (NM_CONNECTION (l->data)); + g_assert (id); + names = g_slist_append (names, (gpointer) id); + } + + /* Find the next available unique connection name */ + while (!cname && (i++ < 10000)) { + gchar *temp; + gboolean found = FALSE; + + temp = g_strdup_printf (format, i); + for (l = names; l; l = l->next) { + if (!strcmp (l->data, temp)) { + found = TRUE; + break; + } + } + if (!found) + cname = temp; + else + g_free (temp); + } + g_slist_free (names); + + return cname; +} diff --git a/panels/network/connection-editor/ce-page.h b/panels/network/connection-editor/ce-page.h index 7a0838076..8e3ed8074 100644 --- a/panels/network/connection-editor/ce-page.h +++ b/panels/network/connection-editor/ce-page.h @@ -99,6 +99,14 @@ void ce_page_mac_to_entry (const GByteArray *mac, GByteArray *ce_page_entry_to_mac (GtkEntry *entry, gint type, gboolean *invalid); +gint ce_get_property_default (NMSetting *setting, + const gchar *property_name); +gint ce_spin_output_with_default (GtkSpinButton *spin, + gpointer user_data); + +gchar * ce_page_get_next_available_name (GSList *connections, const gchar *format); + + G_END_DECLS diff --git a/panels/network/connection-editor/connection-editor.gresource.xml b/panels/network/connection-editor/connection-editor.gresource.xml index a15e9bd09..74bf933e8 100644 --- a/panels/network/connection-editor/connection-editor.gresource.xml +++ b/panels/network/connection-editor/connection-editor.gresource.xml @@ -1,8 +1,10 @@ + 8021x-security-page.ui connection-editor.ui details-page.ui + ethernet-page.ui ip4-page.ui ip6-page.ui reset-page.ui diff --git a/panels/network/connection-editor/ethernet-page.ui b/panels/network/connection-editor/ethernet-page.ui new file mode 100644 index 000000000..d0810792d --- /dev/null +++ b/panels/network/connection-editor/ethernet-page.ui @@ -0,0 +1,273 @@ + + + + + 10000 + 1 + 10 + + + + + + + + + Automatic + + + Twisted Pair (TP) + + + Attachment Unit Interface (AUI) + + + BNC + + + Media Independent Interface (MII) + + + + + + + + + + + Automatic + + + 10 Mb/s + + + 100 Mb/s + + + 1 Gb/s + + + 10 Gb/s + + + + + True + False + 50 + 50 + 12 + 12 + True + True + 10 + 6 + + + True + False + 1 + _Name + True + entry_name + + + 0 + 0 + 1 + 1 + + + + + True + True + + + + 1 + 0 + 1 + 1 + + + + + True + False + 1 + _MAC Address + True + combo_mac + + + 0 + 1 + 1 + 1 + + + + + True + False + True + 0 + 1 + + + False + + + + + + 1 + 1 + 1 + 1 + + + + + True + True + True + + True + + + 1 + 2 + 1 + 1 + + + + + True + False + 1 + M_TU + True + + + 0 + 3 + 1 + 1 + + + + + True + False + center + 1 + _Cloned Address + True + + + 0 + 2 + 1 + 1 + + + + + Connect _automatically + True + True + False + end + True + True + 0 + True + + + 0 + 4 + 2 + 1 + + + + + Make available to other _users + True + True + False + True + 0 + True + + + 0 + 5 + 2 + 1 + + + + + True + False + bytes + + + 2 + 3 + 1 + 1 + + + + + True + True + + True + adjustment1 + + + 1 + 3 + 1 + 1 + + + + + + + + + + + + + + + + + True + False + + + 2 + 0 + 1 + 1 + + + + + + + + + + diff --git a/panels/network/connection-editor/net-connection-editor.c b/panels/network/connection-editor/net-connection-editor.c index 87e5a76d3..e889e3ad8 100644 --- a/panels/network/connection-editor/net-connection-editor.c +++ b/panels/network/connection-editor/net-connection-editor.c @@ -35,6 +35,8 @@ #include "ce-page-ip6.h" #include "ce-page-security.h" #include "ce-page-reset.h" +#include "ce-page-ethernet.h" +#include "ce-page-8021x-security.h" #include "egg-list-box/egg-list-box.h" @@ -88,7 +90,9 @@ update_complete (NetConnectionEditor *editor, GError *error) } static void -updated_connection_cb (NMRemoteConnection *connection, GError *error, gpointer data) +updated_connection_cb (NMRemoteConnection *connection, + GError *error, + gpointer data) { NetConnectionEditor *editor = data; @@ -97,12 +101,37 @@ updated_connection_cb (NMRemoteConnection *connection, GError *error, gpointer d update_complete (editor, error); } +static void +added_connection_cb (NMRemoteSettings *settings, + NMRemoteConnection *connection, + GError *error, + gpointer data) +{ + NetConnectionEditor *editor = data; + + if (error) { + g_warning ("Failed to add connection: %s", error->message); + /* Leave the editor open */ + return; + } + + update_complete (editor, error); +} + static void apply_edits (NetConnectionEditor *editor) { update_connection (editor); - nm_remote_connection_commit_changes (NM_REMOTE_CONNECTION (editor->orig_connection), - updated_connection_cb, editor); + + if (editor->is_new_connection) { + nm_remote_settings_add_connection (editor->settings, + editor->orig_connection, + added_connection_cb, + editor); + } else { + nm_remote_connection_commit_changes (NM_REMOTE_CONNECTION (editor->orig_connection), + updated_connection_cb, editor); + } } static void @@ -189,13 +218,21 @@ net_connection_editor_class_init (NetConnectionEditorClass *class) static void net_connection_editor_update_title (NetConnectionEditor *editor) { - NMSettingWireless *sw; - const GByteArray *ssid; gchar *id; - sw = nm_connection_get_setting_wireless (editor->connection); - ssid = nm_setting_wireless_get_ssid (sw); - id = nm_utils_ssid_to_utf8 (ssid); + if (editor->is_new_connection) + id = g_strdup (_("New Profile")); + else { + NMSettingWireless *sw; + sw = nm_connection_get_setting_wireless (editor->connection); + if (sw) { + const GByteArray *ssid; + ssid = nm_setting_wireless_get_ssid (sw); + id = nm_utils_ssid_to_utf8 (ssid); + } else { + id = g_strdup (nm_connection_get_id (editor->connection)); + } + } gtk_window_set_title (GTK_WINDOW (editor->window), id); g_free (id); } @@ -388,17 +425,42 @@ net_connection_editor_set_connection (NetConnectionEditor *editor, NMConnection *connection) { GSList *pages, *l; + NMSettingConnection *sc; + const gchar *type; + + editor->is_new_connection = !nm_remote_settings_get_connection_by_uuid (editor->settings, + nm_connection_get_uuid (connection)); + + if (editor->is_new_connection) { + GtkWidget *button; + + button = GTK_WIDGET (gtk_builder_get_object (editor->builder, "details_apply_button")); + gtk_button_set_label (GTK_BUTTON (button), _("_Add")); + } editor->connection = nm_connection_duplicate (connection); editor->orig_connection = g_object_ref (connection); net_connection_editor_update_title (editor); + sc = nm_connection_get_setting_connection (connection); + type = nm_setting_connection_get_connection_type (sc); + add_page (editor, ce_page_details_new (editor->connection, editor->client, editor->settings, editor->device, editor->ap)); - add_page (editor, ce_page_security_new (editor->connection, editor->client, editor->settings)); - add_page (editor, ce_page_wifi_new (editor->connection, editor->client, editor->settings)); + + if (strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME) == 0) + add_page (editor, ce_page_security_new (editor->connection, editor->client, editor->settings)); + else if (strcmp (type, NM_SETTING_WIRED_SETTING_NAME) == 0) + add_page (editor, ce_page_8021x_security_new (editor->connection, editor->client, editor->settings)); + + if (strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME) == 0) + add_page (editor, ce_page_wifi_new (editor->connection, editor->client, editor->settings)); + else if (strcmp (type, NM_SETTING_WIRED_SETTING_NAME) == 0) + add_page (editor, ce_page_ethernet_new (editor->connection, editor->client, editor->settings)); + add_page (editor, ce_page_ip4_new (editor->connection, editor->client, editor->settings)); add_page (editor, ce_page_ip6_new (editor->connection, editor->client, editor->settings)); + add_page (editor, ce_page_reset_new (editor->connection, editor->client, editor->settings, editor)); pages = g_slist_copy (editor->initializing_pages); diff --git a/panels/network/connection-editor/net-connection-editor.h b/panels/network/connection-editor/net-connection-editor.h index 3870beaf6..31dc486cf 100644 --- a/panels/network/connection-editor/net-connection-editor.h +++ b/panels/network/connection-editor/net-connection-editor.h @@ -52,6 +52,7 @@ struct _NetConnectionEditor NMConnection *connection; NMConnection *orig_connection; + gboolean is_new_connection; NMAccessPoint *ap; GtkBuilder *builder; diff --git a/panels/network/net-device-ethernet.c b/panels/network/net-device-ethernet.c index 3ac6faa35..cb12eb081 100644 --- a/panels/network/net-device-ethernet.c +++ b/panels/network/net-device-ethernet.c @@ -28,9 +28,14 @@ #include #include #include +#include #include "panel-common.h" +#include "egg-list-box/egg-list-box.h" +#include "connection-editor/net-connection-editor.h" +#include "connection-editor/ce-page.h" + #include "net-device-ethernet.h" G_DEFINE_TYPE (NetDeviceEthernet, net_device_ethernet, NET_TYPE_DEVICE_SIMPLE) @@ -51,15 +56,587 @@ device_ethernet_get_speed (NetDeviceSimple *device_simple) return NULL; } +static GSList * +valid_connections_for_device (NMRemoteSettings *remote_settings, + NetDevice *device) +{ + GSList *all, *filtered, *iterator, *valid; + NMConnection *connection; + NMSettingConnection *s_con; + + all = nm_remote_settings_list_connections (remote_settings); + filtered = nm_device_filter_connections (net_device_get_nm_device (device), all); + g_slist_free (all); + + valid = NULL; + for (iterator = filtered; iterator; iterator = iterator->next) { + connection = iterator->data; + s_con = nm_connection_get_setting_connection (connection); + if (!s_con) + continue; + + if (nm_setting_connection_get_master (s_con)) + continue; + + valid = g_slist_prepend (valid, connection); + } + g_slist_free (filtered); + + return g_slist_reverse (valid); +} + +static GtkWidget * +device_ethernet_add_to_notebook (NetObject *object, + GtkNotebook *notebook, + GtkSizeGroup *heading_size_group) +{ + NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object); + GtkWidget *vbox; + + vbox = GTK_WIDGET (gtk_builder_get_object (device->builder, "vbox6")); + g_object_ref (vbox); + gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (vbox)), vbox); + gtk_notebook_append_page (notebook, vbox, NULL); + g_object_unref (vbox); + return vbox; +} + +static void +add_details_row (GtkWidget *details, gint top, const gchar *heading, const gchar *value) +{ + GtkWidget *label; + + label = gtk_label_new (heading); + gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label"); + gtk_widget_set_halign (label, GTK_ALIGN_END); + gtk_widget_set_hexpand (label, TRUE); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + + gtk_grid_attach (GTK_GRID (details), label, 0, top, 1, 1); + + label = gtk_label_new (value); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_widget_set_hexpand (label, TRUE); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + + gtk_grid_attach (GTK_GRID (details), label, 1, top, 1, 1); +} + +static gchar * +get_last_used_string (NMConnection *connection) +{ + gchar *last_used = NULL; + GDateTime *now = NULL; + GDateTime *then = NULL; + gint days; + GTimeSpan diff; + guint64 timestamp; + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection (connection); + if (s_con == NULL) + goto out; + timestamp = nm_setting_connection_get_timestamp (s_con); + if (timestamp == 0) { + last_used = g_strdup (_("never")); + goto out; + } + + /* calculate the amount of time that has elapsed */ + now = g_date_time_new_now_utc (); + then = g_date_time_new_from_unix_utc (timestamp); + diff = g_date_time_difference (now, then); + days = diff / G_TIME_SPAN_DAY; + if (days == 0) + last_used = g_strdup (_("today")); + else if (days == 1) + last_used = g_strdup (_("yesterday")); + else + last_used = g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days); +out: + if (now != NULL) + g_date_time_unref (now); + if (then != NULL) + g_date_time_unref (then); + + return last_used; +} + +static void +add_details (GtkWidget *details, NMDevice *device, NMConnection *connection) +{ + NMIP4Config *ip4_config = NULL; + NMIP6Config *ip6_config = NULL; + gchar *ip4_address = NULL; + gchar *ip4_route = NULL; + gchar *ip4_dns = NULL; + gchar *ip6_address = NULL; + gint i = 0; + + ip4_config = nm_device_get_ip4_config (device); + if (ip4_config) { + ip4_address = panel_get_ip4_address_as_string (ip4_config, "address"); + ip4_route = panel_get_ip4_address_as_string (ip4_config, "gateway"); + ip4_dns = panel_get_ip4_dns_as_string (ip4_config); + } + ip6_config = nm_device_get_ip6_config (device); + if (ip6_config) { + ip6_address = panel_get_ip6_address_as_string (ip6_config); + } + + if (ip4_address && ip6_address) { + add_details_row (details, i++, _("IPv4 Address"), ip4_address); + add_details_row (details, i++, _("IPv6 Address"), ip6_address); + } else if (ip4_address) { + add_details_row (details, i++, _("IP Address"), ip4_address); + } else if (ip6_address) { + add_details_row (details, i++, _("IPv6 Address"), ip6_address); + } + + add_details_row (details, i++, _("Hardware Address"), + nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device))); + + if (ip4_route) + add_details_row (details, i++, _("Default Route"), ip4_route); + if (ip4_dns) + add_details_row (details, i++, _("DNS"), ip4_dns); + + if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) { + gchar *last_used; + last_used = get_last_used_string (connection); + add_details_row (details, i++, _("Last used"), last_used); + g_free (last_used); + } + + g_free (ip4_address); + g_free (ip4_route); + g_free (ip4_dns); + g_free (ip6_address); +} + +static void populate_ui (NetDeviceEthernet *device); + +static gboolean +device_state_to_off_switch (NMDeviceState state) +{ + switch (state) { + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + case NM_DEVICE_STATE_DEACTIVATING: + case NM_DEVICE_STATE_FAILED: + return FALSE; + default: + return TRUE; + } +} + +static void +device_ethernet_refresh_ui (NetDeviceEthernet *device) +{ + NMDevice *nm_device; + NMDeviceState state; + GtkWidget *widget; + GString *status; + gchar *speed = NULL; + + nm_device = net_device_get_nm_device (NET_DEVICE (device)); + + widget = GTK_WIDGET (gtk_builder_get_object (device->builder, "label_device")); + gtk_label_set_label (GTK_LABEL (widget), net_object_get_title (NET_OBJECT (device))); + + widget = GTK_WIDGET (gtk_builder_get_object (device->builder, "image_device")); + gtk_image_set_from_icon_name (GTK_IMAGE (widget), + panel_device_to_icon_name (nm_device), + GTK_ICON_SIZE_DIALOG); + + widget = GTK_WIDGET (gtk_builder_get_object (device->builder, "device_off_switch")); + state = nm_device_get_state (nm_device); + gtk_widget_set_visible (widget, + state != NM_DEVICE_STATE_UNAVAILABLE + && state != NM_DEVICE_STATE_UNMANAGED); + device->updating_device = TRUE; + gtk_switch_set_active (GTK_SWITCH (widget), device_state_to_off_switch (state)); + device->updating_device = FALSE; + + widget = GTK_WIDGET (gtk_builder_get_object (device->builder, "label_status")); + status = g_string_new (panel_device_state_to_localized_string (nm_device)); + if (state != NM_DEVICE_STATE_UNAVAILABLE) + speed = net_device_simple_get_speed (NET_DEVICE_SIMPLE (device)); + if (speed) + g_string_append_printf (status, " - %s", speed); + gtk_label_set_label (GTK_LABEL (widget), status->str); + g_string_free (status, TRUE); + gtk_widget_set_tooltip_text (widget, + panel_device_state_reason_to_localized_string (nm_device)); + + populate_ui (device); +} + +static void +editor_done (NetConnectionEditor *editor, + gboolean success, + NetDeviceEthernet *device) +{ + g_object_unref (editor); + device_ethernet_refresh_ui (device); +} + +static void +show_details_for_row (GtkButton *button, NetDeviceEthernet *device) +{ + GtkWidget *row; + NMConnection *connection; + GtkWidget *window; + NetConnectionEditor *editor; + NMClient *client; + NMRemoteSettings *settings; + NMDevice *nmdev; + + window = gtk_widget_get_toplevel (GTK_WIDGET (button)); + + row = GTK_WIDGET (g_object_get_data (G_OBJECT (button), "row")); + connection = NM_CONNECTION (g_object_get_data (G_OBJECT (row), "connection")); + + nmdev = net_device_get_nm_device (NET_DEVICE (device)); + client = net_object_get_client (NET_OBJECT (device)); + settings = net_object_get_remote_settings (NET_OBJECT (device)); + editor = net_connection_editor_new (GTK_WINDOW (window), connection, nmdev, NULL, client, settings); + g_signal_connect (editor, "done", G_CALLBACK (editor_done), device); + net_connection_editor_run (editor); +} + +static void +add_row (NetDeviceEthernet *device, NMConnection *connection) +{ + GtkWidget *row; + GtkWidget *widget; + GtkWidget *box; + GtkWidget *details; + NMDevice *nmdev; + NMActiveConnection *aconn; + gboolean active; + GtkWidget *image; + + active = FALSE; + + nmdev = net_device_get_nm_device (NET_DEVICE (device)); + aconn = nm_device_get_active_connection (nmdev); + if (aconn) { + const gchar *path1, *path2; + path1 = nm_active_connection_get_connection (aconn); + path2 = nm_connection_get_path (connection); + active = g_strcmp0 (path1, path2) == 0; + } + + row = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start (GTK_BOX (row), box, FALSE, TRUE, 0); + widget = gtk_label_new (nm_connection_get_id (connection)); + gtk_widget_set_margin_left (widget, 12); + gtk_widget_set_margin_right (widget, 12); + gtk_widget_set_margin_top (widget, 12); + gtk_widget_set_margin_bottom (widget, 12); + gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0); + + if (active) { + widget = gtk_image_new_from_icon_name ("object-select-symbolic", GTK_ICON_SIZE_MENU); + gtk_widget_set_halign (widget, GTK_ALIGN_CENTER); + gtk_widget_set_valign (widget, GTK_ALIGN_CENTER); + gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0); + + details = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (details), 10); + gtk_grid_set_column_spacing (GTK_GRID (details), 10); + + gtk_box_pack_start (GTK_BOX (row), details, FALSE, TRUE, 0); + + add_details (details, nmdev, connection); + } + + /* filler */ + widget = gtk_label_new (""); + gtk_widget_set_hexpand (widget, TRUE); + gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0); + + image = gtk_image_new_from_icon_name ("emblem-system-symbolic", GTK_ICON_SIZE_MENU); + gtk_widget_show (image); + widget = gtk_button_new (); + gtk_widget_set_margin_left (widget, 12); + gtk_widget_set_margin_right (widget, 12); + gtk_widget_set_margin_top (widget, 12); + gtk_widget_set_margin_bottom (widget, 12); + gtk_widget_show (widget); + gtk_container_add (GTK_CONTAINER (widget), image); + gtk_widget_set_halign (widget, GTK_ALIGN_CENTER); + gtk_widget_set_valign (widget, GTK_ALIGN_CENTER); + gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0); + g_object_set_data (G_OBJECT (row), "edit", widget); + g_object_set_data (G_OBJECT (widget), "row", row); + g_signal_connect (widget, "clicked", + G_CALLBACK (show_details_for_row), device); + + gtk_widget_show_all (row); + + g_object_set_data (G_OBJECT (row), "connection", connection); + + gtk_container_add (GTK_CONTAINER (device->list), row); +} + +static void +connection_removed (NMRemoteConnection *connection, + NetDeviceEthernet *device) +{ + device_ethernet_refresh_ui (device); +} + +static void +populate_ui (NetDeviceEthernet *device) +{ + NMRemoteSettings *settings; + GList *children, *c; + GSList *connections, *l; + NMConnection *connection; + gint n_connections; + + children = gtk_container_get_children (GTK_CONTAINER (device->list)); + for (c = children; c; c = c->next) { + gtk_container_remove (GTK_CONTAINER (device->list), c->data); + } + g_list_free (children); + + children = gtk_container_get_children (GTK_CONTAINER (device->details)); + for (c = children; c; c = c->next) { + gtk_container_remove (GTK_CONTAINER (device->details), c->data); + } + g_list_free (children); + + settings = net_object_get_remote_settings (NET_OBJECT (device)); + connections = valid_connections_for_device (settings, NET_DEVICE (device)); + + + for (l = connections; l; l = l->next) { + NMConnection *connection = l->data; + if (!g_object_get_data (G_OBJECT (connection), "removed_signal_handler")) { + g_signal_connect (connection, "removed", + G_CALLBACK (connection_removed), device); + g_object_set_data (G_OBJECT (connection), "removed_signal_handler", GINT_TO_POINTER (TRUE)); + } + } + n_connections = g_slist_length (connections); + + if (n_connections > 4) { + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (device->scrolled_window), + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + gtk_widget_set_vexpand (device->scrolled_window, TRUE); + } else { + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (device->scrolled_window), + GTK_POLICY_NEVER, + GTK_POLICY_NEVER); + gtk_widget_set_vexpand (device->scrolled_window, FALSE); + } + + if (n_connections > 1) { + gtk_widget_hide (device->details); + gtk_widget_hide (device->details_button); + for (l = connections; l; l = l->next) { + NMConnection *connection = l->data; + add_row (device, connection); + } + gtk_widget_show (device->scrolled_window); + } else if (n_connections == 1) { + connection = connections->data; + gtk_widget_hide (device->scrolled_window); + add_details (device->details, net_device_get_nm_device (NET_DEVICE (device)), connection); + gtk_widget_show_all (device->details); + gtk_widget_show (device->details_button); + g_object_set_data (G_OBJECT (device->details_button), "row", device->details_button); + g_object_set_data (G_OBJECT (device->details_button), "connection", connection); + + } else { + gtk_widget_hide (device->scrolled_window); + gtk_widget_hide (device->details); + gtk_widget_hide (device->details_button); + } +} + +static void +remote_settings_read_cb (NMRemoteSettings *settings, + NetDeviceEthernet *device) +{ + device_ethernet_refresh_ui (device); +} + +static void +update_separator (GtkWidget **separator, + GtkWidget *child, + GtkWidget *before, + gpointer user_data) +{ + if (before == NULL) + return; + + if (*separator == NULL) + { + *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); + gtk_widget_show (*separator); + g_object_ref_sink (*separator); + } +} + +static void +add_profile (GtkButton *button, NetDeviceEthernet *device) +{ + NMRemoteSettings *settings; + NMConnection *connection; + NMSettingConnection *sc; + gchar *uuid, *id; + NetConnectionEditor *editor; + GtkWidget *window; + NMClient *client; + NMDevice *nmdev; + GSList *connections; + + connection = nm_connection_new (); + sc = NM_SETTING_CONNECTION (nm_setting_connection_new ()); + nm_connection_add_setting (connection, NM_SETTING (sc)); + + uuid = nm_utils_uuid_generate (); + + settings = net_object_get_remote_settings (NET_OBJECT (device)); + connections = nm_remote_settings_list_connections (settings); + id = ce_page_get_next_available_name (connections, _("Profile %d")); + g_slist_free (connections); + + g_object_set (sc, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NULL); + + nm_connection_add_setting (connection, nm_setting_wired_new ()); + + g_free (uuid); + g_free (id); + + window = gtk_widget_get_toplevel (GTK_WIDGET (button)); + + nmdev = net_device_get_nm_device (NET_DEVICE (device)); + client = net_object_get_client (NET_OBJECT (device)); + editor = net_connection_editor_new (GTK_WINDOW (window), connection, nmdev, NULL, client, settings); + g_signal_connect (editor, "done", G_CALLBACK (editor_done), device); + net_connection_editor_run (editor); +} + +static void +device_off_toggled (GtkSwitch *sw, + GParamSpec *pspec, + NetDeviceEthernet *device) +{ + NMClient *client; + NMDevice *nm_device; + NMConnection *connection; + + if (device->updating_device) + return; + + client = net_object_get_client (NET_OBJECT (device)); + nm_device = net_device_get_nm_device (NET_DEVICE (device)); + + if (gtk_switch_get_active (sw)) { + connection = net_device_get_find_connection (NET_DEVICE (device)); + if (connection != NULL) { + nm_client_activate_connection (client, + connection, + nm_device, + NULL, NULL, NULL); + } + } else { + nm_device_disconnect (nm_device, NULL, NULL); + } +} + +static void +device_ethernet_constructed (GObject *object) +{ + NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object); + NMRemoteSettings *settings; + GtkWidget *list; + GtkWidget *swin; + GtkWidget *widget; + + widget = GTK_WIDGET (gtk_builder_get_object (device->builder, + "device_off_switch")); + g_signal_connect (widget, "notify::active", + G_CALLBACK (device_off_toggled), device); + + device->scrolled_window = swin = GTK_WIDGET (gtk_builder_get_object (device->builder, "list")); + device->list = list = GTK_WIDGET (egg_list_box_new ()); + egg_list_box_set_selection_mode (EGG_LIST_BOX (list), GTK_SELECTION_NONE); + egg_list_box_set_separator_funcs (EGG_LIST_BOX (list), update_separator, NULL, NULL); + egg_list_box_add_to_scrolled (EGG_LIST_BOX (list), GTK_SCROLLED_WINDOW (swin)); + gtk_widget_show (list); + + device->details = GTK_WIDGET (gtk_builder_get_object (NET_DEVICE_ETHERNET (object)->builder, "details")); + + device->details_button = GTK_WIDGET (gtk_builder_get_object (NET_DEVICE_ETHERNET (object)->builder, "details_button")); + g_signal_connect (device->details_button, "clicked", + G_CALLBACK (show_details_for_row), device); + + device->add_profile_button = GTK_WIDGET (gtk_builder_get_object (NET_DEVICE_ETHERNET (object)->builder, "add_profile_button")); + g_signal_connect (device->add_profile_button, "clicked", + G_CALLBACK (add_profile), device); + + settings = net_object_get_remote_settings (NET_OBJECT (object)); + g_signal_connect (settings, "connections-read", + G_CALLBACK (remote_settings_read_cb), object); +} + +static void +device_ethernet_finalize (GObject *object) +{ + NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object); + + g_object_unref (device->builder); + + G_OBJECT_CLASS (net_device_ethernet_parent_class)->finalize (object); +} + +static void +device_ethernet_refresh (NetObject *object) +{ + NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object); + device_ethernet_refresh_ui (device); +} + static void net_device_ethernet_class_init (NetDeviceEthernetClass *klass) { NetDeviceSimpleClass *simple_class = NET_DEVICE_SIMPLE_CLASS (klass); + NetObjectClass *obj_class = NET_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); simple_class->get_speed = device_ethernet_get_speed; + obj_class->refresh = device_ethernet_refresh; + obj_class->add_to_notebook = device_ethernet_add_to_notebook; + object_class->constructed = device_ethernet_constructed; + object_class->finalize = device_ethernet_finalize; } static void -net_device_ethernet_init (NetDeviceEthernet *device_ethernet) +net_device_ethernet_init (NetDeviceEthernet *device) { + GError *error = NULL; + + device->builder = gtk_builder_new (); + gtk_builder_add_from_resource (device->builder, + "/org/gnome/control-center/network/network-ethernet.ui", + &error); + if (error != NULL) { + g_warning ("Could not load interface file: %s", error->message); + g_error_free (error); + return; + } } diff --git a/panels/network/net-device-ethernet.h b/panels/network/net-device-ethernet.h index 5c22937b6..84d0e4374 100644 --- a/panels/network/net-device-ethernet.h +++ b/panels/network/net-device-ethernet.h @@ -41,16 +41,24 @@ typedef struct _NetDeviceEthernetClass NetDeviceEthernetClass; struct _NetDeviceEthernet { - NetDeviceSimple parent; - NetDeviceEthernetPrivate *priv; + NetDeviceSimple parent; + + GtkBuilder *builder; + + GtkWidget *list; + GtkWidget *scrolled_window; + GtkWidget *details; + GtkWidget *details_button; + GtkWidget *add_profile_button; + gboolean updating_device; }; struct _NetDeviceEthernetClass { - NetDeviceSimpleClass parent_class; + NetDeviceSimpleClass parent_class; }; -GType net_device_ethernet_get_type (void); +GType net_device_ethernet_get_type (void); G_END_DECLS diff --git a/panels/network/network-ethernet.ui b/panels/network/network-ethernet.ui new file mode 100644 index 000000000..58abe6552 --- /dev/null +++ b/panels/network/network-ethernet.ui @@ -0,0 +1,216 @@ + + + + + True + False + emblem-system-symbolic + + + False + + + True + False + 12 + + + True + False + vertical + 6 + + + True + False + end + start + 1 + 48 + network-wired + 6 + + + 0 + 0 + 1 + 1 + + + + + True + False + start + center + True + + + True + False + 0 + Wired + end + + + + + + + False + False + 0 + + + + + True + False + 0 + Cable unplugged + + + False + False + 1 + + + + + 1 + 0 + 1 + 1 + + + + + True + True + 12 + True + never + in + + + + + + 0 + 1 + 3 + 1 + + + + + True + False + 12 + True + True + 10 + 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 2 + 3 + 1 + + + + + True + True + end + center + True + + + 2 + 0 + 1 + 1 + + + + + True + True + 0 + + + + + True + False + 18 + + + _Add Profile… + True + True + True + start + True + + + True + True + 0 + + + + + True + True + True + end + image1 + + + True + True + 1 + + + + + False + True + 1 + + + + + + + diff --git a/panels/network/network-simple.ui b/panels/network/network-simple.ui index a5ceb47a9..c69a3e994 100644 --- a/panels/network/network-simple.ui +++ b/panels/network/network-simple.ui @@ -10,7 +10,7 @@ 12 6 - + True False start @@ -81,174 +81,6 @@ 1 - - - True - False - 1 - Hardware Address - label_mac - - - - 0 - 1 - 1 - 1 - - - - - True - False - 1 - IPv4 Address - label_ipv4 - - - - 0 - 3 - 1 - 1 - - - - - True - False - 1 - IPv6 Address - label_ipv6 - - - - 0 - 4 - 1 - 1 - - - - - True - False - 1 - Default Route - label_route - - - - 0 - 5 - 1 - 1 - - - - - True - False - 1 - 0 - DNS - label_dns - - - - 0 - 6 - 1 - 1 - - - - - True - True - 0 - AA:BB:CC:DD:55:66:77:88 - True - - - 1 - 1 - 2 - 1 - - - - - True - True - 0 - 127.0.0.1 - True - - - 1 - 3 - 2 - 1 - - - - - True - True - 0 - ::1 - True - - - 1 - 4 - 2 - 1 - - - - - True - True - 0 - 127.0.0.1 - True - - - 1 - 5 - 2 - 1 - - - - - True - True - 0 - 0 - 127.0.0.1 - True - True - - - 1 - 6 - 2 - 1 - - True @@ -272,13 +104,189 @@ - - - - - - - + + True + False + 20 + vertical + 10 + 6 + True + + + True + False + 1 + Hardware Address + label_mac + + + + 0 + 0 + 1 + 1 + + + + + True + False + 1 + IPv4 Address + label_ipv4 + + + + 0 + 1 + 1 + 1 + + + + + True + False + 1 + IPv6 Address + label_ipv6 + + + + 0 + 2 + 1 + 1 + + + + + True + False + 1 + Default Route + label_route + + + + 0 + 3 + 1 + 1 + + + + + True + False + 1 + 0 + DNS + label_dns + + + + 0 + 4 + 1 + 1 + + + + + True + True + 0 + AA:BB:CC:DD:55:66:77:88 + True + + + 1 + 0 + 1 + 1 + + + + + True + True + 0 + 127.0.0.1 + True + + + 1 + 1 + 1 + 1 + + + + + True + True + 0 + ::1 + True + + + 1 + 2 + 1 + 1 + + + + + True + True + 0 + 127.0.0.1 + True + + + 1 + 3 + 1 + 1 + + + + + True + True + 0 + 0 + 127.0.0.1 + True + True + + + 1 + 4 + 1 + 1 + + + + + 0 + 1 + 3 + 1 + @@ -321,13 +329,5 @@ - - - - - - - - - + diff --git a/panels/network/network.gresource.xml b/panels/network/network.gresource.xml index b0b8f1ce3..9dbb815fb 100644 --- a/panels/network/network.gresource.xml +++ b/panels/network/network.gresource.xml @@ -7,5 +7,6 @@ network-wifi.ui network-simple.ui network-mobile.ui + network-ethernet.ui diff --git a/panels/network/panel-common.c b/panels/network/panel-common.c index fe7baf4eb..8fd2fc894 100644 --- a/panels/network/panel-common.c +++ b/panels/network/panel-common.c @@ -488,8 +488,8 @@ panel_set_device_widget_header (GtkBuilder *builder, return TRUE; } -static gchar * -get_ipv4_config_address_as_string (NMIP4Config *ip4_config, const char *what) +gchar * +panel_get_ip4_address_as_string (NMIP4Config *ip4_config, const char *what) { const GSList *list; struct in_addr addr; @@ -522,8 +522,8 @@ out: return str; } -static gchar * -get_ipv4_config_name_servers_as_string (NMIP4Config *ip4_config) +gchar * +panel_get_ip4_dns_as_string (NMIP4Config *ip4_config) { const GArray *array; GString *dns; @@ -547,8 +547,8 @@ out: return str; } -static gchar * -get_ipv6_config_address_as_string (NMIP6Config *ip6_config) +gchar * +panel_get_ip6_address_as_string (NMIP6Config *ip6_config) { const GSList *list; const struct in6_addr *addr; @@ -586,7 +586,7 @@ panel_set_device_widgets (GtkBuilder *builder, NMDevice *device) if (ip4_config != NULL) { /* IPv4 address */ - str_tmp = get_ipv4_config_address_as_string (ip4_config, "address"); + str_tmp = panel_get_ip4_address_as_string (ip4_config, "address"); panel_set_device_widget_details (builder, "ipv4", str_tmp); @@ -594,14 +594,14 @@ panel_set_device_widgets (GtkBuilder *builder, NMDevice *device) g_free (str_tmp); /* IPv4 DNS */ - str_tmp = get_ipv4_config_name_servers_as_string (ip4_config); + str_tmp = panel_get_ip4_dns_as_string (ip4_config); panel_set_device_widget_details (builder, "dns", str_tmp); g_free (str_tmp); /* IPv4 route */ - str_tmp = get_ipv4_config_address_as_string (ip4_config, "gateway"); + str_tmp = panel_get_ip4_address_as_string (ip4_config, "gateway"); panel_set_device_widget_details (builder, "route", str_tmp); @@ -628,7 +628,7 @@ panel_set_device_widgets (GtkBuilder *builder, NMDevice *device) /* get IPv6 parameters */ ip6_config = nm_device_get_ip6_config (device); if (ip6_config != NULL) { - str_tmp = get_ipv6_config_address_as_string (ip6_config); + str_tmp = panel_get_ip6_address_as_string (ip6_config); panel_set_device_widget_details (builder, "ipv6", str_tmp); has_ip6 = str_tmp != NULL; g_free (str_tmp); diff --git a/panels/network/panel-common.h b/panels/network/panel-common.h index c55d46b3a..9288e4fbe 100644 --- a/panels/network/panel-common.h +++ b/panels/network/panel-common.h @@ -45,6 +45,9 @@ gboolean panel_set_device_widget_header (GtkBuilder *buil void panel_set_device_widgets (GtkBuilder *builder, NMDevice *device); void panel_unset_device_widgets (GtkBuilder *builder); +gchar *panel_get_ip4_address_as_string (NMIP4Config *config, const gchar *what); +gchar *panel_get_ip4_dns_as_string (NMIP4Config *config); +gchar *panel_get_ip6_address_as_string (NMIP6Config *config); G_END_DECLS