network: Add connections and devices to different stack

The current Network panel is composed of a single stack and
a treeview to select the currently visible stack page. Each
stack page represents a connection or device.

The new Network panel, however, has none of the concept of
selectable pages. In the new layout, all connections and
devices appear all at once in a more compact and simpler
fashion.

This commit, then, starts moving towards a unified, pageless
panel by adding all the connections and devices to different
stacks. These different stacks are transient to the network
object, and are added at appropriate boxes, giving the panel
a unified layout.

This has some serious implications in the design of the
current code. Most of the code removals were related to the
treeview and different pages handling. No more tree model
madness is present, and the devices are now stored in a
plain simple GPtrArray.

After this patch, NetObject:add_to_stack isn't a good code
design choice anymore. This will be addressed in a future
patch.

https://bugzilla.gnome.org/show_bug.cgi?id=785581
This commit is contained in:
Georges Basile Stavracas Neto 2017-07-15 21:24:07 -03:00 committed by Rui Matos
parent f7bdd3c969
commit e35ecd5468
2 changed files with 103 additions and 501 deletions

View file

@ -54,15 +54,17 @@ struct _CcNetworkPanel
CcPanel parent;
GCancellable *cancellable;
GtkListStore *liststore_devices;
GHashTable *device_to_stack;
GPtrArray *devices;
NMClient *client;
MMManager *modem_manager;
GtkSizeGroup *sizegroup;
gboolean updating_device;
/* widgets */
GtkStack *stack;
GtkWidget *treeview;
GtkWidget *box_proxy;
GtkWidget *box_vpn;
GtkWidget *box_wired;
/* wireless dialog stuff */
CmdlineOperation arg_operation;
@ -82,7 +84,7 @@ enum {
PROP_PARAMETERS
};
static NetObject *find_in_model_by_id (CcNetworkPanel *panel, const gchar *id, GtkTreeIter *iter_out);
static NetObject *find_net_object_by_id (CcNetworkPanel *panel, const gchar *id);
static void handle_argv (CcNetworkPanel *panel);
CC_PANEL_REGISTER (CcNetworkPanel, cc_network_panel)
@ -210,6 +212,9 @@ cc_network_panel_dispose (GObject *object)
g_clear_object (&self->client);
g_clear_object (&self->modem_manager);
g_clear_pointer (&self->device_to_stack, g_hash_table_destroy);
g_clear_pointer (&self->devices, g_ptr_array_unref);
G_OBJECT_CLASS (cc_network_panel_parent_class)->dispose (object);
}
@ -229,175 +234,37 @@ cc_network_panel_get_help_uri (CcPanel *panel)
return "help:gnome-help/net";
}
static NetObject *
get_selected_object (CcNetworkPanel *panel)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
NetObject *object = NULL;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->treeview));
if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
return NULL;
}
gtk_tree_model_get (model, &iter,
PANEL_DEVICES_COLUMN_OBJECT, &object,
-1);
return object;
}
static void
select_first_device (CcNetworkPanel *panel)
{
GtkTreePath *path;
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->treeview));
/* select the first device */
path = gtk_tree_path_new_from_string ("0");
gtk_tree_selection_select_path (selection, path);
gtk_tree_path_free (path);
}
static void
select_tree_iter (CcNetworkPanel *panel, GtkTreeIter *iter)
{
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->treeview));
gtk_tree_selection_select_iter (selection, iter);
}
static void
object_removed_cb (NetObject *object, CcNetworkPanel *panel)
{
gboolean ret;
NetObject *object_tmp;
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkWidget *stack;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->treeview));
/* remove device from model */
model = GTK_TREE_MODEL (panel->liststore_devices);
ret = gtk_tree_model_get_iter_first (model, &iter);
if (!ret)
return;
/* get the other elements */
do {
gtk_tree_model_get (model, &iter,
PANEL_DEVICES_COLUMN_OBJECT, &object_tmp,
-1);
if (g_strcmp0 (net_object_get_id (object),
net_object_get_id (object_tmp)) == 0) {
g_object_unref (object_tmp);
if (gtk_list_store_remove (GTK_LIST_STORE (model), &iter)) {
if (gtk_tree_model_get_iter_first (model, &iter))
gtk_tree_selection_select_iter (selection, &iter);
}
break;
}
g_object_unref (object_tmp);
} while (gtk_tree_model_iter_next (model, &iter));
/* remove device */
stack = g_hash_table_lookup (panel->device_to_stack, object);
if (stack != NULL)
gtk_widget_destroy (stack);
}
GPtrArray *
cc_network_panel_get_devices (CcNetworkPanel *panel)
{
GPtrArray *devices;
GtkTreeModel *model;
GtkTreeIter iter;
NetObject *object;
guint i;
g_return_val_if_fail (CC_IS_NETWORK_PANEL (panel), NULL);
devices = g_ptr_array_new_with_free_func (g_object_unref);
model = GTK_TREE_MODEL (panel->liststore_devices);
if (!gtk_tree_model_get_iter_first (model, &iter))
return devices;
for (i = 0; i < panel->devices->len; i++) {
NetObject *object = g_ptr_array_index (panel->devices, i);
do {
gtk_tree_model_get (model, &iter,
PANEL_DEVICES_COLUMN_OBJECT, &object,
-1);
if (NET_IS_DEVICE (object))
g_ptr_array_add (devices, object);
else
g_object_unref (object);
} while (gtk_tree_model_iter_next (model, &iter));
if (!NET_IS_DEVICE (object))
continue;
return devices;
}
static gint
panel_net_object_get_sort_category (NetObject *net_object)
{
if (NET_IS_DEVICE (net_object)) {
return panel_device_get_sort_category (net_device_get_nm_device (NET_DEVICE (net_object)));
} else if (NET_IS_PROXY (net_object)) {
return 9;
} else if (NET_IS_VPN (net_object)) {
return 5;
g_ptr_array_add (devices, g_object_ref (object));
}
g_assert_not_reached ();
}
static gint
panel_net_object_sort_func (GtkTreeModel *model, GtkTreeIter *a,
GtkTreeIter *b, void *data)
{
g_autoptr(NetObject) obj_a = NULL;
g_autoptr(NetObject) obj_b = NULL;
gint cat_a, cat_b;
const char *title_a, *title_b;
gtk_tree_model_get (model, a,
PANEL_DEVICES_COLUMN_OBJECT, &obj_a,
-1);
gtk_tree_model_get (model, b,
PANEL_DEVICES_COLUMN_OBJECT, &obj_b,
-1);
cat_a = panel_net_object_get_sort_category (obj_a);
cat_b = panel_net_object_get_sort_category (obj_b);
if (cat_a != cat_b)
return cat_a - cat_b;
title_a = net_object_get_title (obj_a);
title_b = net_object_get_title (obj_b);
if (title_a == title_b)
return 0;
if (title_a == NULL)
return -1;
if (title_b == NULL)
return 1;
return g_utf8_collate (title_a, title_b);
}
static void
panel_net_object_notify_title_cb (NetObject *net_object, GParamSpec *pspec, CcNetworkPanel *panel)
{
GtkTreeIter iter;
if (!find_in_model_by_id (panel, net_object_get_id (net_object), &iter))
return;
/* gtk_tree_model_row_changed would not cause the list store to resort.
* Instead set the object column to the current value.
* See https://bugzilla.gnome.org/show_bug.cgi?id=782737 */
gtk_list_store_set (panel->liststore_devices, &iter,
PANEL_DEVICES_COLUMN_OBJECT, net_object,
-1);
return devices;
}
static void
@ -440,8 +307,7 @@ panel_refresh_device_titles (CcNetworkPanel *panel)
static gboolean
handle_argv_for_device (CcNetworkPanel *self,
NMDevice *device,
GtkTreeIter *iter)
NMDevice *device)
{
GtkWidget *toplevel = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)));
@ -453,10 +319,8 @@ handle_argv_for_device (CcNetworkPanel *self,
cc_network_panel_connect_to_3g_network (toplevel, self->client, device);
reset_command_line_args (self); /* done */
select_tree_iter (self, iter);
return TRUE;
} else if (self->arg_operation == OPERATION_SHOW_DEVICE) {
select_tree_iter (self, iter);
reset_command_line_args (self); /* done */
return TRUE;
}
@ -467,8 +331,7 @@ handle_argv_for_device (CcNetworkPanel *self,
static gboolean
handle_argv_for_connection (CcNetworkPanel *panel,
NMConnection *connection,
GtkTreeIter *iter)
NMConnection *connection)
{
if (panel->arg_operation == OPERATION_NULL)
return TRUE;
@ -477,7 +340,6 @@ handle_argv_for_connection (CcNetworkPanel *panel,
if (g_strcmp0 (nm_connection_get_path (connection), panel->arg_device) == 0) {
reset_command_line_args (panel);
select_tree_iter (panel, iter);
return TRUE;
}
@ -488,31 +350,26 @@ handle_argv_for_connection (CcNetworkPanel *panel,
static void
handle_argv (CcNetworkPanel *panel)
{
GtkTreeModel *model;
GtkTreeIter iter;
gboolean ret;
gint i;
if (panel->arg_operation == OPERATION_NULL)
return;
model = GTK_TREE_MODEL (panel->liststore_devices);
ret = gtk_tree_model_get_iter_first (model, &iter);
while (ret) {
for (i = 0; i < panel->devices->len; i++) {
GObject *object_tmp;
NMDevice *device;
NMConnection *connection;
gboolean done = FALSE;
gtk_tree_model_get (model, &iter,
PANEL_DEVICES_COLUMN_OBJECT, &object_tmp,
-1);
object_tmp = g_ptr_array_index (panel->devices, i);
if (NET_IS_DEVICE (object_tmp)) {
g_object_get (object_tmp, "nm-device", &device, NULL);
done = handle_argv_for_device (panel, device, &iter);
done = handle_argv_for_device (panel, device);
g_object_unref (device);
} else if (NET_IS_VPN (object_tmp)) {
g_object_get (object_tmp, "connection", &connection, NULL);
done = handle_argv_for_connection (panel, connection, &iter);
done = handle_argv_for_connection (panel, connection);
g_object_unref (connection);
}
@ -520,47 +377,40 @@ handle_argv (CcNetworkPanel *panel)
if (done)
return;
ret = gtk_tree_model_iter_next (model, &iter);
}
g_debug ("Could not handle argv operation, no matching device yet?");
}
static void
state_changed_cb (NMDevice *device,
NMDeviceState new_state,
NMDeviceState old_state,
NMDeviceStateReason reason,
CcNetworkPanel *panel)
static GtkWidget *
add_device_stack (CcNetworkPanel *self, NetObject *object)
{
GtkTreeIter iter;
GtkWidget *stack;
if (!find_in_model_by_id (panel, nm_device_get_udi (device), &iter)) {
return;
}
stack = gtk_stack_new ();
gtk_widget_show (stack);
g_hash_table_insert (self->device_to_stack, object, stack);
gtk_list_store_set (GTK_LIST_STORE (panel->liststore_devices), &iter,
PANEL_DEVICES_COLUMN_ICON, panel_device_to_icon_name (device, TRUE),
-1);
net_object_add_to_stack (object, GTK_STACK (stack), self->sizegroup);
return stack;
}
static gboolean
static void
panel_add_device (CcNetworkPanel *panel, NMDevice *device)
{
GtkTreeIter iter;
NMDeviceType type;
NetDevice *net_device;
GType device_g_type;
const char *udi;
if (!nm_device_get_managed (device))
goto out;
return;
/* do we have an existing object with this id? */
udi = nm_device_get_udi (device);
if (find_in_model_by_id (panel, udi, NULL) != NULL)
goto out;
if (find_net_object_by_id (panel, udi) != NULL)
return;
type = nm_device_get_device_type (device);
@ -586,7 +436,7 @@ panel_add_device (CcNetworkPanel *panel, NMDevice *device)
case NM_DEVICE_TYPE_BRIDGE:
/* Don't add VPN devices */
case NM_DEVICE_TYPE_TUN:
goto out;
return;
default:
device_g_type = NET_TYPE_DEVICE_SIMPLE;
break;
@ -609,7 +459,7 @@ panel_add_device (CcNetworkPanel *panel, NMDevice *device)
if (panel->modem_manager == NULL) {
g_warning ("Cannot grab information for modem at %s: No ModemManager support",
nm_device_get_udi (device));
goto out;
return;
}
modem_object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (panel->modem_manager),
@ -617,7 +467,7 @@ panel_add_device (CcNetworkPanel *panel, NMDevice *device)
if (modem_object == NULL) {
g_warning ("Cannot grab information for modem at %s: Not found",
nm_device_get_udi (device));
goto out;
return;
}
/* Set the modem object in the NetDeviceMobile */
@ -628,164 +478,52 @@ panel_add_device (CcNetworkPanel *panel, NMDevice *device)
}
/* add as a panel */
if (device_g_type != NET_TYPE_DEVICE)
net_object_add_to_stack (NET_OBJECT (net_device), panel->stack, panel->sizegroup);
if (device_g_type != NET_TYPE_DEVICE) {
GtkWidget *stack;
stack = add_device_stack (panel, NET_OBJECT (net_device));
gtk_container_add (GTK_CONTAINER (panel->box_wired), stack);
}
/* Add to the devices array */
g_ptr_array_add (panel->devices, net_device);
g_signal_connect_object (net_device, "removed",
G_CALLBACK (object_removed_cb), panel, 0);
gtk_list_store_append (panel->liststore_devices, &iter);
gtk_list_store_set (panel->liststore_devices,
&iter,
PANEL_DEVICES_COLUMN_ICON, panel_device_to_icon_name (device, TRUE),
PANEL_DEVICES_COLUMN_OBJECT, net_device,
-1);
g_signal_connect (net_device, "notify::title",
G_CALLBACK (panel_net_object_notify_title_cb), panel);
g_object_unref (net_device);
g_signal_connect (device, "state-changed",
G_CALLBACK (state_changed_cb), panel);
out:
return FALSE;
}
static void
panel_remove_device (CcNetworkPanel *panel, NMDevice *device)
{
gboolean ret;
NetObject *object_tmp;
GtkTreeIter iter;
GtkTreeModel *model;
/* remove device from model */
model = GTK_TREE_MODEL (panel->liststore_devices);
ret = gtk_tree_model_get_iter_first (model, &iter);
if (!ret)
return;
/* get the other elements */
do {
gtk_tree_model_get (model, &iter,
PANEL_DEVICES_COLUMN_OBJECT, &object_tmp,
-1);
if (g_strcmp0 (net_object_get_id (object_tmp),
nm_device_get_udi (device)) == 0) {
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
g_object_unref (object_tmp);
break;
}
g_object_unref (object_tmp);
} while (gtk_tree_model_iter_next (model, &iter));
}
static void
get_object_title (GtkTreeViewColumn *column,
GtkCellRenderer *cell,
GtkTreeModel *model,
GtkTreeIter *iter,
gpointer data)
{
NetObject *object;
gtk_tree_model_get (model, iter,
PANEL_DEVICES_COLUMN_OBJECT, &object,
-1);
if (!object)
/* remove device from array */
object = find_net_object_by_id (panel, nm_device_get_udi (device));
if (object == NULL)
return;
g_object_set (cell, "text", net_object_get_title (object), NULL);
g_object_unref (object);
}
static void
panel_add_devices_columns (CcNetworkPanel *panel, GtkTreeView *treeview)
{
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
/* image */
renderer = gtk_cell_renderer_pixbuf_new ();
g_object_set (renderer,
"width", 32,
"xalign", 1.0,
"stock-size", GTK_ICON_SIZE_MENU,
"follow-state", TRUE,
NULL);
gtk_cell_renderer_set_padding (renderer, 4, 10);
column = gtk_tree_view_column_new_with_attributes ("icon", renderer,
"icon-name", PANEL_DEVICES_COLUMN_ICON,
NULL);
gtk_tree_view_append_column (treeview, column);
/* column for text */
renderer = gtk_cell_renderer_text_new ();
g_object_set (renderer,
"wrap-mode", PANGO_WRAP_WORD,
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
column = gtk_tree_view_column_new_with_attributes ("title", renderer, NULL);
gtk_tree_view_column_set_cell_data_func (GTK_TREE_VIEW_COLUMN (column),
renderer,
get_object_title,
NULL, NULL);
gtk_tree_view_column_set_sort_column_id (column, PANEL_DEVICES_COLUMN_OBJECT);
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (panel->liststore_devices),
PANEL_DEVICES_COLUMN_OBJECT,
panel_net_object_sort_func, NULL, NULL);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (panel->liststore_devices),
PANEL_DEVICES_COLUMN_OBJECT,
GTK_SORT_ASCENDING);
gtk_tree_view_append_column (treeview, column);
gtk_tree_view_column_set_expand (column, TRUE);
}
static void
nm_devices_treeview_clicked_cb (GtkTreeSelection *selection, CcNetworkPanel *panel)
{
const gchar *needle;
GtkTreeIter iter;
GtkTreeModel *model;
NetObject *object = NULL;
if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
g_debug ("no row selected");
return;
}
/* find the widget in the stack that matches the object ID */
object = get_selected_object (panel);
needle = net_object_get_id (object);
gtk_stack_set_visible_child_name (panel->stack, needle);
g_object_unref (object);
g_ptr_array_remove (panel->devices, object);
}
static void
panel_add_proxy_device (CcNetworkPanel *panel)
{
GtkTreeIter iter;
GtkWidget *stack;
NetProxy *proxy;
/* add proxy to stack */
proxy = net_proxy_new ();
net_object_add_to_stack (NET_OBJECT (proxy), panel->stack, panel->sizegroup);
/* add proxy to stack */
stack = add_device_stack (panel, NET_OBJECT (proxy));
gtk_container_add (GTK_CONTAINER (panel->box_proxy), stack);
/* add proxy to device list */
net_object_set_title (NET_OBJECT (proxy), _("Network proxy"));
gtk_list_store_append (panel->liststore_devices, &iter);
gtk_list_store_set (panel->liststore_devices,
&iter,
PANEL_DEVICES_COLUMN_ICON, "preferences-system-network-symbolic",
PANEL_DEVICES_COLUMN_OBJECT, proxy,
-1);
/* NOTE: No connect to notify::title here as it is guaranteed to not
* be changed by anyone.*/
g_object_unref (proxy);
g_ptr_array_add (panel->devices, proxy);
}
static void
@ -844,13 +582,11 @@ manager_running (NMClient *client, GParamSpec *pspec, gpointer user_data)
const GPtrArray *devices;
int i;
NMDevice *device_tmp;
gboolean selected = FALSE;
CcNetworkPanel *panel = CC_NETWORK_PANEL (user_data);
/* clear all devices we added */
if (!nm_client_get_nm_running (client)) {
g_debug ("NM disappeared");
gtk_list_store_clear (panel->liststore_devices);
panel_add_proxy_device (panel);
goto out;
}
@ -863,14 +599,9 @@ manager_running (NMClient *client, GParamSpec *pspec, gpointer user_data)
}
for (i = 0; i < devices->len; i++) {
device_tmp = g_ptr_array_index (devices, i);
selected = panel_add_device (panel, device_tmp) || selected;
panel_add_device (panel, device_tmp);
}
out:
if (!selected) {
/* select the first device */
select_first_device (panel);
}
panel_refresh_device_titles (panel);
g_debug ("Calling handle_argv() after cold-plugging devices");
@ -878,50 +609,35 @@ out:
}
static NetObject *
find_in_model_by_id (CcNetworkPanel *panel, const gchar *id, GtkTreeIter *iter_out)
find_net_object_by_id (CcNetworkPanel *panel, const gchar *id)
{
gboolean ret;
NetObject *object_tmp;
GtkTreeIter iter;
GtkTreeModel *model;
NetObject *object = NULL;
guint i;
/* find in model */
model = GTK_TREE_MODEL (panel->liststore_devices);
ret = gtk_tree_model_get_iter_first (model, &iter);
if (!ret)
goto out;
for (i = 0; i < panel->devices->len; i++) {
object_tmp = g_ptr_array_index (panel->devices, i);
/* get the other elements */
ret = FALSE;
do {
gtk_tree_model_get (model, &iter,
PANEL_DEVICES_COLUMN_OBJECT, &object_tmp,
-1);
if (object_tmp != NULL) {
g_debug ("got %s", net_object_get_id (object_tmp));
if (g_strcmp0 (net_object_get_id (object_tmp), id) == 0)
object = object_tmp;
g_object_unref (object_tmp);
if (g_strcmp0 (net_object_get_id (object_tmp), id) == 0) {
object = object_tmp;
break;
}
} while (object == NULL && gtk_tree_model_iter_next (model, &iter));
out:
if (iter_out)
*iter_out = iter;
}
return object;
}
static void
panel_add_vpn_device (CcNetworkPanel *panel, NMConnection *connection)
{
GtkWidget *stack;
gchar *title;
GtkTreeIter iter;
NetVpn *net_vpn;
const gchar *id;
/* does already exist */
id = nm_connection_get_path (connection);
if (find_in_model_by_id (panel, id, NULL) != NULL)
if (find_net_object_by_id (panel, id) != NULL)
return;
/* add as a VPN object */
@ -936,22 +652,17 @@ panel_add_vpn_device (CcNetworkPanel *panel, NMConnection *connection)
G_CALLBACK (object_removed_cb), panel, 0);
/* add as a panel */
net_object_add_to_stack (NET_OBJECT (net_vpn), panel->stack, panel->sizegroup);
stack = add_device_stack (panel, NET_OBJECT (net_vpn));
gtk_container_add (GTK_CONTAINER (panel->box_vpn), stack);
title = g_strdup_printf (_("%s VPN"), nm_connection_get_id (connection));
net_object_set_title (NET_OBJECT (net_vpn), title);
gtk_list_store_append (panel->liststore_devices, &iter);
gtk_list_store_set (panel->liststore_devices,
&iter,
PANEL_DEVICES_COLUMN_ICON, "network-vpn-symbolic",
PANEL_DEVICES_COLUMN_OBJECT, net_vpn,
-1);
g_signal_connect (net_vpn, "notify::title",
G_CALLBACK (panel_net_object_notify_title_cb), panel);
/* store in the devices array */
g_ptr_array_add (panel->devices, net_vpn);
g_free (title);
g_object_unref (net_vpn);
}
static void
@ -1025,41 +736,6 @@ panel_check_network_manager_version (CcNetworkPanel *panel)
}
}
static void
editor_done (NetConnectionEditor *editor,
gboolean success,
gpointer user_data)
{
g_object_unref (editor);
}
static void
add_connection_cb (GtkToolButton *button, CcNetworkPanel *panel)
{
NetConnectionEditor *editor;
GtkWindow *toplevel;
toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
editor = net_connection_editor_new (toplevel, NULL, NULL, NULL, panel->client);
g_signal_connect (editor, "done", G_CALLBACK (editor_done), panel);
net_connection_editor_run (editor);
}
static void
remove_connection (GtkToolButton *button, CcNetworkPanel *panel)
{
NetObject *object;
/* get current device */
object = get_selected_object (panel);
if (object == NULL)
return;
/* delete the object */
net_object_delete (object);
g_object_unref (object);
}
static void
on_toplevel_map (GtkWidget *widget,
CcNetworkPanel *panel)
@ -1088,20 +764,16 @@ cc_network_panel_class_init (CcNetworkPanelClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/network.ui");
gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, liststore_devices);
gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, stack);
gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_proxy);
gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_vpn);
gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, box_wired);
gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, sizegroup);
gtk_widget_class_bind_template_child (widget_class, CcNetworkPanel, treeview);
gtk_widget_class_bind_template_callback (widget_class, add_connection_cb);
gtk_widget_class_bind_template_callback (widget_class, remove_connection);
}
static void
cc_network_panel_init (CcNetworkPanel *panel)
{
GError *error = NULL;
GtkTreeSelection *selection;
GtkWidget *toplevel;
GDBusConnection *system_bus;
const GPtrArray *connections;
@ -1112,12 +784,8 @@ cc_network_panel_init (CcNetworkPanel *panel)
gtk_widget_init_template (GTK_WIDGET (panel));
panel->cancellable = g_cancellable_new ();
panel_add_devices_columns (panel, GTK_TREE_VIEW (panel->treeview));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->treeview));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
g_signal_connect (selection, "changed",
G_CALLBACK (nm_devices_treeview_clicked_cb), panel);
panel->devices = g_ptr_array_new_with_free_func (g_object_unref);
panel->device_to_stack = g_hash_table_new (g_direct_hash, g_direct_equal);
/* add the virtual proxy device */
panel_add_proxy_device (panel);

View file

@ -41,98 +41,32 @@
<property name="can_focus">False</property>
<property name="spacing">3</property>
<property name="orientation">vertical</property>
<!-- Each GtkBox below will contain GtkStacks from the NetDevices -->
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<object class="GtkBox" id="box_wired">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_start">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkScrolledWindow" id="devices_scrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
<property name="expand">True</property>
<property name="width_request">200</property>
<child>
<object class="GtkTreeView" id="treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">liststore_devices</property>
<property name="headers_visible">False</property>
<property name="search_column">2</property>
<property name="show_expanders">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToolbar" id="devices_toolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="toolbar_style">icons</property>
<property name="show_arrow">False</property>
<property name="icon_size">1</property>
<style>
<class name="inline-toolbar"/>
</style>
<child>
<object class="GtkToolButton" id="add_toolbutton">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Add Device</property>
<property name="use_underline">True</property>
<property name="icon_name">list-add-symbolic</property>
<signal name="clicked" handler="add_connection_cb" object="CcNetworkPanel" swapped="no" />
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="remove_toolbutton">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Remove Device</property>
<property name="use_underline">True</property>
<property name="icon_name">list-remove-symbolic</property>
<signal name="clicked" handler="remove_connection" object="CcNetworkPanel" swapped="no" />
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="stack">
<object class="GtkBox" id="box_vpn">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="transition_type">crossfade</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
</object>
</child>
<child>
<object class="GtkBox" id="box_proxy">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
</object>
</child>
</object>