1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
5
* Licensed under the GNU General Public License Version 2
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
#include <glib-object.h>
25
#include <glib/gi18n.h>
27
#include <NetworkManager.h>
29
#include "panel-common.h"
31
#include "shell/list-box-helper.h"
32
#include "connection-editor/net-connection-editor.h"
33
#include "connection-editor/ce-page.h"
35
#include "net-device-ethernet.h"
37
G_DEFINE_TYPE (NetDeviceEthernet, net_device_ethernet, NET_TYPE_DEVICE_SIMPLE)
40
device_ethernet_get_speed (NetDeviceSimple *device_simple)
45
nm_device = net_device_get_nm_device (NET_DEVICE (device_simple));
47
speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (nm_device));
49
/* Translators: network device speed */
50
return g_strdup_printf (_("%d Mb/s"), speed);
56
device_ethernet_add_to_notebook (NetObject *object,
57
GtkNotebook *notebook,
58
GtkSizeGroup *heading_size_group)
60
NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
63
vbox = GTK_WIDGET (gtk_builder_get_object (device->builder, "vbox6"));
64
gtk_notebook_append_page (notebook, vbox, NULL);
69
add_details_row (GtkWidget *details, gint top, const gchar *heading, const gchar *value)
71
GtkWidget *heading_label;
72
GtkWidget *value_label;
74
heading_label = gtk_label_new (heading);
75
gtk_style_context_add_class (gtk_widget_get_style_context (heading_label), "dim-label");
76
gtk_widget_set_halign (heading_label, GTK_ALIGN_END);
77
gtk_widget_set_hexpand (heading_label, TRUE);
79
gtk_grid_attach (GTK_GRID (details), heading_label, 0, top, 1, 1);
81
value_label = gtk_label_new (value);
82
gtk_widget_set_halign (value_label, GTK_ALIGN_START);
83
gtk_widget_set_hexpand (value_label, TRUE);
85
gtk_label_set_mnemonic_widget (GTK_LABEL (heading_label), value_label);
87
gtk_grid_attach (GTK_GRID (details), value_label, 1, top, 1, 1);
91
get_last_used_string (NMConnection *connection)
93
gchar *last_used = NULL;
94
GDateTime *now = NULL;
95
GDateTime *then = NULL;
99
NMSettingConnection *s_con;
101
s_con = nm_connection_get_setting_connection (connection);
104
timestamp = nm_setting_connection_get_timestamp (s_con);
105
if (timestamp == 0) {
106
last_used = g_strdup (_("never"));
110
/* calculate the amount of time that has elapsed */
111
now = g_date_time_new_now_utc ();
112
then = g_date_time_new_from_unix_utc (timestamp);
113
diff = g_date_time_difference (now, then);
114
days = diff / G_TIME_SPAN_DAY;
116
last_used = g_strdup (_("today"));
118
last_used = g_strdup (_("yesterday"));
120
last_used = g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days);
123
g_date_time_unref (now);
125
g_date_time_unref (then);
131
add_details (GtkWidget *details, NMDevice *device, NMConnection *connection)
133
NMIPConfig *ip4_config = NULL;
134
NMIPConfig *ip6_config = NULL;
135
gchar *ip4_address = NULL;
136
gchar *ip4_route = NULL;
137
gchar *ip4_dns = NULL;
138
gchar *ip6_address = NULL;
141
ip4_config = nm_device_get_ip4_config (device);
143
ip4_address = panel_get_ip4_address_as_string (ip4_config, "address");
144
ip4_route = panel_get_ip4_address_as_string (ip4_config, "gateway");
145
ip4_dns = panel_get_ip4_dns_as_string (ip4_config);
147
ip6_config = nm_device_get_ip6_config (device);
149
ip6_address = panel_get_ip6_address_as_string (ip6_config);
152
if (ip4_address && ip6_address) {
153
add_details_row (details, i++, _("IPv4 Address"), ip4_address);
154
add_details_row (details, i++, _("IPv6 Address"), ip6_address);
155
} else if (ip4_address) {
156
add_details_row (details, i++, _("IP Address"), ip4_address);
157
} else if (ip6_address) {
158
add_details_row (details, i++, _("IPv6 Address"), ip6_address);
161
add_details_row (details, i++, _("Hardware Address"),
162
nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device)));
165
add_details_row (details, i++, _("Default Route"), ip4_route);
167
add_details_row (details, i++, _("DNS"), ip4_dns);
169
if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) {
171
last_used = get_last_used_string (connection);
172
add_details_row (details, i++, _("Last used"), last_used);
176
g_free (ip4_address);
179
g_free (ip6_address);
182
static void populate_ui (NetDeviceEthernet *device);
185
device_state_to_off_switch (NMDeviceState state)
188
case NM_DEVICE_STATE_UNMANAGED:
189
case NM_DEVICE_STATE_UNAVAILABLE:
190
case NM_DEVICE_STATE_DISCONNECTED:
191
case NM_DEVICE_STATE_DEACTIVATING:
192
case NM_DEVICE_STATE_FAILED:
200
device_ethernet_refresh_ui (NetDeviceEthernet *device)
207
nm_device = net_device_get_nm_device (NET_DEVICE (device));
209
widget = GTK_WIDGET (gtk_builder_get_object (device->builder, "label_device"));
210
gtk_label_set_label (GTK_LABEL (widget), net_object_get_title (NET_OBJECT (device)));
212
widget = GTK_WIDGET (gtk_builder_get_object (device->builder, "image_device"));
213
gtk_image_set_from_icon_name (GTK_IMAGE (widget),
214
panel_device_to_icon_name (nm_device, FALSE),
215
GTK_ICON_SIZE_DIALOG);
217
widget = GTK_WIDGET (gtk_builder_get_object (device->builder, "device_off_switch"));
218
state = nm_device_get_state (nm_device);
219
gtk_widget_set_visible (widget,
220
state != NM_DEVICE_STATE_UNAVAILABLE
221
&& state != NM_DEVICE_STATE_UNMANAGED);
222
device->updating_device = TRUE;
223
gtk_switch_set_active (GTK_SWITCH (widget), device_state_to_off_switch (state));
224
device->updating_device = FALSE;
226
if (state != NM_DEVICE_STATE_UNAVAILABLE)
227
speed = net_device_simple_get_speed (NET_DEVICE_SIMPLE (device));
228
panel_set_device_status (device->builder, "label_status", nm_device, speed);
230
populate_ui (device);
234
editor_done (NetConnectionEditor *editor,
236
NetDeviceEthernet *device)
238
g_object_unref (editor);
239
device_ethernet_refresh_ui (device);
243
show_details (GtkButton *button, NetDeviceEthernet *device, const gchar *title)
246
NMConnection *connection;
248
NetConnectionEditor *editor;
252
window = gtk_widget_get_toplevel (GTK_WIDGET (button));
254
row = GTK_WIDGET (g_object_get_data (G_OBJECT (button), "row"));
255
connection = NM_CONNECTION (g_object_get_data (G_OBJECT (row), "connection"));
257
nmdev = net_device_get_nm_device (NET_DEVICE (device));
258
client = net_object_get_client (NET_OBJECT (device));
259
editor = net_connection_editor_new (GTK_WINDOW (window), connection, nmdev, NULL, client);
261
net_connection_editor_set_title (editor, title);
262
g_signal_connect (editor, "done", G_CALLBACK (editor_done), device);
263
net_connection_editor_run (editor);
267
show_details_for_row (GtkButton *button, NetDeviceEthernet *device)
269
show_details (button, device, NULL);
273
show_details_for_wired (GtkButton *button, NetDeviceEthernet *device)
275
/* Translators: This is used as the title of the connection
276
* details window for ethernet, if there is only a single
277
* profile. It is also used to display ethernet in the
280
show_details (button, device, _("Wired"));
284
add_row (NetDeviceEthernet *device, NMConnection *connection)
291
NMActiveConnection *aconn;
297
nmdev = net_device_get_nm_device (NET_DEVICE (device));
298
aconn = nm_device_get_active_connection (nmdev);
300
const gchar *uuid1, *uuid2;
301
uuid1 = nm_active_connection_get_uuid (aconn);
302
uuid2 = nm_connection_get_uuid (connection);
303
active = g_strcmp0 (uuid1, uuid2) == 0;
306
row = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
307
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
308
gtk_box_pack_start (GTK_BOX (row), box, FALSE, TRUE, 0);
309
widget = gtk_label_new (nm_connection_get_id (connection));
310
gtk_widget_set_margin_start (widget, 12);
311
gtk_widget_set_margin_end (widget, 12);
312
gtk_widget_set_margin_top (widget, 12);
313
gtk_widget_set_margin_bottom (widget, 12);
314
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
317
widget = gtk_image_new_from_icon_name ("object-select-symbolic", GTK_ICON_SIZE_MENU);
318
gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
319
gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
320
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
322
details = gtk_grid_new ();
323
gtk_grid_set_row_spacing (GTK_GRID (details), 10);
324
gtk_grid_set_column_spacing (GTK_GRID (details), 10);
326
gtk_box_pack_start (GTK_BOX (row), details, FALSE, TRUE, 0);
328
add_details (details, nmdev, connection);
332
widget = gtk_label_new ("");
333
gtk_widget_set_hexpand (widget, TRUE);
334
gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0);
336
image = gtk_image_new_from_icon_name ("emblem-system-symbolic", GTK_ICON_SIZE_MENU);
337
gtk_widget_show (image);
338
widget = gtk_button_new ();
339
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "image-button");
340
gtk_widget_set_margin_start (widget, 12);
341
gtk_widget_set_margin_end (widget, 12);
342
gtk_widget_set_margin_top (widget, 12);
343
gtk_widget_set_margin_bottom (widget, 12);
344
gtk_widget_show (widget);
345
gtk_container_add (GTK_CONTAINER (widget), image);
346
gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
347
gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
348
atk_object_set_name (gtk_widget_get_accessible (widget), _("Options…"));
349
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
350
g_object_set_data (G_OBJECT (row), "edit", widget);
351
g_object_set_data (G_OBJECT (widget), "row", row);
352
g_signal_connect (widget, "clicked",
353
G_CALLBACK (show_details_for_row), device);
355
gtk_widget_show_all (row);
357
g_object_set_data (G_OBJECT (row), "connection", connection);
359
gtk_container_add (GTK_CONTAINER (device->list), row);
363
connection_removed (NMClient *client,
364
NMRemoteConnection *connection,
365
NetDeviceEthernet *device)
367
if (g_hash_table_remove (device->connections, connection))
368
device_ethernet_refresh_ui (device);
372
populate_ui (NetDeviceEthernet *device)
375
GSList *connections, *l;
376
NMConnection *connection;
379
children = gtk_container_get_children (GTK_CONTAINER (device->list));
380
for (c = children; c; c = c->next) {
381
gtk_container_remove (GTK_CONTAINER (device->list), c->data);
383
g_list_free (children);
385
children = gtk_container_get_children (GTK_CONTAINER (device->details));
386
for (c = children; c; c = c->next) {
387
gtk_container_remove (GTK_CONTAINER (device->details), c->data);
389
g_list_free (children);
391
connections = net_device_get_valid_connections (NET_DEVICE (device));
392
for (l = connections; l; l = l->next) {
393
NMConnection *connection = l->data;
394
if (!g_hash_table_contains (device->connections, connection)) {
395
g_hash_table_add (device->connections, connection);
398
n_connections = g_slist_length (connections);
400
if (n_connections > 4) {
401
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (device->scrolled_window),
403
GTK_POLICY_AUTOMATIC);
404
gtk_widget_set_vexpand (device->scrolled_window, TRUE);
406
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (device->scrolled_window),
409
gtk_widget_set_vexpand (device->scrolled_window, FALSE);
412
if (n_connections > 1) {
413
gtk_widget_hide (device->details);
414
gtk_widget_hide (device->details_button);
415
for (l = connections; l; l = l->next) {
416
NMConnection *connection = l->data;
417
add_row (device, connection);
419
gtk_widget_show (device->scrolled_window);
420
} else if (n_connections == 1) {
421
connection = connections->data;
422
gtk_widget_hide (device->scrolled_window);
423
add_details (device->details, net_device_get_nm_device (NET_DEVICE (device)), connection);
424
gtk_widget_show_all (device->details);
425
gtk_widget_show (device->details_button);
426
g_object_set_data (G_OBJECT (device->details_button), "row", device->details_button);
427
g_object_set_data (G_OBJECT (device->details_button), "connection", connection);
430
gtk_widget_hide (device->scrolled_window);
431
gtk_widget_hide (device->details);
432
gtk_widget_hide (device->details_button);
435
g_slist_free (connections);
439
client_connection_added_cb (NMClient *client,
440
NMRemoteConnection *connection,
441
NetDeviceEthernet *device)
443
device_ethernet_refresh_ui (device);
447
add_profile (GtkButton *button, NetDeviceEthernet *device)
449
NMConnection *connection;
450
NMSettingConnection *sc;
452
NetConnectionEditor *editor;
456
const GPtrArray *connections;
458
connection = nm_simple_connection_new ();
459
sc = NM_SETTING_CONNECTION (nm_setting_connection_new ());
460
nm_connection_add_setting (connection, NM_SETTING (sc));
462
uuid = nm_utils_uuid_generate ();
464
client = net_object_get_client (NET_OBJECT (device));
465
connections = nm_client_get_connections (client);
466
id = ce_page_get_next_available_name (connections, NAME_FORMAT_PROFILE, NULL);
469
NM_SETTING_CONNECTION_UUID, uuid,
470
NM_SETTING_CONNECTION_ID, id,
471
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
472
NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
475
nm_connection_add_setting (connection, nm_setting_wired_new ());
480
window = gtk_widget_get_toplevel (GTK_WIDGET (button));
482
nmdev = net_device_get_nm_device (NET_DEVICE (device));
483
editor = net_connection_editor_new (GTK_WINDOW (window), connection, nmdev, NULL, client);
484
g_signal_connect (editor, "done", G_CALLBACK (editor_done), device);
485
net_connection_editor_run (editor);
489
device_off_toggled (GtkSwitch *sw,
491
NetDeviceEthernet *device)
495
NMConnection *connection;
497
if (device->updating_device)
500
client = net_object_get_client (NET_OBJECT (device));
501
nm_device = net_device_get_nm_device (NET_DEVICE (device));
503
if (gtk_switch_get_active (sw)) {
504
connection = net_device_get_find_connection (NET_DEVICE (device));
505
if (connection != NULL) {
506
nm_client_activate_connection_async (client,
509
NULL, NULL, NULL, NULL);
512
nm_device_disconnect (nm_device, NULL, NULL);
517
device_title_changed (NetDeviceEthernet *device,
521
device_ethernet_refresh_ui (device);
525
connection_activated (GtkListBox *list, GtkListBoxRow *row, NetDeviceEthernet *device)
529
NMConnection *connection;
531
client = net_object_get_client (NET_OBJECT (device));
532
nm_device = net_device_get_nm_device (NET_DEVICE (device));
534
if (!NM_IS_DEVICE_ETHERNET (nm_device) ||
535
!nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (nm_device)))
538
connection = NM_CONNECTION (g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (row))), "connection"));
540
nm_client_activate_connection_async (client,
543
NULL, NULL, NULL, NULL);
547
device_ethernet_constructed (GObject *object)
549
NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
555
widget = GTK_WIDGET (gtk_builder_get_object (device->builder,
556
"device_off_switch"));
557
g_signal_connect (widget, "notify::active",
558
G_CALLBACK (device_off_toggled), device);
560
device->scrolled_window = swin = GTK_WIDGET (gtk_builder_get_object (device->builder, "list"));
561
device->list = list = GTK_WIDGET (gtk_list_box_new ());
562
gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
563
gtk_list_box_set_header_func (GTK_LIST_BOX (list), cc_list_box_update_header_func, NULL, NULL);
564
gtk_container_add (GTK_CONTAINER (swin), list);
565
g_signal_connect (list, "row-activated",
566
G_CALLBACK (connection_activated), device);
567
gtk_widget_show (list);
569
device->details = GTK_WIDGET (gtk_builder_get_object (device->builder, "details"));
571
device->details_button = GTK_WIDGET (gtk_builder_get_object (device->builder, "details_button"));
572
g_signal_connect (device->details_button, "clicked",
573
G_CALLBACK (show_details_for_wired), device);
575
device->add_profile_button = GTK_WIDGET (gtk_builder_get_object (device->builder, "add_profile_button"));
576
g_signal_connect (device->add_profile_button, "clicked",
577
G_CALLBACK (add_profile), device);
579
client = net_object_get_client (NET_OBJECT (object));
580
g_signal_connect (client, NM_CLIENT_CONNECTION_ADDED,
581
G_CALLBACK (client_connection_added_cb), object);
582
g_signal_connect_object (client, NM_CLIENT_CONNECTION_REMOVED,
583
G_CALLBACK (connection_removed), device, 0);
585
device_ethernet_refresh_ui (device);
589
device_ethernet_finalize (GObject *object)
591
NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
593
g_object_unref (device->builder);
594
g_hash_table_destroy (device->connections);
596
G_OBJECT_CLASS (net_device_ethernet_parent_class)->finalize (object);
600
device_ethernet_refresh (NetObject *object)
602
NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
603
device_ethernet_refresh_ui (device);
607
net_device_ethernet_class_init (NetDeviceEthernetClass *klass)
609
NetDeviceSimpleClass *simple_class = NET_DEVICE_SIMPLE_CLASS (klass);
610
NetObjectClass *obj_class = NET_OBJECT_CLASS (klass);
611
GObjectClass *object_class = G_OBJECT_CLASS (klass);
613
simple_class->get_speed = device_ethernet_get_speed;
614
obj_class->refresh = device_ethernet_refresh;
615
obj_class->add_to_notebook = device_ethernet_add_to_notebook;
616
object_class->constructed = device_ethernet_constructed;
617
object_class->finalize = device_ethernet_finalize;
621
net_device_ethernet_init (NetDeviceEthernet *device)
623
GError *error = NULL;
625
device->builder = gtk_builder_new ();
626
gtk_builder_add_from_resource (device->builder,
627
"/org/gnome/control-center/network/network-ethernet.ui",
630
g_warning ("Could not load interface file: %s", error->message);
631
g_error_free (error);
635
device->connections = g_hash_table_new (NULL, NULL);
637
g_signal_connect (device, "notify::title", G_CALLBACK (device_title_changed), NULL);