1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2  *
3  * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
4  *
5  * Licensed under the GNU General Public License Version 2
6  *
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.
11  *
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.
16  *
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.
20  */
21 
22 #include "config.h"
23 
24 #include <glib-object.h>
25 #include <glib/gi18n.h>
26 
27 #include <NetworkManager.h>
28 
29 #include "panel-common.h"
30 
31 #include "shell/list-box-helper.h"
32 #include "connection-editor/net-connection-editor.h"
33 #include "connection-editor/ce-page.h"
34 
35 #include "net-device-ethernet.h"
36 
G_DEFINE_TYPE(NetDeviceEthernet,net_device_ethernet,NET_TYPE_DEVICE_SIMPLE)37 G_DEFINE_TYPE (NetDeviceEthernet, net_device_ethernet, NET_TYPE_DEVICE_SIMPLE)
38 
39 static char *
40 device_ethernet_get_speed (NetDeviceSimple *device_simple)
41 {
42         NMDevice *nm_device;
43         guint speed;
44 
45         nm_device = net_device_get_nm_device (NET_DEVICE (device_simple));
46 
47         speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (nm_device));
48         if (speed > 0) {
49                 /* Translators: network device speed */
50                 return g_strdup_printf (_("%d Mb/s"), speed);
51         } else
52                 return NULL;
53 }
54 
55 static GtkWidget *
device_ethernet_add_to_notebook(NetObject * object,GtkNotebook * notebook,GtkSizeGroup * heading_size_group)56 device_ethernet_add_to_notebook (NetObject    *object,
57                                  GtkNotebook  *notebook,
58                                  GtkSizeGroup *heading_size_group)
59 {
60         NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
61         GtkWidget *vbox;
62 
63         vbox = GTK_WIDGET (gtk_builder_get_object (device->builder, "vbox6"));
64         gtk_notebook_append_page (notebook, vbox, NULL);
65         return vbox;
66 }
67 
68 static void
add_details_row(GtkWidget * details,gint top,const gchar * heading,const gchar * value)69 add_details_row (GtkWidget *details, gint top, const gchar *heading, const gchar *value)
70 {
71         GtkWidget *heading_label;
72         GtkWidget *value_label;
73 
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);
78 
79         gtk_grid_attach (GTK_GRID (details), heading_label, 0, top, 1, 1);
80 
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);
84 
85         gtk_label_set_mnemonic_widget (GTK_LABEL (heading_label), value_label);
86 
87         gtk_grid_attach (GTK_GRID (details), value_label, 1, top, 1, 1);
88 }
89 
90 static gchar *
get_last_used_string(NMConnection * connection)91 get_last_used_string (NMConnection *connection)
92 {
93         gchar *last_used = NULL;
94         GDateTime *now = NULL;
95         GDateTime *then = NULL;
96         gint days;
97         GTimeSpan diff;
98         guint64 timestamp;
99         NMSettingConnection *s_con;
100 
101         s_con = nm_connection_get_setting_connection (connection);
102         if (s_con == NULL)
103                 goto out;
104         timestamp = nm_setting_connection_get_timestamp (s_con);
105         if (timestamp == 0) {
106                 last_used = g_strdup (_("never"));
107                 goto out;
108         }
109 
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;
115         if (days == 0)
116                 last_used = g_strdup (_("today"));
117         else if (days == 1)
118                 last_used = g_strdup (_("yesterday"));
119         else
120                 last_used = g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days);
121 out:
122         if (now != NULL)
123                 g_date_time_unref (now);
124         if (then != NULL)
125                 g_date_time_unref (then);
126 
127         return last_used;
128 }
129 
130 static void
add_details(GtkWidget * details,NMDevice * device,NMConnection * connection)131 add_details (GtkWidget *details, NMDevice *device, NMConnection *connection)
132 {
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;
139         gint i = 0;
140 
141         ip4_config = nm_device_get_ip4_config (device);
142         if (ip4_config) {
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);
146         }
147         ip6_config = nm_device_get_ip6_config (device);
148         if (ip6_config) {
149                 ip6_address = panel_get_ip6_address_as_string (ip6_config);
150         }
151 
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);
159         }
160 
161         add_details_row (details, i++, _("Hardware Address"),
162                          nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device)));
163 
164         if (ip4_route)
165                 add_details_row (details, i++, _("Default Route"), ip4_route);
166         if (ip4_dns)
167                 add_details_row (details, i++, _("DNS"), ip4_dns);
168 
169         if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) {
170                 gchar *last_used;
171                 last_used = get_last_used_string (connection);
172                 add_details_row (details, i++, _("Last used"), last_used);
173                 g_free (last_used);
174         }
175 
176         g_free (ip4_address);
177         g_free (ip4_route);
178         g_free (ip4_dns);
179         g_free (ip6_address);
180 }
181 
182 static void populate_ui (NetDeviceEthernet *device);
183 
184 static gboolean
device_state_to_off_switch(NMDeviceState state)185 device_state_to_off_switch (NMDeviceState state)
186 {
187         switch (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:
193                         return FALSE;
194                 default:
195                         return TRUE;
196         }
197 }
198 
199 static void
device_ethernet_refresh_ui(NetDeviceEthernet * device)200 device_ethernet_refresh_ui (NetDeviceEthernet *device)
201 {
202         NMDevice *nm_device;
203         NMDeviceState state;
204         GtkWidget *widget;
205         gchar *speed = NULL;
206 
207         nm_device = net_device_get_nm_device (NET_DEVICE (device));
208 
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)));
211 
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);
216 
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;
225 
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);
229 
230         populate_ui (device);
231 }
232 
233 static void
editor_done(NetConnectionEditor * editor,gboolean success,NetDeviceEthernet * device)234 editor_done (NetConnectionEditor *editor,
235              gboolean             success,
236              NetDeviceEthernet   *device)
237 {
238         g_object_unref (editor);
239         device_ethernet_refresh_ui (device);
240 }
241 
242 static void
show_details(GtkButton * button,NetDeviceEthernet * device,const gchar * title)243 show_details (GtkButton *button, NetDeviceEthernet *device, const gchar *title)
244 {
245         GtkWidget *row;
246         NMConnection *connection;
247         GtkWidget *window;
248         NetConnectionEditor *editor;
249         NMClient *client;
250         NMDevice *nmdev;
251 
252         window = gtk_widget_get_toplevel (GTK_WIDGET (button));
253 
254         row = GTK_WIDGET (g_object_get_data (G_OBJECT (button), "row"));
255         connection = NM_CONNECTION (g_object_get_data (G_OBJECT (row), "connection"));
256 
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);
260         if (title)
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);
264 }
265 
266 static void
show_details_for_row(GtkButton * button,NetDeviceEthernet * device)267 show_details_for_row (GtkButton *button, NetDeviceEthernet *device)
268 {
269         show_details (button, device, NULL);
270 }
271 
272 static void
show_details_for_wired(GtkButton * button,NetDeviceEthernet * device)273 show_details_for_wired (GtkButton *button, NetDeviceEthernet *device)
274 {
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
278          * device list.
279          */
280         show_details (button, device, _("Wired"));
281 }
282 
283 static void
add_row(NetDeviceEthernet * device,NMConnection * connection)284 add_row (NetDeviceEthernet *device, NMConnection *connection)
285 {
286         GtkWidget *row;
287         GtkWidget *widget;
288         GtkWidget *box;
289         GtkWidget *details;
290         NMDevice *nmdev;
291         NMActiveConnection *aconn;
292         gboolean active;
293         GtkWidget *image;
294 
295         active = FALSE;
296 
297         nmdev = net_device_get_nm_device (NET_DEVICE (device));
298         aconn = nm_device_get_active_connection (nmdev);
299         if (aconn) {
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;
304         }
305 
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);
315 
316         if (active) {
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);
321 
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);
325 
326                 gtk_box_pack_start (GTK_BOX (row), details, FALSE, TRUE, 0);
327 
328                 add_details (details, nmdev, connection);
329         }
330 
331         /* filler */
332         widget = gtk_label_new ("");
333         gtk_widget_set_hexpand (widget, TRUE);
334         gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0);
335 
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);
354 
355         gtk_widget_show_all (row);
356 
357         g_object_set_data (G_OBJECT (row), "connection", connection);
358 
359         gtk_container_add (GTK_CONTAINER (device->list), row);
360 }
361 
362 static void
connection_removed(NMClient * client,NMRemoteConnection * connection,NetDeviceEthernet * device)363 connection_removed (NMClient           *client,
364                     NMRemoteConnection *connection,
365                     NetDeviceEthernet  *device)
366 {
367         if (g_hash_table_remove (device->connections, connection))
368                 device_ethernet_refresh_ui (device);
369 }
370 
371 static void
populate_ui(NetDeviceEthernet * device)372 populate_ui (NetDeviceEthernet *device)
373 {
374         GList *children, *c;
375         GSList *connections, *l;
376         NMConnection *connection;
377         gint n_connections;
378 
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);
382         }
383         g_list_free (children);
384 
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);
388         }
389         g_list_free (children);
390 
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);
396                 }
397         }
398         n_connections = g_slist_length (connections);
399 
400         if (n_connections > 4) {
401                 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (device->scrolled_window),
402                                                 GTK_POLICY_NEVER,
403                                                 GTK_POLICY_AUTOMATIC);
404                 gtk_widget_set_vexpand (device->scrolled_window, TRUE);
405         } else {
406                 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (device->scrolled_window),
407                                                 GTK_POLICY_NEVER,
408                                                 GTK_POLICY_NEVER);
409                 gtk_widget_set_vexpand (device->scrolled_window, FALSE);
410         }
411 
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);
418                 }
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);
428 
429         } else {
430                 gtk_widget_hide (device->scrolled_window);
431                 gtk_widget_hide (device->details);
432                 gtk_widget_hide (device->details_button);
433         }
434 
435         g_slist_free (connections);
436 }
437 
438 static void
client_connection_added_cb(NMClient * client,NMRemoteConnection * connection,NetDeviceEthernet * device)439 client_connection_added_cb (NMClient           *client,
440                             NMRemoteConnection *connection,
441                             NetDeviceEthernet  *device)
442 {
443         device_ethernet_refresh_ui (device);
444 }
445 
446 static void
add_profile(GtkButton * button,NetDeviceEthernet * device)447 add_profile (GtkButton *button, NetDeviceEthernet *device)
448 {
449         NMConnection *connection;
450         NMSettingConnection *sc;
451         gchar *uuid, *id;
452         NetConnectionEditor *editor;
453         GtkWidget *window;
454         NMClient *client;
455         NMDevice *nmdev;
456         const GPtrArray *connections;
457 
458         connection = nm_simple_connection_new ();
459         sc = NM_SETTING_CONNECTION (nm_setting_connection_new ());
460         nm_connection_add_setting (connection, NM_SETTING (sc));
461 
462         uuid = nm_utils_uuid_generate ();
463 
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);
467 
468         g_object_set (sc,
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,
473                       NULL);
474 
475         nm_connection_add_setting (connection, nm_setting_wired_new ());
476 
477         g_free (uuid);
478         g_free (id);
479 
480         window = gtk_widget_get_toplevel (GTK_WIDGET (button));
481 
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);
486 }
487 
488 static void
device_off_toggled(GtkSwitch * sw,GParamSpec * pspec,NetDeviceEthernet * device)489 device_off_toggled (GtkSwitch         *sw,
490                     GParamSpec        *pspec,
491                     NetDeviceEthernet *device)
492 {
493         NMClient *client;
494         NMDevice *nm_device;
495         NMConnection *connection;
496 
497         if (device->updating_device)
498                 return;
499 
500         client = net_object_get_client (NET_OBJECT (device));
501         nm_device = net_device_get_nm_device (NET_DEVICE (device));
502 
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,
507                                                              connection,
508                                                              nm_device,
509                                                              NULL, NULL, NULL, NULL);
510                 }
511         } else {
512                 nm_device_disconnect (nm_device, NULL, NULL);
513         }
514 }
515 
516 static void
device_title_changed(NetDeviceEthernet * device,GParamSpec * pspec,gpointer user_data)517 device_title_changed (NetDeviceEthernet *device,
518                       GParamSpec        *pspec,
519                       gpointer           user_data)
520 {
521         device_ethernet_refresh_ui (device);
522 }
523 
524 static void
connection_activated(GtkListBox * list,GtkListBoxRow * row,NetDeviceEthernet * device)525 connection_activated (GtkListBox *list, GtkListBoxRow *row, NetDeviceEthernet *device)
526 {
527         NMClient *client;
528         NMDevice *nm_device;
529         NMConnection *connection;
530 
531         client = net_object_get_client (NET_OBJECT (device));
532         nm_device = net_device_get_nm_device (NET_DEVICE (device));
533 
534         if (!NM_IS_DEVICE_ETHERNET (nm_device) ||
535             !nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (nm_device)))
536                 return;
537 
538         connection = NM_CONNECTION (g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (row))), "connection"));
539 
540         nm_client_activate_connection_async (client,
541                                              connection,
542                                              nm_device,
543                                              NULL, NULL, NULL, NULL);
544 }
545 
546 static void
device_ethernet_constructed(GObject * object)547 device_ethernet_constructed (GObject *object)
548 {
549         NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
550         NMClient *client;
551         GtkWidget *list;
552         GtkWidget *swin;
553         GtkWidget *widget;
554 
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);
559 
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);
568 
569         device->details = GTK_WIDGET (gtk_builder_get_object (device->builder, "details"));
570 
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);
574 
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);
578 
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);
584 
585         device_ethernet_refresh_ui (device);
586 }
587 
588 static void
device_ethernet_finalize(GObject * object)589 device_ethernet_finalize (GObject *object)
590 {
591         NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
592 
593         g_object_unref (device->builder);
594         g_hash_table_destroy (device->connections);
595 
596         G_OBJECT_CLASS (net_device_ethernet_parent_class)->finalize (object);
597 }
598 
599 static void
device_ethernet_refresh(NetObject * object)600 device_ethernet_refresh (NetObject *object)
601 {
602         NetDeviceEthernet *device = NET_DEVICE_ETHERNET (object);
603         device_ethernet_refresh_ui (device);
604 }
605 
606 static void
net_device_ethernet_class_init(NetDeviceEthernetClass * klass)607 net_device_ethernet_class_init (NetDeviceEthernetClass *klass)
608 {
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);
612 
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;
618 }
619 
620 static void
net_device_ethernet_init(NetDeviceEthernet * device)621 net_device_ethernet_init (NetDeviceEthernet *device)
622 {
623         GError *error = NULL;
624 
625         device->builder = gtk_builder_new ();
626         gtk_builder_add_from_resource (device->builder,
627                                        "/org/cinnamon/control-center/network/network-ethernet.ui",
628                                        &error);
629         if (error != NULL) {
630                 g_warning ("Could not load interface file: %s", error->message);
631                 g_error_free (error);
632                 return;
633         }
634 
635         device->connections = g_hash_table_new (NULL, NULL);
636 
637         g_signal_connect (device, "notify::title", G_CALLBACK (device_title_changed), NULL);
638 }
639