1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2010-2012 Richard Hughes <richard@hughsie.com>
4 * Copyright (C) 2012 Thomas Bechtold <thomasbechtold@jpberlin.de>
5 * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
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, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 #include <config.h>
23 #include <glib/gi18n.h>
24 #include <stdlib.h>
25
26 #include "cc-network-panel.h"
27 #include "cc-network-resources.h"
28
29 #include <NetworkManager.h>
30
31 #include "net-device.h"
32 #include "net-device-mobile.h"
33 #include "net-device-wifi.h"
34 #include "net-device-ethernet.h"
35 #include "net-object.h"
36 #include "net-proxy.h"
37 #include "net-vpn.h"
38
39 #include "panel-common.h"
40
41 #include "network-dialogs.h"
42 #include "connection-editor/net-connection-editor.h"
43
44 #ifdef BUILD_MODEM
45 #include <libmm-glib.h>
46 #endif
47
48 #ifdef HAVE_NMA_18
49 #include <nma-cert-chooser.h>
50 #endif
51
52 CC_PANEL_REGISTER (CcNetworkPanel, cc_network_panel)
53
54 #define NETWORK_PANEL_PRIVATE(o) \
55 (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_NETWORK_PANEL, CcNetworkPanelPrivate))
56
57 typedef enum {
58 OPERATION_NULL,
59 OPERATION_SHOW_DEVICE,
60 OPERATION_CREATE_WIFI,
61 OPERATION_CONNECT_HIDDEN,
62 OPERATION_CONNECT_8021X,
63 OPERATION_CONNECT_MOBILE
64 } CmdlineOperation;
65
66 struct _CcNetworkPanelPrivate
67 {
68 GCancellable *cancellable;
69 GtkBuilder *builder;
70 GtkWidget *treeview;
71 NMClient *client;
72 #ifdef BUILD_MODEM
73 MMManager *modem_manager;
74 #else
75 void *modem_manager;
76 #endif
77 gboolean updating_device;
78
79 /* wireless dialog stuff */
80 CmdlineOperation arg_operation;
81 gchar *arg_device;
82 gchar *arg_access_point;
83 gboolean operation_done;
84 };
85
86 enum {
87 PANEL_DEVICES_COLUMN_ICON,
88 PANEL_DEVICES_COLUMN_OBJECT,
89 PANEL_DEVICES_COLUMN_LAST
90 };
91
92 enum {
93 PROP_0,
94 PROP_PARAMETERS
95 };
96
97 static NetObject *find_in_model_by_id (CcNetworkPanel *panel, const gchar *id, GtkTreeIter *iter_out);
98 static void handle_argv (CcNetworkPanel *panel);
99
100 static void
cc_network_panel_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)101 cc_network_panel_get_property (GObject *object,
102 guint property_id,
103 GValue *value,
104 GParamSpec *pspec)
105 {
106 switch (property_id) {
107 default:
108 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
109 }
110 }
111
112 static CmdlineOperation
cmdline_operation_from_string(const gchar * string)113 cmdline_operation_from_string (const gchar *string)
114 {
115 if (g_strcmp0 (string, "create-wifi") == 0)
116 return OPERATION_CREATE_WIFI;
117 if (g_strcmp0 (string, "connect-hidden-wifi") == 0)
118 return OPERATION_CONNECT_HIDDEN;
119 if (g_strcmp0 (string, "connect-8021x-wifi") == 0)
120 return OPERATION_CONNECT_8021X;
121 if (g_strcmp0 (string, "connect-3g") == 0)
122 return OPERATION_CONNECT_MOBILE;
123 if (g_strcmp0 (string, "show-device") == 0)
124 return OPERATION_SHOW_DEVICE;
125
126 g_warning ("Invalid additional argument %s", string);
127 return OPERATION_NULL;
128 }
129
130 static void
reset_command_line_args(CcNetworkPanel * self)131 reset_command_line_args (CcNetworkPanel *self)
132 {
133 self->priv->arg_operation = OPERATION_NULL;
134 g_clear_pointer (&self->priv->arg_device, g_free);
135 g_clear_pointer (&self->priv->arg_access_point, g_free);
136 }
137
138 static gboolean
verify_argv(CcNetworkPanel * self,const char ** args)139 verify_argv (CcNetworkPanel *self,
140 const char **args)
141 {
142 switch (self->priv->arg_operation) {
143 case OPERATION_CONNECT_MOBILE:
144 case OPERATION_CONNECT_8021X:
145 case OPERATION_SHOW_DEVICE:
146 if (self->priv->arg_device == NULL) {
147 g_warning ("Operation %s requires an object path", args[0]);
148 return FALSE;
149 }
150 default:
151 return TRUE;
152 }
153 }
154
155 static GPtrArray *
variant_av_to_string_array(GVariant * array)156 variant_av_to_string_array (GVariant *array)
157 {
158 GVariantIter iter;
159 GVariant *v;
160 GPtrArray *strv;
161 gsize count;
162 count = g_variant_iter_init (&iter, array);
163 strv = g_ptr_array_sized_new (count + 1);
164 while (g_variant_iter_next (&iter, "v", &v)) {
165 if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
166 g_ptr_array_add (strv, (gpointer *)g_variant_get_string (v, NULL));
167 g_variant_unref (v);
168 }
169 g_ptr_array_add (strv, NULL); /* NULL-terminate the strv data array */
170 return strv;
171 }
172
173 static void
cc_network_panel_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)174 cc_network_panel_set_property (GObject *object,
175 guint property_id,
176 const GValue *value,
177 GParamSpec *pspec)
178 {
179 CcNetworkPanel *self = CC_NETWORK_PANEL (object);
180 CcNetworkPanelPrivate *priv = self->priv;
181
182 switch (property_id) {
183 case PROP_PARAMETERS: {
184 GVariant *parameters;
185
186 reset_command_line_args (self);
187
188 parameters = g_value_get_variant (value);
189 if (parameters) {
190 GPtrArray *array;
191 const gchar **args;
192 array = variant_av_to_string_array (parameters);
193 args = (const gchar **) array->pdata;
194
195 g_debug ("Invoked with operation %s", args[0]);
196
197 if (args[0])
198 priv->arg_operation = cmdline_operation_from_string (args[0]);
199 if (args[0] && args[1])
200 priv->arg_device = g_strdup (args[1]);
201 if (args[0] && args[1] && args[2])
202 priv->arg_access_point = g_strdup (args[2]);
203
204 if (verify_argv (self, (const char **) args) == FALSE) {
205 reset_command_line_args (self);
206 g_ptr_array_unref (array);
207 return;
208 }
209 g_ptr_array_unref (array);
210 g_debug ("Calling handle_argv() after setting property");
211 handle_argv (self);
212 }
213 break;
214 }
215 default:
216 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
217 }
218 }
219
220 static void
cc_network_panel_dispose(GObject * object)221 cc_network_panel_dispose (GObject *object)
222 {
223 CcNetworkPanelPrivate *priv = CC_NETWORK_PANEL (object)->priv;
224
225 if (priv->cancellable != NULL)
226 g_cancellable_cancel (priv->cancellable);
227
228 g_clear_object (&priv->cancellable);
229 g_clear_object (&priv->builder);
230 g_clear_object (&priv->client);
231 g_clear_object (&priv->modem_manager);
232
233 G_OBJECT_CLASS (cc_network_panel_parent_class)->dispose (object);
234 }
235
236 static void
cc_network_panel_finalize(GObject * object)237 cc_network_panel_finalize (GObject *object)
238 {
239 CcNetworkPanel *panel = CC_NETWORK_PANEL (object);
240
241 reset_command_line_args (panel);
242
243 G_OBJECT_CLASS (cc_network_panel_parent_class)->finalize (object);
244 }
245
246 static const char *
cc_network_panel_get_help_uri(CcPanel * panel)247 cc_network_panel_get_help_uri (CcPanel *panel)
248 {
249 return "help:gnome-help/net";
250 }
251
252 static void
cc_network_panel_class_init(CcNetworkPanelClass * klass)253 cc_network_panel_class_init (CcNetworkPanelClass *klass)
254 {
255 GObjectClass *object_class = G_OBJECT_CLASS (klass);
256 CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
257
258 g_type_class_add_private (klass, sizeof (CcNetworkPanelPrivate));
259
260 panel_class->get_help_uri = cc_network_panel_get_help_uri;
261
262 object_class->get_property = cc_network_panel_get_property;
263 object_class->set_property = cc_network_panel_set_property;
264 object_class->dispose = cc_network_panel_dispose;
265 object_class->finalize = cc_network_panel_finalize;
266
267 g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
268 }
269
270 static NetObject *
get_selected_object(CcNetworkPanel * panel)271 get_selected_object (CcNetworkPanel *panel)
272 {
273 GtkTreeSelection *selection;
274 GtkTreeModel *model;
275 GtkTreeIter iter;
276 NetObject *object = NULL;
277
278 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->priv->treeview));
279 if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
280 return NULL;
281 }
282
283 gtk_tree_model_get (model, &iter,
284 PANEL_DEVICES_COLUMN_OBJECT, &object,
285 -1);
286
287 return object;
288 }
289
290 static void
select_first_device(CcNetworkPanel * panel)291 select_first_device (CcNetworkPanel *panel)
292 {
293 GtkTreePath *path;
294 GtkTreeSelection *selection;
295
296 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->priv->treeview));
297
298 /* select the first device */
299 path = gtk_tree_path_new_from_string ("0");
300 gtk_tree_selection_select_path (selection, path);
301 gtk_tree_path_free (path);
302 }
303
304 static void
select_tree_iter(CcNetworkPanel * panel,GtkTreeIter * iter)305 select_tree_iter (CcNetworkPanel *panel, GtkTreeIter *iter)
306 {
307 GtkTreeSelection *selection;
308
309 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->priv->treeview));
310
311 gtk_tree_selection_select_iter (selection, iter);
312 }
313
314 static void
object_removed_cb(NetObject * object,CcNetworkPanel * panel)315 object_removed_cb (NetObject *object, CcNetworkPanel *panel)
316 {
317 gboolean ret;
318 NetObject *object_tmp;
319 GtkTreeIter iter;
320 GtkTreeModel *model;
321 GtkTreeSelection *selection;
322
323 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->priv->treeview));
324
325 /* remove device from model */
326 model = GTK_TREE_MODEL (gtk_builder_get_object (panel->priv->builder,
327 "liststore_devices"));
328 ret = gtk_tree_model_get_iter_first (model, &iter);
329 if (!ret)
330 return;
331
332 /* get the other elements */
333 do {
334 gtk_tree_model_get (model, &iter,
335 PANEL_DEVICES_COLUMN_OBJECT, &object_tmp,
336 -1);
337 if (g_strcmp0 (net_object_get_id (object),
338 net_object_get_id (object_tmp)) == 0) {
339 g_object_unref (object_tmp);
340 if (gtk_list_store_remove (GTK_LIST_STORE (model), &iter)) {
341 if (gtk_tree_model_get_iter_first (model, &iter))
342 gtk_tree_selection_select_iter (selection, &iter);
343 }
344 break;
345 }
346 g_object_unref (object_tmp);
347 } while (gtk_tree_model_iter_next (model, &iter));
348 }
349
350 GPtrArray *
cc_network_panel_get_devices(CcNetworkPanel * panel)351 cc_network_panel_get_devices (CcNetworkPanel *panel)
352 {
353 GPtrArray *devices;
354 GtkTreeModel *model;
355 GtkTreeIter iter;
356 NetObject *object;
357
358 devices = g_ptr_array_new_with_free_func (g_object_unref);
359
360 model = GTK_TREE_MODEL (gtk_builder_get_object (panel->priv->builder,
361 "liststore_devices"));
362 if (!gtk_tree_model_get_iter_first (model, &iter))
363 return devices;
364
365 do {
366 gtk_tree_model_get (model, &iter,
367 PANEL_DEVICES_COLUMN_OBJECT, &object,
368 -1);
369 if (NET_IS_DEVICE (object))
370 g_ptr_array_add (devices, object);
371 else
372 g_object_unref (object);
373 } while (gtk_tree_model_iter_next (model, &iter));
374
375 return devices;
376 }
377
378 static gint
panel_net_object_get_sort_category(NetObject * net_object)379 panel_net_object_get_sort_category (NetObject *net_object)
380 {
381 if (NET_IS_DEVICE (net_object)) {
382 return panel_device_get_sort_category (net_device_get_nm_device (NET_DEVICE (net_object)));
383 } else if (NET_IS_PROXY (net_object)) {
384 return 9;
385 } else if (NET_IS_VPN (net_object)) {
386 return 5;
387 }
388
389 g_assert_not_reached ();
390 }
391
392 static gint
panel_net_object_sort_func(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,void * data)393 panel_net_object_sort_func (GtkTreeModel *model, GtkTreeIter *a,
394 GtkTreeIter *b, void *data)
395 {
396 g_autoptr(NetObject) obj_a = NULL;
397 g_autoptr(NetObject) obj_b = NULL;
398 gint cat_a, cat_b;
399 const char *title_a, *title_b;
400
401 gtk_tree_model_get (model, a,
402 PANEL_DEVICES_COLUMN_OBJECT, &obj_a,
403 -1);
404 gtk_tree_model_get (model, b,
405 PANEL_DEVICES_COLUMN_OBJECT, &obj_b,
406 -1);
407
408 cat_a = panel_net_object_get_sort_category (obj_a);
409 cat_b = panel_net_object_get_sort_category (obj_b);
410
411 if (cat_a != cat_b)
412 return cat_a - cat_b;
413
414 title_a = net_object_get_title (obj_a);
415 title_b = net_object_get_title (obj_b);
416
417 if (title_a == title_b)
418 return 0;
419 if (title_a == NULL)
420 return -1;
421 if (title_b == NULL)
422 return 1;
423
424 return g_utf8_collate (title_a, title_b);
425 }
426
427 static void
panel_net_object_notify_title_cb(NetObject * net_object,GParamSpec * pspec,CcNetworkPanel * panel)428 panel_net_object_notify_title_cb (NetObject *net_object, GParamSpec *pspec, CcNetworkPanel *panel)
429 {
430 GtkTreeIter iter;
431 GtkListStore *liststore;
432
433 if (!find_in_model_by_id (panel, net_object_get_id (net_object), &iter))
434 return;
435
436 liststore = GTK_LIST_STORE (gtk_builder_get_object (panel->priv->builder,
437 "liststore_devices"));
438
439 /* gtk_tree_model_row_changed would not cause the list store to resort.
440 * Instead set the object column to the current value.
441 * See https://bugzilla.gnome.org/show_bug.cgi?id=782737 */
442 gtk_list_store_set (liststore, &iter,
443 PANEL_DEVICES_COLUMN_OBJECT, net_object,
444 -1);
445 }
446
447 static void
panel_refresh_device_titles(CcNetworkPanel * panel)448 panel_refresh_device_titles (CcNetworkPanel *panel)
449 {
450 GPtrArray *ndarray, *nmdarray;
451 NetDevice **devices;
452 NMDevice **nm_devices, *nm_device;
453 gchar **titles;
454 gint i, num_devices;
455
456 ndarray = cc_network_panel_get_devices (panel);
457 if (!ndarray->len) {
458 g_ptr_array_free (ndarray, TRUE);
459 return;
460 }
461
462 nmdarray = g_ptr_array_new ();
463 for (i = 0; i < ndarray->len; i++) {
464 nm_device = net_device_get_nm_device (ndarray->pdata[i]);
465 if (nm_device)
466 g_ptr_array_add (nmdarray, nm_device);
467 else
468 g_ptr_array_remove_index (ndarray, i--);
469 }
470
471 devices = (NetDevice **)ndarray->pdata;
472 nm_devices = (NMDevice **)nmdarray->pdata;
473 num_devices = ndarray->len;
474
475 titles = nm_device_disambiguate_names (nm_devices, num_devices);
476 for (i = 0; i < num_devices; i++) {
477 net_object_set_title (NET_OBJECT (devices[i]), titles[i]);
478 g_free (titles[i]);
479 }
480 g_free (titles);
481 g_ptr_array_free (ndarray, TRUE);
482 g_ptr_array_free (nmdarray, TRUE);
483 }
484
485 static gboolean
handle_argv_for_device(CcNetworkPanel * panel,NMDevice * device,GtkTreeIter * iter)486 handle_argv_for_device (CcNetworkPanel *panel,
487 NMDevice *device,
488 GtkTreeIter *iter)
489 {
490 CcNetworkPanelPrivate *priv = panel->priv;
491 NMDeviceType type;
492 //GtkWidget *toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (panel)));
493 GtkWidget *toplevel = GTK_WIDGET(panel);
494
495 if (priv->arg_operation == OPERATION_NULL)
496 return TRUE;
497
498 type = nm_device_get_device_type (device);
499
500 if (type == NM_DEVICE_TYPE_WIFI &&
501 (priv->arg_operation == OPERATION_CREATE_WIFI ||
502 priv->arg_operation == OPERATION_CONNECT_HIDDEN)) {
503 g_debug ("Selecting wifi device");
504 select_tree_iter (panel, iter);
505
506 if (priv->arg_operation == OPERATION_CREATE_WIFI)
507 cc_network_panel_create_wifi_network (toplevel, priv->client);
508 else
509 cc_network_panel_connect_to_hidden_network (toplevel, priv->client);
510
511 reset_command_line_args (panel); /* done */
512 return TRUE;
513 } else if (g_strcmp0 (nm_object_get_path (NM_OBJECT (device)), priv->arg_device) == 0) {
514 if (priv->arg_operation == OPERATION_CONNECT_MOBILE) {
515 cc_network_panel_connect_to_3g_network (toplevel, priv->client, device);
516
517 reset_command_line_args (panel); /* done */
518 select_tree_iter (panel, iter);
519 return TRUE;
520 } else if (priv->arg_operation == OPERATION_CONNECT_8021X) {
521 cc_network_panel_connect_to_8021x_network (toplevel, priv->client, device, priv->arg_access_point);
522 reset_command_line_args (panel); /* done */
523 select_tree_iter (panel, iter);
524 return TRUE;
525 }
526 else if (priv->arg_operation == OPERATION_SHOW_DEVICE) {
527 select_tree_iter (panel, iter);
528 reset_command_line_args (panel); /* done */
529 return TRUE;
530 }
531 }
532
533 return FALSE;
534 }
535
536 static gboolean
handle_argv_for_connection(CcNetworkPanel * panel,NMConnection * connection,GtkTreeIter * iter)537 handle_argv_for_connection (CcNetworkPanel *panel,
538 NMConnection *connection,
539 GtkTreeIter *iter)
540 {
541 CcNetworkPanelPrivate *priv = panel->priv;
542
543 if (priv->arg_operation == OPERATION_NULL)
544 return TRUE;
545 if (priv->arg_operation != OPERATION_SHOW_DEVICE)
546 return FALSE;
547
548 if (g_strcmp0 (nm_connection_get_path (connection), priv->arg_device) == 0) {
549 reset_command_line_args (panel);
550 select_tree_iter (panel, iter);
551 return TRUE;
552 }
553
554 return FALSE;
555 }
556
557
558 static void
handle_argv(CcNetworkPanel * panel)559 handle_argv (CcNetworkPanel *panel)
560 {
561 GtkTreeModel *model;
562 GtkTreeIter iter;
563 gboolean ret;
564
565 if (panel->priv->arg_operation == OPERATION_NULL)
566 return;
567
568 model = GTK_TREE_MODEL (gtk_builder_get_object (panel->priv->builder,
569 "liststore_devices"));
570 ret = gtk_tree_model_get_iter_first (model, &iter);
571 while (ret) {
572 GObject *object_tmp;
573 NMDevice *device;
574 NMConnection *connection;
575 gboolean done = FALSE;
576
577 gtk_tree_model_get (model, &iter,
578 PANEL_DEVICES_COLUMN_OBJECT, &object_tmp,
579 -1);
580 if (NET_IS_DEVICE (object_tmp)) {
581 g_object_get (object_tmp, "nm-device", &device, NULL);
582 done = handle_argv_for_device (panel, device, &iter);
583 g_object_unref (device);
584 } else if (NET_IS_VPN (object_tmp)) {
585 g_object_get (object_tmp, "connection", &connection, NULL);
586 done = handle_argv_for_connection (panel, connection, &iter);
587 g_object_unref (connection);
588 }
589
590 g_object_unref (object_tmp);
591
592 if (done)
593 return;
594
595 ret = gtk_tree_model_iter_next (model, &iter);
596 }
597
598 g_debug ("Could not handle argv operation, no matching device yet?");
599 }
600
601 static void
state_changed_cb(NMDevice * device,NMDeviceState new_state,NMDeviceState old_state,NMDeviceStateReason reason,CcNetworkPanel * panel)602 state_changed_cb (NMDevice *device,
603 NMDeviceState new_state,
604 NMDeviceState old_state,
605 NMDeviceStateReason reason,
606 CcNetworkPanel *panel)
607 {
608 GtkListStore *store;
609 GtkTreeIter iter;
610
611 if (!find_in_model_by_id (panel, nm_device_get_udi (device), &iter)) {
612 return;
613 }
614
615 store = GTK_LIST_STORE (gtk_builder_get_object (panel->priv->builder,
616 "liststore_devices"));
617
618 gtk_list_store_set (store, &iter,
619 PANEL_DEVICES_COLUMN_ICON, panel_device_to_icon_name (device, TRUE),
620 -1);
621 }
622
623 static gboolean
panel_add_device(CcNetworkPanel * panel,NMDevice * device)624 panel_add_device (CcNetworkPanel *panel, NMDevice *device)
625 {
626 GtkListStore *liststore_devices;
627 GtkTreeIter iter;
628 NMDeviceType type;
629 NetDevice *net_device;
630 CcNetworkPanelPrivate *priv = panel->priv;
631 GtkNotebook *notebook;
632 GtkSizeGroup *size_group;
633 GType device_g_type;
634 const char *udi;
635
636 if (!nm_device_get_managed (device))
637 goto out;
638
639 /* do we have an existing object with this id? */
640 udi = nm_device_get_udi (device);
641 if (find_in_model_by_id (panel, udi, NULL) != NULL)
642 goto out;
643
644 type = nm_device_get_device_type (device);
645
646 g_debug ("device %s type %i path %s",
647 udi, type, nm_object_get_path (NM_OBJECT (device)));
648
649 /* map the NMDeviceType to the GType, or ignore */
650 switch (type) {
651 case NM_DEVICE_TYPE_ETHERNET:
652 device_g_type = NET_TYPE_DEVICE_ETHERNET;
653 break;
654 case NM_DEVICE_TYPE_MODEM:
655 device_g_type = NET_TYPE_DEVICE_MOBILE;
656 break;
657 case NM_DEVICE_TYPE_WIFI:
658 device_g_type = NET_TYPE_DEVICE_WIFI;
659 break;
660 /* not going to set up a cluster in GNOME */
661 case NM_DEVICE_TYPE_VETH:
662 /* enterprise features */
663 case NM_DEVICE_TYPE_BOND:
664 case NM_DEVICE_TYPE_TEAM:
665 /* Don't need the libvirtd bridge */
666 case NM_DEVICE_TYPE_BRIDGE:
667 /* Don't add VPN devices */
668 case NM_DEVICE_TYPE_TUN:
669 goto out;
670 default:
671 device_g_type = NET_TYPE_DEVICE_SIMPLE;
672 break;
673 }
674
675 /* create device */
676 net_device = g_object_new (device_g_type,
677 "panel", panel,
678 "removable", FALSE,
679 "cancellable", panel->priv->cancellable,
680 "client", panel->priv->client,
681 "nm-device", device,
682 "id", nm_device_get_udi (device),
683 NULL);
684
685 if (type == NM_DEVICE_TYPE_MODEM &&
686 g_str_has_prefix (nm_device_get_udi (device), "/org/freedesktop/ModemManager1/Modem/")) {
687 GDBusObject *modem_object;
688
689 if (priv->modem_manager == NULL) {
690 g_warning ("Cannot grab information for modem at %s: No ModemManager support",
691 nm_device_get_udi (device));
692 goto out;
693 }
694
695 modem_object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (priv->modem_manager),
696 nm_device_get_udi (device));
697 if (modem_object == NULL) {
698 g_warning ("Cannot grab information for modem at %s: Not found",
699 nm_device_get_udi (device));
700 goto out;
701 }
702
703 /* Set the modem object in the NetDeviceMobile */
704 g_object_set (net_device,
705 "mm-object", modem_object,
706 NULL);
707 g_object_unref (modem_object);
708 }
709
710 /* add as a panel */
711 if (device_g_type != NET_TYPE_DEVICE) {
712 notebook = GTK_NOTEBOOK (gtk_builder_get_object (panel->priv->builder,
713 "notebook_types"));
714 size_group = GTK_SIZE_GROUP (gtk_builder_get_object (panel->priv->builder,
715 "sizegroup1"));
716 net_object_add_to_notebook (NET_OBJECT (net_device),
717 notebook,
718 size_group);
719 }
720
721 liststore_devices = GTK_LIST_STORE (gtk_builder_get_object (priv->builder,
722 "liststore_devices"));
723 g_signal_connect_object (net_device, "removed",
724 G_CALLBACK (object_removed_cb), panel, 0);
725 gtk_list_store_append (liststore_devices, &iter);
726 gtk_list_store_set (liststore_devices,
727 &iter,
728 PANEL_DEVICES_COLUMN_ICON, panel_device_to_icon_name (device, TRUE),
729 PANEL_DEVICES_COLUMN_OBJECT, net_device,
730 -1);
731 g_signal_connect (net_device, "notify::title",
732 G_CALLBACK (panel_net_object_notify_title_cb), panel);
733
734 g_object_unref (net_device);
735 g_signal_connect (device, "state-changed",
736 G_CALLBACK (state_changed_cb), panel);
737
738 out:
739 return FALSE;
740 }
741
742 static void
panel_remove_device(CcNetworkPanel * panel,NMDevice * device)743 panel_remove_device (CcNetworkPanel *panel, NMDevice *device)
744 {
745 gboolean ret;
746 NetObject *object_tmp;
747 GtkTreeIter iter;
748 GtkTreeModel *model;
749
750 /* remove device from model */
751 model = GTK_TREE_MODEL (gtk_builder_get_object (panel->priv->builder,
752 "liststore_devices"));
753 ret = gtk_tree_model_get_iter_first (model, &iter);
754 if (!ret)
755 return;
756
757 /* get the other elements */
758 do {
759 gtk_tree_model_get (model, &iter,
760 PANEL_DEVICES_COLUMN_OBJECT, &object_tmp,
761 -1);
762 if (g_strcmp0 (net_object_get_id (object_tmp),
763 nm_device_get_udi (device)) == 0) {
764 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
765 g_object_unref (object_tmp);
766 break;
767 }
768 g_object_unref (object_tmp);
769 } while (gtk_tree_model_iter_next (model, &iter));
770 }
771
772 static void
get_object_title(GtkTreeViewColumn * column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)773 get_object_title (GtkTreeViewColumn *column,
774 GtkCellRenderer *cell,
775 GtkTreeModel *model,
776 GtkTreeIter *iter,
777 gpointer data)
778 {
779 NetObject *object;
780
781 gtk_tree_model_get (model, iter,
782 PANEL_DEVICES_COLUMN_OBJECT, &object,
783 -1);
784 if (!object)
785 return;
786
787 g_object_set (cell, "text", net_object_get_title (object), NULL);
788 g_object_unref (object);
789 }
790
791 static void
panel_add_devices_columns(CcNetworkPanel * panel,GtkTreeView * treeview)792 panel_add_devices_columns (CcNetworkPanel *panel, GtkTreeView *treeview)
793 {
794 CcNetworkPanelPrivate *priv = panel->priv;
795 GtkCellRenderer *renderer;
796 GtkListStore *liststore_devices;
797 GtkTreeViewColumn *column;
798
799 /* image */
800 renderer = gtk_cell_renderer_pixbuf_new ();
801 g_object_set (renderer,
802 "width", 32,
803 "xalign", 1.0,
804 "stock-size", GTK_ICON_SIZE_MENU,
805 "follow-state", TRUE,
806 NULL);
807 gtk_cell_renderer_set_padding (renderer, 4, 10);
808
809 column = gtk_tree_view_column_new_with_attributes ("icon", renderer,
810 "icon-name", PANEL_DEVICES_COLUMN_ICON,
811 NULL);
812 gtk_tree_view_append_column (treeview, column);
813
814 /* column for text */
815 renderer = gtk_cell_renderer_text_new ();
816 g_object_set (renderer,
817 "wrap-mode", PANGO_WRAP_WORD,
818 "ellipsize", PANGO_ELLIPSIZE_END,
819 NULL);
820 column = gtk_tree_view_column_new_with_attributes ("title", renderer, NULL);
821 gtk_tree_view_column_set_cell_data_func (GTK_TREE_VIEW_COLUMN (column),
822 renderer,
823 get_object_title,
824 NULL, NULL);
825 gtk_tree_view_column_set_sort_column_id (column, PANEL_DEVICES_COLUMN_OBJECT);
826 liststore_devices = GTK_LIST_STORE (gtk_builder_get_object (priv->builder,
827 "liststore_devices"));
828 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (liststore_devices),
829 PANEL_DEVICES_COLUMN_OBJECT,
830 panel_net_object_sort_func, NULL, NULL);
831 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore_devices),
832 PANEL_DEVICES_COLUMN_OBJECT,
833 GTK_SORT_ASCENDING);
834 gtk_tree_view_append_column (treeview, column);
835 gtk_tree_view_column_set_expand (column, TRUE);
836 }
837
838 static void
nm_devices_treeview_clicked_cb(GtkTreeSelection * selection,CcNetworkPanel * panel)839 nm_devices_treeview_clicked_cb (GtkTreeSelection *selection, CcNetworkPanel *panel)
840 {
841 CcNetworkPanelPrivate *priv = panel->priv;
842 const gchar *id_tmp;
843 const gchar *needle;
844 GList *l;
845 GList *panels = NULL;
846 GtkNotebook *notebook;
847 GtkTreeIter iter;
848 GtkTreeModel *model;
849 GtkWidget *widget;
850 guint i = 0;
851 NetObject *object = NULL;
852
853 if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
854 g_debug ("no row selected");
855 goto out;
856 }
857
858 /* find the widget in the notebook that matches the object ID */
859 object = get_selected_object (panel);
860 needle = net_object_get_id (object);
861 notebook = GTK_NOTEBOOK (gtk_builder_get_object (priv->builder,
862 "notebook_types"));
863 panels = gtk_container_get_children (GTK_CONTAINER (notebook));
864 for (l = panels; l != NULL; l = l->next) {
865 widget = GTK_WIDGET (l->data);
866 id_tmp = g_object_get_data (G_OBJECT (widget), "NetObject::id");
867 if (g_strcmp0 (needle, id_tmp) == 0) {
868 gtk_notebook_set_current_page (notebook, i);
869
870 /* object is deletable? */
871 widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
872 "remove_toolbutton"));
873 gtk_widget_set_sensitive (widget,
874 net_object_get_removable (object));
875 break;
876 }
877 i++;
878 }
879 g_object_unref (object);
880 out:
881 g_list_free (panels);
882 }
883
884 static void
panel_add_proxy_device(CcNetworkPanel * panel)885 panel_add_proxy_device (CcNetworkPanel *panel)
886 {
887 GtkListStore *liststore_devices;
888 GtkTreeIter iter;
889 NetProxy *proxy;
890 GtkNotebook *notebook;
891 GtkSizeGroup *size_group;
892
893 /* add proxy to notebook */
894 proxy = net_proxy_new ();
895 notebook = GTK_NOTEBOOK (gtk_builder_get_object (panel->priv->builder,
896 "notebook_types"));
897 size_group = GTK_SIZE_GROUP (gtk_builder_get_object (panel->priv->builder,
898 "sizegroup1"));
899 net_object_add_to_notebook (NET_OBJECT (proxy),
900 notebook,
901 size_group);
902
903 /* add proxy to device list */
904 liststore_devices = GTK_LIST_STORE (gtk_builder_get_object (panel->priv->builder,
905 "liststore_devices"));
906 net_object_set_title (NET_OBJECT (proxy), _("Network proxy"));
907 gtk_list_store_append (liststore_devices, &iter);
908 gtk_list_store_set (liststore_devices,
909 &iter,
910 PANEL_DEVICES_COLUMN_ICON, "preferences-system-network-symbolic",
911 PANEL_DEVICES_COLUMN_OBJECT, proxy,
912 -1);
913
914 /* NOTE: No connect to notify::title here as it is guaranteed to not
915 * be changed by anyone.*/
916
917 g_object_unref (proxy);
918 }
919
920 static void
connection_state_changed(NMActiveConnection * c,GParamSpec * pspec,CcNetworkPanel * panel)921 connection_state_changed (NMActiveConnection *c, GParamSpec *pspec, CcNetworkPanel *panel)
922 {
923 }
924
925 static void
active_connections_changed(NMClient * client,GParamSpec * pspec,gpointer user_data)926 active_connections_changed (NMClient *client, GParamSpec *pspec, gpointer user_data)
927 {
928 CcNetworkPanel *panel = user_data;
929 const GPtrArray *connections;
930 int i, j;
931
932 g_debug ("Active connections changed:");
933 connections = nm_client_get_active_connections (client);
934 for (i = 0; connections && (i < connections->len); i++) {
935 NMActiveConnection *connection;
936 const GPtrArray *devices;
937
938 connection = g_ptr_array_index (connections, i);
939 g_debug (" %s", nm_object_get_path (NM_OBJECT (connection)));
940 devices = nm_active_connection_get_devices (connection);
941 for (j = 0; devices && j < devices->len; j++)
942 g_debug (" %s", nm_device_get_udi (g_ptr_array_index (devices, j)));
943 if (NM_IS_VPN_CONNECTION (connection))
944 g_debug (" VPN base connection: %s", nm_active_connection_get_specific_object_path (connection));
945
946 if (g_object_get_data (G_OBJECT (connection), "has-state-changed-handler") == NULL) {
947 g_signal_connect_object (connection, "notify::state",
948 G_CALLBACK (connection_state_changed), panel, 0);
949 g_object_set_data (G_OBJECT (connection), "has-state-changed-handler", GINT_TO_POINTER (TRUE));
950 }
951 }
952 }
953
954 static void
device_added_cb(NMClient * client,NMDevice * device,CcNetworkPanel * panel)955 device_added_cb (NMClient *client, NMDevice *device, CcNetworkPanel *panel)
956 {
957 g_debug ("New device added");
958 panel_add_device (panel, device);
959 panel_refresh_device_titles (panel);
960 }
961
962 static void
device_removed_cb(NMClient * client,NMDevice * device,CcNetworkPanel * panel)963 device_removed_cb (NMClient *client, NMDevice *device, CcNetworkPanel *panel)
964 {
965 g_debug ("Device removed");
966 panel_remove_device (panel, device);
967 panel_refresh_device_titles (panel);
968 }
969
970 static void
manager_running(NMClient * client,GParamSpec * pspec,gpointer user_data)971 manager_running (NMClient *client, GParamSpec *pspec, gpointer user_data)
972 {
973 const GPtrArray *devices;
974 int i;
975 NMDevice *device_tmp;
976 GtkListStore *liststore_devices;
977 gboolean selected = FALSE;
978 CcNetworkPanel *panel = CC_NETWORK_PANEL (user_data);
979
980 /* clear all devices we added */
981 if (!nm_client_get_nm_running (client)) {
982 g_debug ("NM disappeared");
983 liststore_devices = GTK_LIST_STORE (gtk_builder_get_object (panel->priv->builder,
984 "liststore_devices"));
985 gtk_list_store_clear (liststore_devices);
986 panel_add_proxy_device (panel);
987 goto out;
988 }
989
990 g_debug ("coldplugging devices");
991 devices = nm_client_get_devices (client);
992 if (devices == NULL) {
993 g_debug ("No devices to add");
994 return;
995 }
996 for (i = 0; i < devices->len; i++) {
997 device_tmp = g_ptr_array_index (devices, i);
998 selected = panel_add_device (panel, device_tmp) || selected;
999 }
1000 out:
1001 if (!selected) {
1002 /* select the first device */
1003 select_first_device (panel);
1004 }
1005
1006 panel_refresh_device_titles (panel);
1007
1008 g_debug ("Calling handle_argv() after cold-plugging devices");
1009 handle_argv (panel);
1010 }
1011
1012 static NetObject *
find_in_model_by_id(CcNetworkPanel * panel,const gchar * id,GtkTreeIter * iter_out)1013 find_in_model_by_id (CcNetworkPanel *panel, const gchar *id, GtkTreeIter *iter_out)
1014 {
1015 gboolean ret;
1016 NetObject *object_tmp;
1017 GtkTreeIter iter;
1018 GtkTreeModel *model;
1019 NetObject *object = NULL;
1020
1021 /* find in model */
1022 model = GTK_TREE_MODEL (gtk_builder_get_object (panel->priv->builder,
1023 "liststore_devices"));
1024 ret = gtk_tree_model_get_iter_first (model, &iter);
1025 if (!ret)
1026 goto out;
1027
1028 /* get the other elements */
1029 ret = FALSE;
1030 do {
1031 gtk_tree_model_get (model, &iter,
1032 PANEL_DEVICES_COLUMN_OBJECT, &object_tmp,
1033 -1);
1034 if (object_tmp != NULL) {
1035 g_debug ("got %s", net_object_get_id (object_tmp));
1036 if (g_strcmp0 (net_object_get_id (object_tmp), id) == 0)
1037 object = object_tmp;
1038 g_object_unref (object_tmp);
1039 }
1040 } while (object == NULL && gtk_tree_model_iter_next (model, &iter));
1041 out:
1042 if (iter_out)
1043 *iter_out = iter;
1044 return object;
1045 }
1046
1047 static void
panel_add_vpn_device(CcNetworkPanel * panel,NMConnection * connection)1048 panel_add_vpn_device (CcNetworkPanel *panel, NMConnection *connection)
1049 {
1050 gchar *title;
1051 GtkListStore *liststore_devices;
1052 GtkTreeIter iter;
1053 NetVpn *net_vpn;
1054 const gchar *id;
1055 GtkNotebook *notebook;
1056 GtkSizeGroup *size_group;
1057
1058 /* does already exist */
1059 id = nm_connection_get_path (connection);
1060 if (find_in_model_by_id (panel, id, NULL) != NULL)
1061 return;
1062
1063 /* add as a VPN object */
1064 net_vpn = g_object_new (NET_TYPE_VPN,
1065 "panel", panel,
1066 "removable", TRUE,
1067 "id", id,
1068 "connection", connection,
1069 "client", panel->priv->client,
1070 NULL);
1071 g_signal_connect_object (net_vpn, "removed",
1072 G_CALLBACK (object_removed_cb), panel, 0);
1073
1074 /* add as a panel */
1075 notebook = GTK_NOTEBOOK (gtk_builder_get_object (panel->priv->builder,
1076 "notebook_types"));
1077 size_group = GTK_SIZE_GROUP (gtk_builder_get_object (panel->priv->builder,
1078 "sizegroup1"));
1079 net_object_add_to_notebook (NET_OBJECT (net_vpn),
1080 notebook,
1081 size_group);
1082
1083 liststore_devices = GTK_LIST_STORE (gtk_builder_get_object (panel->priv->builder,
1084 "liststore_devices"));
1085 title = g_strdup_printf (_("%s VPN"), nm_connection_get_id (connection));
1086
1087 net_object_set_title (NET_OBJECT (net_vpn), title);
1088 gtk_list_store_append (liststore_devices, &iter);
1089 gtk_list_store_set (liststore_devices,
1090 &iter,
1091 PANEL_DEVICES_COLUMN_ICON, "network-vpn-symbolic",
1092 PANEL_DEVICES_COLUMN_OBJECT, net_vpn,
1093 -1);
1094 g_signal_connect (net_vpn, "notify::title",
1095 G_CALLBACK (panel_net_object_notify_title_cb), panel);
1096
1097 g_free (title);
1098 g_object_unref (net_vpn);
1099 }
1100
1101 static void
add_connection(CcNetworkPanel * panel,NMConnection * connection)1102 add_connection (CcNetworkPanel *panel,
1103 NMConnection *connection)
1104 {
1105 NMSettingConnection *s_con;
1106 const gchar *type, *iface;
1107
1108 s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection,
1109 NM_TYPE_SETTING_CONNECTION));
1110 type = nm_setting_connection_get_connection_type (s_con);
1111 iface = nm_connection_get_interface_name (connection);
1112 if (g_strcmp0 (type, "vpn") != 0 && iface == NULL)
1113 return;
1114
1115 /* Don't add the libvirtd bridge to the UI */
1116 if (g_strcmp0 (nm_setting_connection_get_interface_name (s_con), "virbr0") == 0)
1117 return;
1118
1119 g_debug ("add %s/%s remote connection: %s",
1120 type, g_type_name_from_instance ((GTypeInstance*)connection),
1121 nm_connection_get_path (connection));
1122 if (!iface)
1123 panel_add_vpn_device (panel, connection);
1124 }
1125
1126 static void
notify_connection_added_cb(NMClient * client,NMRemoteConnection * connection,CcNetworkPanel * panel)1127 notify_connection_added_cb (NMClient *client,
1128 NMRemoteConnection *connection,
1129 CcNetworkPanel *panel)
1130 {
1131 add_connection (panel, NM_CONNECTION (connection));
1132 }
1133
1134 static void
panel_check_network_manager_version(CcNetworkPanel * panel)1135 panel_check_network_manager_version (CcNetworkPanel *panel)
1136 {
1137 GtkWidget *box;
1138 GtkWidget *label;
1139 gchar *markup;
1140 const gchar *version;
1141
1142 /* parse running version */
1143 version = nm_client_get_version (panel->priv->client);
1144 if (version == NULL) {
1145 gtk_container_remove (GTK_CONTAINER (panel), gtk_bin_get_child (GTK_BIN (panel)));
1146
1147 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 20);
1148 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1149 gtk_widget_set_vexpand (box, TRUE);
1150 gtk_container_add (GTK_CONTAINER (panel), box);
1151
1152 label = gtk_label_new (_("Oops, something has gone wrong. Please contact your software vendor."));
1153 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1154 gtk_widget_set_valign (label, GTK_ALIGN_END);
1155 gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
1156
1157 markup = g_strdup_printf ("<small><tt>%s</tt></small>",
1158 _("NetworkManager needs to be running."));
1159 label = gtk_label_new (NULL);
1160 gtk_label_set_markup (GTK_LABEL (label), markup);
1161 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1162 gtk_widget_set_valign (label, GTK_ALIGN_START);
1163 gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
1164
1165 gtk_widget_show_all (box);
1166 g_free (markup);
1167 } else {
1168 manager_running (panel->priv->client, NULL, panel);
1169 }
1170 }
1171
1172 static void
editor_done(NetConnectionEditor * editor,gboolean success,gpointer user_data)1173 editor_done (NetConnectionEditor *editor,
1174 gboolean success,
1175 gpointer user_data)
1176 {
1177 g_object_unref (editor);
1178 }
1179
1180 static void
add_connection_cb(GtkToolButton * button,CcNetworkPanel * panel)1181 add_connection_cb (GtkToolButton *button, CcNetworkPanel *panel)
1182 {
1183 NetConnectionEditor *editor;
1184 GtkWindow *toplevel;
1185
1186 toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
1187 editor = net_connection_editor_new (toplevel, NULL, NULL, NULL,
1188 panel->priv->client);
1189 g_signal_connect (editor, "done", G_CALLBACK (editor_done), panel);
1190 net_connection_editor_run (editor);
1191 }
1192
1193 static void
remove_connection(GtkToolButton * button,CcNetworkPanel * panel)1194 remove_connection (GtkToolButton *button, CcNetworkPanel *panel)
1195 {
1196 NetObject *object;
1197
1198 /* get current device */
1199 object = get_selected_object (panel);
1200 if (object == NULL)
1201 return;
1202
1203 /* delete the object */
1204 net_object_delete (object);
1205 g_object_unref (object);
1206 }
1207
1208 static void
on_toplevel_map(GtkWidget * widget,CcNetworkPanel * panel)1209 on_toplevel_map (GtkWidget *widget,
1210 CcNetworkPanel *panel)
1211 {
1212 /* is the user compiling against a new version, but not running
1213 * the daemon? */
1214 panel_check_network_manager_version (panel);
1215 }
1216
1217 static void
cc_network_panel_init(CcNetworkPanel * panel)1218 cc_network_panel_init (CcNetworkPanel *panel)
1219 {
1220 GError *error = NULL;
1221 GtkStyleContext *context;
1222 GtkTreeSelection *selection;
1223 GtkWidget *widget;
1224 GtkWidget *toplevel;
1225 GDBusConnection *system_bus;
1226 GtkCssProvider *provider;
1227 const GPtrArray *connections;
1228 guint i;
1229
1230 panel->priv = NETWORK_PANEL_PRIVATE (panel);
1231 g_resources_register (cc_network_get_resource ());
1232
1233 panel->priv->builder = gtk_builder_new ();
1234 gtk_builder_add_from_resource (panel->priv->builder,
1235 "/org/cinnamon/control-center/network/network.ui",
1236 &error);
1237 if (error != NULL) {
1238 g_warning ("Could not load interface file: %s", error->message);
1239 g_error_free (error);
1240 return;
1241 }
1242
1243 #ifdef HAVE_NMA_18
1244 /* some newer VPN plugins pre-require internal resources from libnma */
1245 /* this solution is really ugly, but works clean */
1246 gtk_widget_destroy (nma_cert_chooser_new ("dummy", NMA_CERT_CHOOSER_FLAG_NONE));
1247 #endif
1248
1249 panel->priv->cancellable = g_cancellable_new ();
1250
1251 panel->priv->treeview = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
1252 "treeview_devices"));
1253 panel_add_devices_columns (panel, GTK_TREE_VIEW (panel->priv->treeview));
1254 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->priv->treeview));
1255 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1256 g_signal_connect (selection, "changed",
1257 G_CALLBACK (nm_devices_treeview_clicked_cb), panel);
1258
1259 widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
1260 "devices_scrolledwindow"));
1261 gtk_widget_set_size_request (widget, 200, -1);
1262 context = gtk_widget_get_style_context (widget);
1263 gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
1264
1265 widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
1266 "devices_toolbar"));
1267 context = gtk_widget_get_style_context (widget);
1268 gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
1269
1270 /* add the virtual proxy device */
1271 panel_add_proxy_device (panel);
1272
1273 /* use NetworkManager client */
1274 panel->priv->client = nm_client_new (NULL, NULL);
1275 g_signal_connect (panel->priv->client, "notify::nm-running" ,
1276 G_CALLBACK (manager_running), panel);
1277 g_signal_connect (panel->priv->client, "notify::active-connections",
1278 G_CALLBACK (active_connections_changed), panel);
1279 g_signal_connect (panel->priv->client, "device-added",
1280 G_CALLBACK (device_added_cb), panel);
1281 g_signal_connect (panel->priv->client, "device-removed",
1282 G_CALLBACK (device_removed_cb), panel);
1283
1284 #ifdef BUILD_MODEM
1285 /* Setup ModemManager client */
1286 system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
1287 if (system_bus == NULL) {
1288 g_warning ("Error connecting to system D-Bus: %s",
1289 error->message);
1290 g_clear_error (&error);
1291 } else {
1292 panel->priv->modem_manager = mm_manager_new_sync (system_bus,
1293 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
1294 NULL,
1295 &error);
1296 if (panel->priv->modem_manager == NULL) {
1297 g_warning ("Error connecting to ModemManager: %s",
1298 error->message);
1299 g_clear_error (&error);
1300 }
1301 g_object_unref (system_bus);
1302 }
1303 #else
1304 panel->priv->modem_manager = NULL;
1305 #endif
1306
1307 widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
1308 "add_toolbutton"));
1309 g_signal_connect (widget, "clicked",
1310 G_CALLBACK (add_connection_cb), panel);
1311
1312 /* disable for now, until we actually show removable connections */
1313 widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
1314 "remove_toolbutton"));
1315 g_signal_connect (widget, "clicked",
1316 G_CALLBACK (remove_connection), panel);
1317
1318 /* add remote settings such as VPN settings as virtual devices */
1319 g_signal_connect (panel->priv->client, NM_CLIENT_CONNECTION_ADDED,
1320 G_CALLBACK (notify_connection_added_cb), panel);
1321
1322 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (panel));
1323 g_signal_connect_after (toplevel, "map", G_CALLBACK (on_toplevel_map), panel);
1324
1325 /* hide implementation details */
1326 widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
1327 "notebook_types"));
1328 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
1329
1330 widget = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder,
1331 "vbox1"));
1332 gtk_container_add (GTK_CONTAINER (panel), widget);
1333
1334 provider = gtk_css_provider_new ();
1335 gtk_css_provider_load_from_data (provider, ".circular-button { border-radius: 20px; -gtk-outline-radius: 20px; }", -1, NULL);
1336 gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
1337 GTK_STYLE_PROVIDER (provider),
1338 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1339 g_object_unref (provider);
1340
1341 /* Cold-plug existing connections */
1342 connections = nm_client_get_connections (panel->priv->client);
1343 if (connections) {
1344 for (i = 0; i < connections->len; i++)
1345 add_connection (panel, connections->pdata[i]);
1346 }
1347
1348 g_debug ("Calling handle_argv() after cold-plugging connections");
1349 handle_argv (panel);
1350 }
1351
1352 void
cc_network_panel_register(GIOModule * module)1353 cc_network_panel_register (GIOModule *module)
1354 {
1355 textdomain (GETTEXT_PACKAGE);
1356 bindtextdomain (GETTEXT_PACKAGE, "/usr/share/locale");
1357 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1358 cc_network_panel_register_type (G_TYPE_MODULE (module));
1359 g_io_extension_point_implement (CC_SHELL_PANEL_EXTENSION_POINT,
1360 CC_TYPE_NETWORK_PANEL,
1361 "network", 0);
1362 }
1363