diff options
Diffstat (limited to 'panels/network/net-device-ethernet.c')
-rw-r--r-- | panels/network/net-device-ethernet.c | 451 |
1 files changed, 450 insertions, 1 deletions
diff --git a/panels/network/net-device-ethernet.c b/panels/network/net-device-ethernet.c index 3ac6faa35..f3ef7744d 100644 --- a/panels/network/net-device-ethernet.c +++ b/panels/network/net-device-ethernet.c @@ -28,9 +28,14 @@ #include <nm-device.h> #include <nm-device-ethernet.h> #include <nm-remote-connection.h> +#include <nm-utils.h> #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,459 @@ 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++, _("IP4 Address"), ip4_address); + add_details_row (details, i++, _("IP6 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++, _("IP 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 void +editor_done (NetConnectionEditor *editor, + gboolean success, + NetDeviceEthernet *device) +{ + g_object_unref (editor); + populate_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 +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)); + + n_connections = g_slist_length (connections); + 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) +{ + populate_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_ethernet_constructed (GObject *object) +{ + NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object); + NMRemoteSettings *settings; + GtkWidget *list; + GtkWidget *swin; + + device->scrolled_window = swin = GTK_WIDGET (gtk_builder_get_object (NET_DEVICE_ETHERNET (object)->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 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->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_file (device->builder, + GNOMECC_UI_DIR "/network-ethernet.ui", + &error); + if (error != NULL) { + g_warning ("Could not load interface file: %s", error->message); + g_error_free (error); + return; + } } |